diff options
693 files changed, 8057 insertions, 4913 deletions
diff --git a/Documentation/arm64/memory.txt b/Documentation/arm64/memory.txt index dbbdcbba75a..4110cca96bd 100644 --- a/Documentation/arm64/memory.txt +++ b/Documentation/arm64/memory.txt @@ -27,17 +27,17 @@ Start			End			Size		Use  -----------------------------------------------------------------------  0000000000000000	0000007fffffffff	 512GB		user -ffffff8000000000	ffffffbbfffcffff	~240GB		vmalloc +ffffff8000000000	ffffffbbfffeffff	~240GB		vmalloc -ffffffbbfffd0000	ffffffbcfffdffff	  64KB		[guard page] +ffffffbbffff0000	ffffffbbffffffff	  64KB		[guard page] -ffffffbbfffe0000	ffffffbcfffeffff	  64KB		PCI I/O space +ffffffbc00000000	ffffffbdffffffff	   8GB		vmemmap -ffffffbbffff0000	ffffffbcffffffff	  64KB		[guard page] +ffffffbe00000000	ffffffbffbbfffff	  ~8GB		[guard, future vmmemap] -ffffffbc00000000	ffffffbdffffffff	   8GB		vmemmap +ffffffbffbe00000	ffffffbffbe0ffff	  64KB		PCI I/O space -ffffffbe00000000	ffffffbffbffffff	  ~8GB		[guard, future vmmemap] +ffffffbbffff0000	ffffffbcffffffff	  ~2MB		[guard]  ffffffbffc000000	ffffffbfffffffff	  64MB		modules diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index ecc81e36871..d187e9f7cf1 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -8,7 +8,7 @@ PIT Timer required properties:    shared across all System Controller members.  TC/TCLIB Timer required properties: -- compatible: Should be "atmel,<chip>-pit". +- compatible: Should be "atmel,<chip>-tcb".    <chip> can be "at91rm9200" or "at91sam9x5"  - reg: Should contain registers location and length  - interrupts: Should contain all interrupts for the TC block diff --git a/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt new file mode 100644 index 00000000000..df70318a617 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt @@ -0,0 +1,19 @@ +* EETI eGalax Multiple Touch Controller + +Required properties: +- compatible: must be "eeti,egalax_ts" +- reg: i2c slave address +- interrupt-parent: the phandle for the interrupt controller +- interrupts: touch controller interrupt +- wakeup-gpios: the gpio pin to be used for waking up the controller +  as well as uased as irq pin + +Example: + +	egalax_ts@04 { +		compatible = "eeti,egalax_ts"; +		reg = <0x04>; +		interrupt-parent = <&gpio1>; +		interrupts = <9 2>; +		wakeup-gpios = <&gpio1 9 0>; +	}; diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt index c8e578263ce..683fde93c4f 100644 --- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt +++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt @@ -93,7 +93,7 @@ Valid values for pin and group names are:      With some exceptions, these support nvidia,high-speed-mode,      nvidia,schmitt, nvidia,low-power-mode, nvidia,pull-down-strength, -    nvidia,pull-up-strength, nvidia,slew_rate-rising, nvidia,slew_rate-falling. +    nvidia,pull-up-strength, nvidia,slew-rate-rising, nvidia,slew-rate-falling.      drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1, drive_cdev2,      drive_csus, drive_dap1, drive_dap2, drive_dap3, drive_dap4, drive_dbg, diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt index c275b70349c..6f426ed7009 100644 --- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt +++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt @@ -83,7 +83,7 @@ Valid values for pin and group names are:    drive groups:      These all support nvidia,pull-down-strength, nvidia,pull-up-strength, -    nvidia,slew_rate-rising, nvidia,slew_rate-falling. Most but not all +    nvidia,slew-rate-rising, nvidia,slew-rate-falling. Most but not all      support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode.      ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, cec, crt, csus, dap1, diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README index 7eceaff63f5..815b711bcd8 100644 --- a/Documentation/firmware_class/README +++ b/Documentation/firmware_class/README @@ -18,32 +18,40 @@   High level behavior (mixed):   ============================ - kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device) + 1), kernel(driver): +	- calls request_firmware(&fw_entry, $FIRMWARE, device) +	- kernel searchs the fimware image with name $FIRMWARE directly +	in the below search path of root filesystem: +		"/lib/firmware/updates/" UTS_RELEASE, +		"/lib/firmware/updates", +		"/lib/firmware/" UTS_RELEASE, +		"/lib/firmware" +	- If found, goto 7), else goto 2) - userspace: + 2), userspace:   	- /sys/class/firmware/xxx/{loading,data} appear.  	- hotplug gets called with a firmware identifier in $FIRMWARE  	  and the usual hotplug environment.  		- hotplug: echo 1 > /sys/class/firmware/xxx/loading - kernel: Discard any previous partial load. + 3), kernel: Discard any previous partial load. - userspace: + 4), userspace:  		- hotplug: cat appropriate_firmware_image > \  					/sys/class/firmware/xxx/data - kernel: grows a buffer in PAGE_SIZE increments to hold the image as it + 5), kernel: grows a buffer in PAGE_SIZE increments to hold the image as it  	 comes in. - userspace: + 6), userspace:  		- hotplug: echo 0 > /sys/class/firmware/xxx/loading - kernel: request_firmware() returns and the driver has the firmware + 7), kernel: request_firmware() returns and the driver has the firmware  	 image in fw_entry->{data,size}. If something went wrong  	 request_firmware() returns non-zero and fw_entry is set to  	 NULL. - kernel(driver): Driver code calls release_firmware(fw_entry) releasing + 8), kernel(driver): Driver code calls release_firmware(fw_entry) releasing  		 the firmware image and any related resource.   High level behavior (driver code): diff --git a/Documentation/hwmon/fam15h_power b/Documentation/hwmon/fam15h_power index a92918e0bd6..80654813d04 100644 --- a/Documentation/hwmon/fam15h_power +++ b/Documentation/hwmon/fam15h_power @@ -10,7 +10,7 @@ Supported chips:    BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors      (not yet published) -Author: Andreas Herrmann <andreas.herrmann3@amd.com> +Author: Andreas Herrmann <herrmann.der.user@googlemail.com>  Description  ----------- diff --git a/Documentation/zh_CN/IRQ.txt b/Documentation/zh_CN/IRQ.txt new file mode 100644 index 00000000000..956026d5cf8 --- /dev/null +++ b/Documentation/zh_CN/IRQ.txt @@ -0,0 +1,39 @@ +Chinese translated version of Documentation/IRQ.txt + +If you have any comment or update to the content, please contact the +original document maintainer directly.  However, if you have a problem +communicating in English you can also ask the Chinese maintainer for +help.  Contact the Chinese maintainer if this translation is outdated +or if there is a problem with the translation. + +Maintainer: Eric W. Biederman <ebiederman@xmission.com> +Chinese maintainer: Fu Wei <tekkamanninja@gmail.com> +--------------------------------------------------------------------- +Documentation/IRQ.txt 的中文翻译 + +如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 +交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 +译存在问题,请联系中文版维护者。 +英文版维护者: Eric W. Biederman <ebiederman@xmission.com> +中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com> +中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> +中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> + + +以下为正文 +--------------------------------------------------------------------- +何为 IRQ? + +一个 IRQ 是来自某个设备的一个中断请求。目前,它们可以来自一个硬件引脚, +或来自一个数据包。多个设备可能连接到同个硬件引脚,从而共享一个 IRQ。 + +一个 IRQ 编号是用于告知硬件中断源的内核标识。通常情况下,这是一个 +全局 irq_desc 数组的索引,但是除了在 linux/interrupt.h 中的实现, +具体的细节是体系结构特定的。 + +一个 IRQ 编号是设备上某个可能的中断源的枚举。通常情况下,枚举的编号是 +该引脚在系统内中断控制器的所有输入引脚中的编号。对于 ISA 总线中的情况, +枚举的是在两个 i8259 中断控制器中 16 个输入引脚。 + +架构可以对 IRQ 编号指定额外的含义,在硬件涉及任何手工配置的情况下, +是被提倡的。ISA 的 IRQ 是一个分配这类额外含义的典型例子。 diff --git a/Documentation/zh_CN/arm64/booting.txt b/Documentation/zh_CN/arm64/booting.txt new file mode 100644 index 00000000000..28fa325b746 --- /dev/null +++ b/Documentation/zh_CN/arm64/booting.txt @@ -0,0 +1,156 @@ +Chinese translated version of Documentation/arm64/booting.txt + +If you have any comment or update to the content, please contact the +original document maintainer directly.  However, if you have a problem +communicating in English you can also ask the Chinese maintainer for +help.  Contact the Chinese maintainer if this translation is outdated +or if there is a problem with the translation. + +Maintainer: Will Deacon <will.deacon@arm.com> +Chinese maintainer: Fu Wei <tekkamanninja@gmail.com> +--------------------------------------------------------------------- +Documentation/arm64/booting.txt 的中文翻译 + +如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 +交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 +译存在问题,请联系中文版维护者。 + +英文版维护者: Will Deacon <will.deacon@arm.com> +中文版维护者: 傅炜  Fu Wei <tekkamanninja@gmail.com> +中文版翻译者: 傅炜  Fu Wei <tekkamanninja@gmail.com> +中文版校译者: 傅炜  Fu Wei <tekkamanninja@gmail.com> + +以下为正文 +--------------------------------------------------------------------- +			启动 AArch64 Linux +			================== + +作者: Will Deacon <will.deacon@arm.com> +日期: 2012 年 09 月 07 日 + +本文档基于 Russell King 的 ARM 启动文档,且适用于所有公开发布的 +AArch64 Linux 内核代码。 + +AArch64 异常模型由多个异常级别(EL0 - EL3)组成,对于 EL0 和 EL1 +异常级有对应的安全和非安全模式。EL2 是系统管理级,且仅存在于 +非安全模式下。EL3 是最高特权级,且仅存在于安全模式下。 + +基于本文档的目的,我们将简单地使用‘引导装载程序’(‘boot loader’) +这个术语来定义在将控制权交给 Linux 内核前 CPU 上执行的所有软件。 +这可能包含安全监控和系统管理代码,或者它可能只是一些用于准备最小启动 +环境的指令。 + +基本上,引导装载程序(至少)应实现以下操作: + +1、设置和初始化 RAM +2、设置设备树数据 +3、解压内核映像 +4、调用内核映像 + + +1、设置和初始化 RAM +----------------- + +必要性: 强制 + +引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。 +这个操作的执行是设备依赖的。(它可能使用内部算法来自动定位和计算所有 +RAM,或可能使用对这个设备已知的 RAM 信息,还可能使用任何引导装载程序 +设计者想到的匹配方法。) + + +2、设置设备树数据 +--------------- + +必要性: 强制 + +设备树数据块(dtb)大小必须不大于 2 MB,且位于从内核映像起始算起第一个 +512MB 内的 2MB 边界上。这使得内核可以通过初始页表中的单个节描述符来 +映射此数据块。 + + +3、解压内核映像 +------------- + +必要性: 可选 + +AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内核映像文件 +(比如 Image.gz),则需要通过引导装载程序(使用 gzip 等)来进行解压。 +若引导装载程序没有实现这个需求,就要使用非压缩内核映像文件。 + + +4、调用内核映像 +------------- + +必要性: 强制 + +已解压的内核映像包含一个 32 字节的头,内容如下: + +  u32 magic	= 0x14000008;	/* 跳转到 stext, 小端 */ +  u32 res0	= 0;		/* 保留 */ +  u64 text_offset;		/* 映像装载偏移 */ +  u64 res1	= 0;		/* 保留 */ +  u64 res2	= 0;		/* 保留 */ + +映像必须位于系统 RAM 起始处的特定偏移(当前是 0x80000)。系统 RAM +的起始地址必须是以 2MB 对齐的。 + +在跳转入内核前,必须符合以下状态: + +- 停止所有 DMA 设备,这样内存数据就不会因为虚假网络包或磁盘数据而 +  被破坏。这可能可以节省你许多的调试时间。 + +- 主 CPU 通用寄存器设置 +  x0 = 系统 RAM 中设备树数据块(dtb)的物理地址。 +  x1 = 0 (保留,将来可能使用) +  x2 = 0 (保留,将来可能使用) +  x3 = 0 (保留,将来可能使用) + +- CPU 模式 +  所有形式的中断必须在 PSTATE.DAIF 中被屏蔽(Debug、SError、IRQ +  和 FIQ)。 +  CPU 必须处于 EL2(推荐,可访问虚拟化扩展)或非安全 EL1 模式下。 + +- 高速缓存、MMU +  MMU 必须关闭。 +  指令缓存开启或关闭都可以。 +  数据缓存必须关闭且无效。 +  外部高速缓存(如果存在)必须配置并禁用。 + +- 架构计时器 +  CNTFRQ 必须设定为计时器的频率。 +  如果在 EL1 模式下进入内核,则 CNTHCTL_EL2 中的 EL1PCTEN (bit 0) +  必须置位。 + +- 一致性 +  通过内核启动的所有 CPU 在内核入口地址上必须处于相同的一致性域中。 +  这可能要根据具体实现来定义初始化过程,以使能每个CPU上对维护操作的 +  接收。 + +- 系统寄存器 +  在进入内核映像的异常级中,所有构架中可写的系统寄存器必须通过软件 +  在一个更高的异常级别下初始化,以防止在 未知 状态下运行。 + +引导装载程序必须在每个 CPU 处于以下状态时跳入内核入口: + +- 主 CPU 必须直接跳入内核映像的第一条指令。通过此 CPU 传递的设备树 +  数据块必须在每个 CPU 节点中包含以下内容: + +    1、‘enable-method’属性。目前,此字段支持的值仅为字符串“spin-table”。 + +    2、‘cpu-release-addr’标识一个 64-bit、初始化为零的内存位置。 + +  引导装载程序必须生成这些设备树属性,并在跳入内核入口之前将其插入 +  数据块。 + +- 任何辅助 CPU 必须在内存保留区(通过设备树中的 /memreserve/ 域传递 +  给内核)中自旋于内核之外,轮询它们的 cpu-release-addr 位置(必须 +  包含在保留区中)。可通过插入 wfe 指令来降低忙循环开销,而主 CPU 将 +  发出 sev 指令。当对 cpu-release-addr 所指位置的读取操作返回非零值 +  时,CPU 必须直接跳入此值所指向的地址。 + +- 辅助 CPU 通用寄存器设置 +  x0 = 0 (保留,将来可能使用) +  x1 = 0 (保留,将来可能使用) +  x2 = 0 (保留,将来可能使用) +  x3 = 0 (保留,将来可能使用) diff --git a/Documentation/zh_CN/arm64/memory.txt b/Documentation/zh_CN/arm64/memory.txt new file mode 100644 index 00000000000..83b51931470 --- /dev/null +++ b/Documentation/zh_CN/arm64/memory.txt @@ -0,0 +1,93 @@ +Chinese translated version of Documentation/arm64/memory.txt + +If you have any comment or update to the content, please contact the +original document maintainer directly.  However, if you have a problem +communicating in English you can also ask the Chinese maintainer for +help.  Contact the Chinese maintainer if this translation is outdated +or if there is a problem with the translation. + +Maintainer: Catalin Marinas <catalin.marinas@arm.com> +Chinese maintainer: Fu Wei <tekkamanninja@gmail.com> +--------------------------------------------------------------------- +Documentation/arm64/memory.txt 的中文翻译 + +如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 +交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 +译存在问题,请联系中文版维护者。 + +英文版维护者: Catalin Marinas <catalin.marinas@arm.com> +中文版维护者: 傅炜  Fu Wei <tekkamanninja@gmail.com> +中文版翻译者: 傅炜  Fu Wei <tekkamanninja@gmail.com> +中文版校译者: 傅炜  Fu Wei <tekkamanninja@gmail.com> + +以下为正文 +--------------------------------------------------------------------- +		     Linux 在 AArch64 中的内存布局 +		     =========================== + +作者: Catalin Marinas <catalin.marinas@arm.com> +日期: 2012 年 02 月 20 日 + +本文档描述 AArch64 Linux 内核所使用的虚拟内存布局。此构架可以实现 +页大小为 4KB 的 4 级转换表和页大小为 64KB 的 3 级转换表。 + +AArch64 Linux 使用页大小为 4KB 的 3 级转换表配置,对于用户和内核 +都有 39-bit (512GB) 的虚拟地址空间。对于页大小为 64KB的配置,仅 +使用 2 级转换表,但内存布局相同。 + +用户地址空间的 63:39 位为 0,而内核地址空间的相应位为 1。TTBRx 的 +选择由虚拟地址的 63 位给出。swapper_pg_dir 仅包含内核(全局)映射, +而用户 pgd 仅包含用户(非全局)映射。swapper_pgd_dir 地址被写入 +TTBR1 中,且从不写入 TTBR0。 + + +AArch64 Linux 内存布局: + +起始地址			结束地址			大小		用途 +----------------------------------------------------------------------- +0000000000000000	0000007fffffffff	 512GB		用户空间 + +ffffff8000000000	ffffffbbfffcffff	~240GB		vmalloc + +ffffffbbfffd0000	ffffffbcfffdffff	  64KB		[防护页] + +ffffffbbfffe0000	ffffffbcfffeffff	  64KB		PCI I/O 空间 + +ffffffbbffff0000	ffffffbcffffffff	  64KB		[防护页] + +ffffffbc00000000	ffffffbdffffffff	   8GB		vmemmap + +ffffffbe00000000	ffffffbffbffffff	  ~8GB		[防护页,未来用于 vmmemap] + +ffffffbffc000000	ffffffbfffffffff	  64MB		模块 + +ffffffc000000000	ffffffffffffffff	 256GB		内存空间 + + +4KB 页大小的转换表查找: + ++--------+--------+--------+--------+--------+--------+--------+--------+ +|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0| ++--------+--------+--------+--------+--------+--------+--------+--------+ + |                 |         |         |         |         | + |                 |         |         |         |         v + |                 |         |         |         |   [11:0]  页内偏移 + |                 |         |         |         +-> [20:12] L3 索引 + |                 |         |         +-----------> [29:21] L2 索引 + |                 |         +---------------------> [38:30] L1 索引 + |                 +-------------------------------> [47:39] L0 索引 (未使用) + +-------------------------------------------------> [63] TTBR0/1 + + +64KB 页大小的转换表查找: + ++--------+--------+--------+--------+--------+--------+--------+--------+ +|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0| ++--------+--------+--------+--------+--------+--------+--------+--------+ + |                 |    |               |              | + |                 |    |               |              v + |                 |    |               |            [15:0]  页内偏移 + |                 |    |               +----------> [28:16] L3 索引 + |                 |    +--------------------------> [41:29] L2 索引 (仅使用 38:29 ) + |                 +-------------------------------> [47:42] L1 索引 (未使用) + +-------------------------------------------------> [63] TTBR0/1 diff --git a/MAINTAINERS b/MAINTAINERS index 027ec2bfa13..59203e77ce9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -503,7 +503,7 @@ F:	include/linux/altera_uart.h  F:	include/linux/altera_jtaguart.h  AMD FAM15H PROCESSOR POWER MONITORING DRIVER -M:	Andreas Herrmann <andreas.herrmann3@amd.com> +M:	Andreas Herrmann <herrmann.der.user@googlemail.com>  L:	lm-sensors@lm-sensors.org  S:	Maintained  F:	Documentation/hwmon/fam15h_power @@ -637,6 +637,13 @@ W:	http://www.arm.linux.org.uk/  S:	Maintained  F:	arch/arm/ +ARM SUB-ARCHITECTURES +L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S:	MAINTAINED +F:	arch/arm/mach-*/ +F:	arch/arm/plat-*/ +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git +  ARM PRIMECELL AACI PL041 DRIVER  M:	Russell King <linux@arm.linux.org.uk>  S:	Maintained @@ -2500,6 +2507,7 @@ M:	Joonyoung Shim <jy0922.shim@samsung.com>  M:	Seung-Woo Kim <sw0312.kim@samsung.com>  M:	Kyungmin Park <kyungmin.park@samsung.com>  L:	dri-devel@lists.freedesktop.org +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git  S:	Supported  F:	drivers/gpu/drm/exynos  F:	include/drm/exynos* @@ -2802,6 +2810,7 @@ F:	sound/usb/misc/ua101.c  EXTENSIBLE FIRMWARE INTERFACE (EFI)  M:	Matt Fleming <matt.fleming@intel.com>  L:	linux-efi@vger.kernel.org +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git  S:	Maintained  F:	Documentation/x86/efi-stub.txt  F:	arch/ia64/kernel/efi.c @@ -5061,7 +5070,13 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git  S:	Odd Fixes  F:	drivers/net/  F:	include/linux/if_* -F:	include/linux/*device.h +F:	include/linux/netdevice.h +F:	include/linux/arcdevice.h +F:	include/linux/etherdevice.h +F:	include/linux/fcdevice.h +F:	include/linux/fddidevice.h +F:	include/linux/hippidevice.h +F:	include/linux/inetdevice.h  NETXEN (1/10) GbE SUPPORT  M:	Sony Chacko <sony.chacko@qlogic.com> @@ -5633,7 +5648,7 @@ S:	Maintained  F:	drivers/pinctrl/spear/  PKTCDVD DRIVER -M:	Peter Osterlund <petero2@telia.com> +M:	Jiri Kosina <jkosina@suse.cz>  S:	Maintained  F:	drivers/block/pktcdvd.c  F:	include/linux/pktcdvd.h @@ -1,7 +1,7 @@  VERSION = 3  PATCHLEVEL = 7  SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc5  NAME = Terrified Chipmunk  # *DOCUMENTATION* diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 73067efd484..ade7e924bef 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1603,8 +1603,8 @@ config NR_CPUS  	default "4"  config HOTPLUG_CPU -	bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" -	depends on SMP && HOTPLUG && EXPERIMENTAL +	bool "Support for hot-pluggable CPUs" +	depends on SMP && HOTPLUG  	help  	  Say Y here to experiment with turning CPUs off and on.  CPUs  	  can be controlled through /sys/devices/system/cpu. @@ -1645,8 +1645,8 @@ config HZ  	default 100  config THUMB2_KERNEL -	bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)" -	depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL +	bool "Compile the kernel in Thumb-2 mode" +	depends on CPU_V7 && !CPU_V6 && !CPU_V6K  	select AEABI  	select ARM_ASM_UNIFIED  	select ARM_UNWIND @@ -1850,6 +1850,7 @@ config XEN_DOM0  config XEN  	bool "Xen guest support on ARM (EXPERIMENTAL)"  	depends on EXPERIMENTAL && ARM && OF +	depends on CPU_V7 && !CPU_V6  	help  	  Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. diff --git a/arch/arm/Makefile b/arch/arm/Makefile index f023e3acdfb..5f914fca911 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -21,8 +21,6 @@ endif  OBJCOPYFLAGS	:=-O binary -R .comment -S  GZFLAGS		:=-9  #KBUILD_CFLAGS	+=-pipe -# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb: -KBUILD_CFLAGS	+=$(call cc-option,-marm,)  # Never generate .eh_frame  KBUILD_CFLAGS	+= $(call cc-option,-fno-dwarf2-cfi-asm) @@ -105,17 +103,20 @@ endif  ifeq ($(CONFIG_THUMB2_KERNEL),y)  AFLAGS_AUTOIT	:=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it)  AFLAGS_NOWARN	:=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W) -CFLAGS_THUMB2	:=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN) -AFLAGS_THUMB2	:=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb +CFLAGS_ISA	:=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN) +AFLAGS_ISA	:=$(CFLAGS_ISA) -Wa$(comma)-mthumb  # Work around buggy relocation from gas if requested:  ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y)  CFLAGS_MODULE	+=-fno-optimize-sibling-calls  endif +else +CFLAGS_ISA	:=$(call cc-option,-marm,) +AFLAGS_ISA	:=$(CFLAGS_ISA)  endif  # Need -Uarm for gcc < 3.x -KBUILD_CFLAGS	+=$(CFLAGS_ABI) $(CFLAGS_THUMB2) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm -KBUILD_AFLAGS	+=$(CFLAGS_ABI) $(AFLAGS_THUMB2) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float +KBUILD_CFLAGS	+=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm +KBUILD_AFLAGS	+=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float  CHECKFLAGS	+= -D__arm__ diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 3fdab016aa5..f2aa09eb658 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -33,7 +33,7 @@ ifeq ($(CONFIG_XIP_KERNEL),y)  $(obj)/xipImage: vmlinux FORCE  	$(call if_changed,objcopy) -	@echo '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))' +	$(kecho) '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'  $(obj)/Image $(obj)/zImage: FORCE  	@echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)' @@ -48,14 +48,14 @@ $(obj)/xipImage: FORCE  $(obj)/Image: vmlinux FORCE  	$(call if_changed,objcopy) -	@echo '  Kernel: $@ is ready' +	$(kecho) '  Kernel: $@ is ready'  $(obj)/compressed/vmlinux: $(obj)/Image FORCE  	$(Q)$(MAKE) $(build)=$(obj)/compressed $@  $(obj)/zImage:	$(obj)/compressed/vmlinux FORCE  	$(call if_changed,objcopy) -	@echo '  Kernel: $@ is ready' +	$(kecho) '  Kernel: $@ is ready'  endif @@ -90,7 +90,7 @@ fi  $(obj)/uImage:	$(obj)/zImage FORCE  	@$(check_for_multiple_loadaddr)  	$(call if_changed,uimage) -	@echo '  Image $@ is ready' +	$(kecho) '  Image $@ is ready'  $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE  	$(Q)$(MAKE) $(build)=$(obj)/bootp $@ @@ -98,7 +98,7 @@ $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE  $(obj)/bootpImage: $(obj)/bootp/bootp FORCE  	$(call if_changed,objcopy) -	@echo '  Kernel: $@ is ready' +	$(kecho) '  Kernel: $@ is ready'  PHONY += initrd FORCE  initrd: diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi index b06c0db273b..e6391a4e664 100644 --- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi +++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi @@ -126,14 +126,14 @@  		#size-cells = <0>;  		btn3 { -			label = "Buttin 3"; +			label = "Button 3";  			gpios = <&pioA 30 1>;  			linux,code = <0x103>;  			gpio-key,wakeup;  		};  		btn4 { -			label = "Buttin 4"; +			label = "Button 4";  			gpios = <&pioA 31 1>;  			linux,code = <0x104>;  			gpio-key,wakeup; diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi index 748ba7aa746..4b0e0ca08f4 100644 --- a/arch/arm/boot/dts/dbx5x0.dtsi +++ b/arch/arm/boot/dts/dbx5x0.dtsi @@ -483,6 +483,8 @@  			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";  			reg = <0x80004000 0x1000>;  			interrupts = <0 21 0x4>; +			arm,primecell-periphid = <0x180024>; +  			#address-cells = <1>;  			#size-cells = <0>;  			v-i2c-supply = <&db8500_vape_reg>; @@ -494,6 +496,8 @@  			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";  			reg = <0x80122000 0x1000>;  			interrupts = <0 22 0x4>; +			arm,primecell-periphid = <0x180024>; +  			#address-cells = <1>;  			#size-cells = <0>;  			v-i2c-supply = <&db8500_vape_reg>; @@ -505,6 +509,8 @@  			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";  			reg = <0x80128000 0x1000>;  			interrupts = <0 55 0x4>; +			arm,primecell-periphid = <0x180024>; +  			#address-cells = <1>;  			#size-cells = <0>;  			v-i2c-supply = <&db8500_vape_reg>; @@ -516,6 +522,8 @@  			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";  			reg = <0x80110000 0x1000>;  			interrupts = <0 12 0x4>; +			arm,primecell-periphid = <0x180024>; +  			#address-cells = <1>;  			#size-cells = <0>;  			v-i2c-supply = <&db8500_vape_reg>; @@ -527,6 +535,8 @@  			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";  			reg = <0x8012a000 0x1000>;  			interrupts = <0 51 0x4>; +			arm,primecell-periphid = <0x180024>; +  			#address-cells = <1>;  			#size-cells = <0>;  			v-i2c-supply = <&db8500_vape_reg>; @@ -573,33 +583,38 @@  			interrupts = <0 60 0x4>;  			status = "disabled";  		}; +  		sdi@80118000 {  			compatible = "arm,pl18x", "arm,primecell";  			reg = <0x80118000 0x1000>;  			interrupts = <0 50 0x4>;  			status = "disabled";  		}; +  		sdi@80005000 {  			compatible = "arm,pl18x", "arm,primecell";  			reg = <0x80005000 0x1000>;  			interrupts = <0 41 0x4>;  			status = "disabled";  		}; +  		sdi@80119000 {  			compatible = "arm,pl18x", "arm,primecell";  			reg = <0x80119000 0x1000>;  			interrupts = <0 59 0x4>;  			status = "disabled";  		}; +  		sdi@80114000 {  			compatible = "arm,pl18x", "arm,primecell";  			reg = <0x80114000 0x1000>;  			interrupts = <0 99 0x4>;  			status = "disabled";  		}; +  		sdi@80008000 {  			compatible = "arm,pl18x", "arm,primecell"; -			reg = <0x80114000 0x1000>; +			reg = <0x80008000 0x1000>;  			interrupts = <0 100 0x4>;  			status = "disabled";  		}; diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts index 73567b843e7..a21511c1407 100644 --- a/arch/arm/boot/dts/exynos4210-trats.dts +++ b/arch/arm/boot/dts/exynos4210-trats.dts @@ -20,8 +20,10 @@  	compatible = "samsung,trats", "samsung,exynos4210";  	memory { -		reg =  <0x40000000 0x20000000 -			0x60000000 0x20000000>; +		reg =  <0x40000000 0x10000000 +			0x50000000 0x10000000 +			0x60000000 0x10000000 +			0x70000000 0x10000000>;  	};  	chosen { diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi index 9ca4ca70c1b..6d31aa38346 100644 --- a/arch/arm/boot/dts/imx23.dtsi +++ b/arch/arm/boot/dts/imx23.dtsi @@ -69,6 +69,7 @@  				interrupts = <13>, <56>;  				interrupt-names = "gpmi-dma", "bch";  				clocks = <&clks 34>; +				clock-names = "gpmi_io";  				fsl,gpmi-dma-channel = <4>;  				status = "disabled";  			}; diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index e16d6315548..55c57ea6169 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi @@ -85,6 +85,7 @@  				interrupts = <88>, <41>;  				interrupt-names = "gpmi-dma", "bch";  				clocks = <&clks 50>; +				clock-names = "gpmi_io";  				fsl,gpmi-dma-channel = <4>;  				status = "disabled";  			}; diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi index f38ea8771b4..696e929d030 100644 --- a/arch/arm/boot/dts/omap3.dtsi +++ b/arch/arm/boot/dts/omap3.dtsi @@ -257,7 +257,7 @@  			interrupt-names = "common", "tx", "rx", "sidetone";  			interrupt-parent = <&intc>;  			ti,buffer-size = <1280>; -			ti,hwmods = "mcbsp2"; +			ti,hwmods = "mcbsp2", "mcbsp2_sidetone";  		};  		mcbsp3: mcbsp@49024000 { @@ -272,7 +272,7 @@  			interrupt-names = "common", "tx", "rx", "sidetone";  			interrupt-parent = <&intc>;  			ti,buffer-size = <128>; -			ti,hwmods = "mcbsp3"; +			ti,hwmods = "mcbsp3", "mcbsp3_sidetone";  		};  		mcbsp4: mcbsp@49026000 { diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 66aa7a6db88..394ded624e3 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -139,6 +139,7 @@ CONFIG_I2C_IMX=y  CONFIG_SPI=y  CONFIG_SPI_IMX=y  CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_MC9S08DZ60=y  # CONFIG_HWMON is not set  CONFIG_WATCHDOG=y  CONFIG_IMX2_WDT=y @@ -155,6 +156,7 @@ CONFIG_SOC_CAMERA=y  CONFIG_SOC_CAMERA_OV2640=y  CONFIG_VIDEO_MX3=y  CONFIG_FB=y +CONFIG_LCD_PLATFORM=y  CONFIG_BACKLIGHT_LCD_SUPPORT=y  CONFIG_LCD_CLASS_DEVICE=y  CONFIG_LCD_L4F00242T03=y diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index 7bcf850eddc..3458752c4bb 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -1,6 +1,6 @@  CONFIG_EXPERIMENTAL=y  CONFIG_SYSVIPC=y -CONFIG_NO_HZ=y +CONFIG_IRQ_DOMAIN_DEBUG=y  CONFIG_HIGH_RES_TIMERS=y  CONFIG_LOG_BUF_SHIFT=14  CONFIG_BLK_DEV_INITRD=y @@ -9,10 +9,12 @@ CONFIG_SLAB=y  CONFIG_MODULES=y  CONFIG_MODULE_UNLOAD=y  CONFIG_ARCH_MVEBU=y -CONFIG_MACH_ARMADA_370_XP=y +CONFIG_MACH_ARMADA_370=y +CONFIG_MACH_ARMADA_XP=y +# CONFIG_CACHE_L2X0 is not set  CONFIG_AEABI=y  CONFIG_HIGHMEM=y -CONFIG_USE_OF=y +# CONFIG_COMPACTION is not set  CONFIG_ZBOOT_ROM_TEXT=0x0  CONFIG_ZBOOT_ROM_BSS=0x0  CONFIG_ARM_APPENDED_DTB=y @@ -23,6 +25,8 @@ CONFIG_SERIAL_8250_CONSOLE=y  CONFIG_SERIAL_OF_PLATFORM=y  CONFIG_GPIOLIB=y  CONFIG_GPIO_SYSFS=y +# CONFIG_USB_SUPPORT is not set +# CONFIG_IOMMU_SUPPORT is not set  CONFIG_EXT2_FS=y  CONFIG_EXT3_FS=y  # CONFIG_EXT3_FS_XATTR is not set diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig index cdd4d2bd396..2ba9e63d0f1 100644 --- a/arch/arm/configs/versatile_defconfig +++ b/arch/arm/configs/versatile_defconfig @@ -1,3 +1,4 @@ +CONFIG_ARCH_VERSATILE=y  CONFIG_EXPERIMENTAL=y  # CONFIG_LOCALVERSION_AUTO is not set  CONFIG_SYSVIPC=y diff --git a/arch/arm/include/asm/flat.h b/arch/arm/include/asm/flat.h index 59426a4595c..e847d23351e 100644 --- a/arch/arm/include/asm/flat.h +++ b/arch/arm/include/asm/flat.h @@ -8,7 +8,7 @@  #define	flat_argvp_envp_on_stack()		1  #define	flat_old_ram_flag(flags)		(flags)  #define	flat_reloc_valid(reloc, size)		((reloc) <= (size)) -#define	flat_get_addr_from_rp(rp, relval, flags, persistent) get_unaligned(rp) +#define	flat_get_addr_from_rp(rp, relval, flags, persistent) ((void)persistent,get_unaligned(rp))  #define	flat_put_addr_at_rp(rp, val, relval)	put_unaligned(val,rp)  #define	flat_get_relocate_addr(rel)		(rel)  #define	flat_set_persistent(relval, p)		0 diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 35c1ed89b93..42f042ee4ad 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -64,7 +64,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);  static inline void __raw_writew(u16 val, volatile void __iomem *addr)  {  	asm volatile("strh %1, %0" -		     : "+Qo" (*(volatile u16 __force *)addr) +		     : "+Q" (*(volatile u16 __force *)addr)  		     : "r" (val));  } @@ -72,7 +72,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)  {  	u16 val;  	asm volatile("ldrh %1, %0" -		     : "+Qo" (*(volatile u16 __force *)addr), +		     : "+Q" (*(volatile u16 __force *)addr),  		       "=r" (val));  	return val;  } diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h index 05b8e82ec9f..e3f75726343 100644 --- a/arch/arm/include/asm/sched_clock.h +++ b/arch/arm/include/asm/sched_clock.h @@ -10,7 +10,5 @@  extern void sched_clock_postinit(void);  extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); -extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, -		unsigned long rate);  #endif diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 77bd79f2ffd..7e1f76027f6 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -200,8 +200,8 @@ extern int __put_user_8(void *, unsigned long long);  #define USER_DS			KERNEL_DS  #define segment_eq(a,b)		(1) -#define __addr_ok(addr)		(1) -#define __range_ok(addr,size)	(0) +#define __addr_ok(addr)		((void)(addr),1) +#define __range_ok(addr,size)	((void)(addr),0)  #define get_fs()		(KERNEL_DS)  static inline void set_fs(mm_segment_t fs) diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h index 6a6f1e485f4..301c1db3e99 100644 --- a/arch/arm/include/asm/vfpmacros.h +++ b/arch/arm/include/asm/vfpmacros.h @@ -27,9 +27,9 @@  #if __LINUX_ARM_ARCH__ <= 6  	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs  	ldr	\tmp, [\tmp, #0] -	tst	\tmp, #HWCAP_VFPv3D16 -	ldceql	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31} -	addne	\base, \base, #32*4		    @ step over unused register space +	tst	\tmp, #HWCAP_VFPD32 +	ldcnel	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31} +	addeq	\base, \base, #32*4		    @ step over unused register space  #else  	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0  	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field @@ -51,9 +51,9 @@  #if __LINUX_ARM_ARCH__ <= 6  	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs  	ldr	\tmp, [\tmp, #0] -	tst	\tmp, #HWCAP_VFPv3D16 -	stceql	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31} -	addne	\base, \base, #32*4		    @ step over unused register space +	tst	\tmp, #HWCAP_VFPD32 +	stcnel	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31} +	addeq	\base, \base, #32*4		    @ step over unused register space  #else  	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0  	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field diff --git a/arch/arm/include/debug/8250_32.S b/arch/arm/include/debug/8250_32.S new file mode 100644 index 00000000000..8db01eeabbb --- /dev/null +++ b/arch/arm/include/debug/8250_32.S @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2011 Picochip Ltd., Jamie Iles + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit + * accesses to the 8250. + */ + +#include <linux/serial_reg.h> + +		.macro	senduart,rd,rx +		str	\rd, [\rx, #UART_TX << UART_SHIFT] +		.endm + +		.macro	busyuart,rd,rx +1002:		ldr	\rd, [\rx, #UART_LSR << UART_SHIFT] +		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE +		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE +		bne	1002b +		.endm + +		/* The UART's don't have any flow control IO's wired up. */ +		.macro	waituart,rd,rx +		.endm diff --git a/arch/arm/include/debug/picoxcell.S b/arch/arm/include/debug/picoxcell.S index 7419deb1b94..bc1f07c49cd 100644 --- a/arch/arm/include/debug/picoxcell.S +++ b/arch/arm/include/debug/picoxcell.S @@ -5,10 +5,7 @@   * it under the terms of the GNU General Public License version 2 as   * published by the Free Software Foundation.   * - * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit - * accesses to the 8250.   */ -#include <linux/serial_reg.h>  #define UART_SHIFT 2  #define PICOXCELL_UART1_BASE		0x80230000 @@ -19,17 +16,4 @@  		ldr	\rp, =PICOXCELL_UART1_BASE  		.endm -		.macro	senduart,rd,rx -		str	\rd, [\rx, #UART_TX << UART_SHIFT] -		.endm - -		.macro	busyuart,rd,rx -1002:		ldr	\rd, [\rx, #UART_LSR << UART_SHIFT] -		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE -		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE -		bne	1002b -		.endm - -		/* The UART's don't have any flow control IO's wired up. */ -		.macro	waituart,rd,rx -		.endm +#include "8250_32.S" diff --git a/arch/arm/include/debug/socfpga.S b/arch/arm/include/debug/socfpga.S index d6f26d23374..966b2f99494 100644 --- a/arch/arm/include/debug/socfpga.S +++ b/arch/arm/include/debug/socfpga.S @@ -7,6 +7,9 @@   * published by the Free Software Foundation.   */ +#define UART_SHIFT 2 +#define DEBUG_LL_UART_OFFSET	0x00002000 +  		.macro	addruart, rp, rv, tmp  		mov	\rp, #DEBUG_LL_UART_OFFSET  		orr	\rp, \rp, #0x00c00000 @@ -14,3 +17,5 @@  		orr	\rp, \rp, #0xff000000	@ physical base  		.endm +#include "8250_32.S" + diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h index f254f6503cc..3688fd15a32 100644 --- a/arch/arm/include/uapi/asm/hwcap.h +++ b/arch/arm/include/uapi/asm/hwcap.h @@ -18,11 +18,12 @@  #define HWCAP_THUMBEE	(1 << 11)  #define HWCAP_NEON	(1 << 12)  #define HWCAP_VFPv3	(1 << 13) -#define HWCAP_VFPv3D16	(1 << 14) +#define HWCAP_VFPv3D16	(1 << 14)	/* also set for VFPv4-D16 */  #define HWCAP_TLS	(1 << 15)  #define HWCAP_VFPv4	(1 << 16)  #define HWCAP_IDIVA	(1 << 17)  #define HWCAP_IDIVT	(1 << 18) +#define HWCAP_VFPD32	(1 << 19)	/* set if VFP has 32 regs (not 16) */  #define HWCAP_IDIV	(HWCAP_IDIVA | HWCAP_IDIVT) diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 16cedb42c0c..896165096d6 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -34,6 +34,7 @@  #include <linux/list.h>  #include <linux/kallsyms.h>  #include <linux/proc_fs.h> +#include <linux/export.h>  #include <asm/exception.h>  #include <asm/mach/arch.h> @@ -109,6 +110,7 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)  	/* Order is clear bits in "clr" then set bits in "set" */  	irq_modify_status(irq, clr, set & ~clr);  } +EXPORT_SYMBOL_GPL(set_irq_flags);  void __init init_IRQ(void)  { diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c index 38c1a3b103a..83931290506 100644 --- a/arch/arm/kernel/kprobes-test-arm.c +++ b/arch/arm/kernel/kprobes-test-arm.c @@ -366,7 +366,9 @@ void kprobe_arm_test_cases(void)  	TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3")  	TEST_UNSUPPORTED(".word 0xe0500090 @ undef")  	TEST_UNSUPPORTED(".word 0xe05fff9f @ undef") +#endif +#if __LINUX_ARM_ARCH__ >= 7  	TEST_RRR(  "mls		r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")  	TEST_RRR(  "mlshi	r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")  	TEST_RR(   "mls		lr, r",1, VAL2,", r",2, VAL3,", r13") @@ -456,6 +458,8 @@ void kprobe_arm_test_cases(void)  	TEST_UNSUPPORTED(".word	0xe1700090") /* Unallocated space */  #if __LINUX_ARM_ARCH__ >= 6  	TEST_UNSUPPORTED("ldrex	r2, [sp]") +#endif +#if (__LINUX_ARM_ARCH__ >= 7) || defined(CONFIG_CPU_32v6K)  	TEST_UNSUPPORTED("strexd	r0, r2, r3, [sp]")  	TEST_UNSUPPORTED("ldrexd	r2, r3, [sp]")  	TEST_UNSUPPORTED("strexb	r0, r2, [sp]") diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index e29c3337ca8..8ef8c933780 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -45,10 +45,9 @@ int machine_kexec_prepare(struct kimage *image)  	for (i = 0; i < image->nr_segments; i++) {  		current_segment = &image->segment[i]; -		err = memblock_is_region_memory(current_segment->mem, -						current_segment->memsz); -		if (err) -			return - EINVAL; +		if (!memblock_is_region_memory(current_segment->mem, +					       current_segment->memsz)) +			return -EINVAL;  		err = get_user(header, (__be32*)current_segment->buf);  		if (err) diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 93971b1a4f0..53c0304b734 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -96,6 +96,10 @@ armpmu_event_set_period(struct perf_event *event,  	s64 period = hwc->sample_period;  	int ret = 0; +	/* The period may have been changed by PERF_EVENT_IOC_PERIOD */ +	if (unlikely(period != hwc->last_period)) +		left = period - (hwc->last_period - left); +  	if (unlikely(left <= -period)) {  		left = period;  		local64_set(&hwc->period_left, left); diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c index e21bac20d90..fc6692e2b60 100644 --- a/arch/arm/kernel/sched_clock.c +++ b/arch/arm/kernel/sched_clock.c @@ -107,13 +107,6 @@ static void sched_clock_poll(unsigned long wrap_ticks)  	update_sched_clock();  } -void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, -		unsigned long rate) -{ -	setup_sched_clock(read, bits, rate); -	cd.needs_suspend = true; -} -  void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)  {  	unsigned long r, w; @@ -189,18 +182,15 @@ void __init sched_clock_postinit(void)  static int sched_clock_suspend(void)  {  	sched_clock_poll(sched_clock_timer.data); -	if (cd.needs_suspend) -		cd.suspended = true; +	cd.suspended = true;  	return 0;  }  static void sched_clock_resume(void)  { -	if (cd.needs_suspend) { -		cd.epoch_cyc = read_sched_clock(); -		cd.epoch_cyc_copy = cd.epoch_cyc; -		cd.suspended = false; -	} +	cd.epoch_cyc = read_sched_clock(); +	cd.epoch_cyc_copy = cd.epoch_cyc; +	cd.suspended = false;  }  static struct syscore_ops sched_clock_ops = { diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 8e20754dd31..fbc8b2623d8 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -294,18 +294,24 @@ static void percpu_timer_setup(void);  asmlinkage void __cpuinit secondary_start_kernel(void)  {  	struct mm_struct *mm = &init_mm; -	unsigned int cpu = smp_processor_id(); +	unsigned int cpu; + +	/* +	 * The identity mapping is uncached (strongly ordered), so +	 * switch away from it before attempting any exclusive accesses. +	 */ +	cpu_switch_mm(mm->pgd, mm); +	enter_lazy_tlb(mm, current); +	local_flush_tlb_all();  	/*  	 * All kernel threads share the same mm context; grab a  	 * reference and switch to it.  	 */ +	cpu = smp_processor_id();  	atomic_inc(&mm->mm_count);  	current->active_mm = mm;  	cpumask_set_cpu(cpu, mm_cpumask(mm)); -	cpu_switch_mm(mm->pgd, mm); -	enter_lazy_tlb(mm, current); -	local_flush_tlb_all();  	printk("CPU%u: Booted secondary processor\n", cpu); diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index e1f906989bb..b22d700fea2 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -42,10 +42,10 @@ static void twd_set_mode(enum clock_event_mode mode,  	switch (mode) {  	case CLOCK_EVT_MODE_PERIODIC: -		/* timer load already set up */  		ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE  			| TWD_TIMER_CONTROL_PERIODIC; -		__raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD); +		__raw_writel(DIV_ROUND_CLOSEST(twd_timer_rate, HZ), +			twd_base + TWD_TIMER_LOAD);  		break;  	case CLOCK_EVT_MODE_ONESHOT:  		/* period set, and timer enabled in 'next_event' hook */ diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c index 9d0a30032d7..0dc53854a5d 100644 --- a/arch/arm/lib/delay.c +++ b/arch/arm/lib/delay.c @@ -45,6 +45,7 @@ int read_current_timer(unsigned long *timer_val)  	*timer_val = delay_timer->read_current_timer();  	return 0;  } +EXPORT_SYMBOL_GPL(read_current_timer);  static void __timer_delay(unsigned long cycles)  { diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index b1420710193..043624219b5 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -21,19 +21,13 @@ config SOC_AT91SAM9  	bool  	select CPU_ARM926T  	select GENERIC_CLOCKEVENTS +	select MULTI_IRQ_HANDLER +	select SPARSE_IRQ  menu "Atmel AT91 System-on-Chip"  comment "Atmel AT91 Processor" -config SOC_AT91SAM9 -	bool -	select AT91_SAM9_SMC -	select AT91_SAM9_TIME -	select CPU_ARM926T -	select MULTI_IRQ_HANDLER -	select SPARSE_IRQ -  config SOC_AT91RM9200  	bool "AT91RM9200"  	select CPU_ARM920T diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index b4f0565aff6..5269825194a 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {  	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),  	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),  	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk), -	CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk), +	CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk),  	/* fake hclk clock */  	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),  	CLKDEV_CON_ID("pioA", &pioA_clk), diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index a563189cdfc..1e122bcd784 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -479,7 +479,7 @@ static struct i2c_gpio_platform_data pdata = {  static struct platform_device at91rm9200_twi_device = {  	.name			= "i2c-gpio", -	.id			= -1, +	.id			= 0,  	.dev.platform_data	= &pdata,  }; @@ -512,7 +512,7 @@ static struct resource twi_resources[] = {  static struct platform_device at91rm9200_twi_device = {  	.name		= "i2c-at91rm9200", -	.id		= -1, +	.id		= 0,  	.resource	= twi_resources,  	.num_resources	= ARRAY_SIZE(twi_resources),  }; diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index ad29f93f20c..f8202615f4a 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -211,8 +211,8 @@ static struct clk_lookup periph_clocks_lookups[] = {  	CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),  	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),  	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk), -	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk), -	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk), +	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk), +	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk),  	/* more usart lookup table for DT entries */  	CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),  	CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk), diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index a76b8684f52..aa1e5872988 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -389,7 +389,7 @@ static struct i2c_gpio_platform_data pdata = {  static struct platform_device at91sam9260_twi_device = {  	.name			= "i2c-gpio", -	.id			= -1, +	.id			= 0,  	.dev.platform_data	= &pdata,  }; @@ -421,7 +421,7 @@ static struct resource twi_resources[] = {  };  static struct platform_device at91sam9260_twi_device = { -	.id		= -1, +	.id		= 0,  	.resource	= twi_resources,  	.num_resources	= ARRAY_SIZE(twi_resources),  }; diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 8d999eb1a13..04295c04b3e 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -178,8 +178,8 @@ static struct clk_lookup periph_clocks_lookups[] = {  	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),  	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),  	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0), -	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk), -	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk), +	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk), +	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk),  	CLKDEV_CON_ID("pioA", &pioA_clk),  	CLKDEV_CON_ID("pioB", &pioB_clk),  	CLKDEV_CON_ID("pioC", &pioC_clk), diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 9752f17efba..b9487696b7b 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -285,7 +285,7 @@ static struct i2c_gpio_platform_data pdata = {  static struct platform_device at91sam9261_twi_device = {  	.name			= "i2c-gpio", -	.id			= -1, +	.id			= 0,  	.dev.platform_data	= &pdata,  }; @@ -317,7 +317,7 @@ static struct resource twi_resources[] = {  };  static struct platform_device at91sam9261_twi_device = { -	.id		= -1, +	.id		= 0,  	.resource	= twi_resources,  	.num_resources	= ARRAY_SIZE(twi_resources),  }; diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 6a01d0360df..d6f9c23927c 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -193,7 +193,7 @@ static struct clk_lookup periph_clocks_lookups[] = {  	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),  	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),  	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk), -	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk), +	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),  	/* fake hclk clock */  	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),  	CLKDEV_CON_ID("pioA", &pioA_clk), diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 8dde220b42b..cb85da2ecce 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -567,7 +567,7 @@ static struct i2c_gpio_platform_data pdata = {  static struct platform_device at91sam9263_twi_device = {  	.name			= "i2c-gpio", -	.id			= -1, +	.id			= 0,  	.dev.platform_data	= &pdata,  }; @@ -600,7 +600,7 @@ static struct resource twi_resources[] = {  static struct platform_device at91sam9263_twi_device = {  	.name		= "i2c-at91sam9260", -	.id		= -1, +	.id		= 0,  	.resource	= twi_resources,  	.num_resources	= ARRAY_SIZE(twi_resources),  }; diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index d6ca0543ce8..5047bdc92ad 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -314,7 +314,7 @@ static struct i2c_gpio_platform_data pdata = {  static struct platform_device at91sam9rl_twi_device = {  	.name			= "i2c-gpio", -	.id			= -1, +	.id			= 0,  	.dev.platform_data	= &pdata,  }; @@ -347,7 +347,7 @@ static struct resource twi_resources[] = {  static struct platform_device at91sam9rl_twi_device = {  	.name		= "i2c-at91sam9g20", -	.id		= -1, +	.id		= 0,  	.resource	= twi_resources,  	.num_resources	= ARRAY_SIZE(twi_resources),  }; diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c index 6bd7300a2bc..bb7f54474b9 100644 --- a/arch/arm/mach-at91/at91x40.c +++ b/arch/arm/mach-at91/at91x40.c @@ -88,6 +88,6 @@ void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS])  	if (!priority)  		priority = at91x40_default_irq_priority; -	at91_aic_init(priority); +	at91_aic_init(priority, at91_extern_irq);  } diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c index 9cda3fd346a..6960778af4c 100644 --- a/arch/arm/mach-at91/board-neocore926.c +++ b/arch/arm/mach-at91/board-neocore926.c @@ -129,7 +129,7 @@ static struct spi_board_info neocore926_spi_devices[] = {  		.max_speed_hz	= 125000 * 16,  		.bus_num	= 0,  		.platform_data	= &ads_info, -		.irq		= AT91SAM9263_ID_IRQ1, +		.irq		= NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,  	},  #endif  }; diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 27b3af1a304..a9167dd45f9 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -309,7 +309,7 @@ static struct spi_board_info ek_spi_devices[] = {  		.max_speed_hz	= 125000 * 26,	/* (max sample rate @ 3V) * (cmd + data + overhead) */  		.bus_num	= 0,  		.platform_data	= &ads_info, -		.irq		= AT91SAM9261_ID_IRQ0, +		.irq		= NR_IRQS_LEGACY + AT91SAM9261_ID_IRQ0,  		.controller_data = (void *) AT91_PIN_PA28,	/* CS pin */  	},  #endif diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 073e17403d9..b87dbe2be0d 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -132,7 +132,7 @@ static struct spi_board_info ek_spi_devices[] = {  		.max_speed_hz	= 125000 * 26,	/* (max sample rate @ 3V) * (cmd + data + overhead) */  		.bus_num	= 0,  		.platform_data	= &ads_info, -		.irq		= AT91SAM9263_ID_IRQ1, +		.irq		= NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,  	},  #endif  }; diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index f4965067765..b62f560e6c7 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -26,7 +26,8 @@ extern void __init at91_dt_initialize(void);  extern void __init at91_init_irq_default(void);  extern void __init at91_init_interrupts(unsigned int priority[]);  extern void __init at91x40_init_interrupts(unsigned int priority[]); -extern void __init at91_aic_init(unsigned int priority[]); +extern void __init at91_aic_init(unsigned int priority[], +				 unsigned int ext_irq_mask);  extern int  __init at91_aic_of_init(struct device_node *node,  				    struct device_node *parent);  extern int  __init at91_aic5_of_init(struct device_node *node, diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c index 1e02c0e49dc..febc2ee901a 100644 --- a/arch/arm/mach-at91/irq.c +++ b/arch/arm/mach-at91/irq.c @@ -502,14 +502,19 @@ int __init at91_aic5_of_init(struct device_node *node,  /*   * Initialize the AIC interrupt controller.   */ -void __init at91_aic_init(unsigned int *priority) +void __init at91_aic_init(unsigned int *priority, unsigned int ext_irq_mask)  {  	unsigned int i;  	int irq_base; -	if (at91_aic_pm_init()) +	at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs) +				  * sizeof(*at91_extern_irq), GFP_KERNEL); + +	if (at91_aic_pm_init() || at91_extern_irq == NULL)  		panic("Unable to allocate bit maps\n"); +	*at91_extern_irq = ext_irq_mask; +  	at91_aic_base = ioremap(AT91_AIC, 512);  	if (!at91_aic_base)  		panic("Unable to ioremap AIC registers\n"); diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index da9881b161e..0b32c81730a 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -47,7 +47,7 @@ void __init at91_init_irq_default(void)  void __init at91_init_interrupts(unsigned int *priority)  {  	/* Initialize the AIC interrupt controller */ -	at91_aic_init(priority); +	at91_aic_init(priority, at91_extern_irq);  	/* Enable GPIO interrupts */  	at91_gpio_irq_setup(); @@ -151,7 +151,7 @@ static void __init soc_detect(u32 dbgu_base)  	}  	/* at91sam9g10 */ -	if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { +	if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {  		at91_soc_initdata.type = AT91_SOC_SAM9G10;  		at91_boot_soc = at91sam9261_soc;  	} diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 715b690e500..1947be8e5f5 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -47,6 +47,7 @@  #include <plat/fimc-core.h>  #include <plat/iic-core.h>  #include <plat/tv-core.h> +#include <plat/spi-core.h>  #include <plat/regs-serial.h>  #include "common.h" @@ -346,6 +347,8 @@ static void __init exynos4_map_io(void)  	s5p_fb_setname(0, "exynos4-fb");  	s5p_hdmi_setname("exynos4-hdmi"); + +	s3c64xx_spi_setname("exynos4210-spi");  }  static void __init exynos5_map_io(void) @@ -366,6 +369,8 @@ static void __init exynos5_map_io(void)  	s3c_i2c0_setname("s3c2440-i2c");  	s3c_i2c1_setname("s3c2440-i2c");  	s3c_i2c2_setname("s3c2440-i2c"); + +	s3c64xx_spi_setname("exynos4210-spi");  }  static void __init exynos4_init_clocks(int xtal) diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index e58d786faf7..eadf4b59e7d 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -99,6 +99,7 @@ static char const *exynos4_dt_compat[] __initdata = {  DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")  	/* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */ +	.smp		= smp_ops(exynos_smp_ops),  	.init_irq	= exynos4_init_irq,  	.map_io		= exynos4_dt_map_io,  	.handle_irq	= gic_handle_irq, diff --git a/arch/arm/mach-imx/clk-busy.c b/arch/arm/mach-imx/clk-busy.c index 1a7a8dd045a..1ab91b5209e 100644 --- a/arch/arm/mach-imx/clk-busy.c +++ b/arch/arm/mach-imx/clk-busy.c @@ -108,7 +108,7 @@ struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,  	busy->div.hw.init = &init;  	clk = clk_register(NULL, &busy->div.hw); -	if (!clk) +	if (IS_ERR(clk))  		kfree(busy);  	return clk; diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c index d20d4795f4e..01e2f843bf2 100644 --- a/arch/arm/mach-imx/clk-imx25.c +++ b/arch/arm/mach-imx/clk-imx25.c @@ -127,8 +127,8 @@ int __init mx25_clocks_init(void)  	clk[esdhc2_ipg_per] = imx_clk_gate("esdhc2_ipg_per", "per4", ccm(CCM_CGCR0),  4);  	clk[gpt_ipg_per] = imx_clk_gate("gpt_ipg_per", "per5", ccm(CCM_CGCR0),  5);  	clk[i2c_ipg_per] = imx_clk_gate("i2c_ipg_per", "per6", ccm(CCM_CGCR0),  6); -	clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per8", ccm(CCM_CGCR0),  7); -	clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "ipg_per", ccm(CCM_CGCR0),  8); +	clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per7", ccm(CCM_CGCR0),  7); +	clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "per8", ccm(CCM_CGCR0),  8);  	clk[ssi1_ipg_per] = imx_clk_gate("ssi1_ipg_per", "per13", ccm(CCM_CGCR0), 13);  	clk[ssi2_ipg_per] = imx_clk_gate("ssi2_ipg_per", "per14", ccm(CCM_CGCR0), 14);  	clk[uart_ipg_per] = imx_clk_gate("uart_ipg_per", "per15", ccm(CCM_CGCR0), 15); diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c index 3b6b640eed2..366e5d59d88 100644 --- a/arch/arm/mach-imx/clk-imx27.c +++ b/arch/arm/mach-imx/clk-imx27.c @@ -109,7 +109,7 @@ int __init mx27_clocks_init(unsigned long fref)  	clk[per3_div] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6);  	clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);  	clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks)); -	clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 3); +	clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6);  	clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3);  	clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));  	clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks)); @@ -121,7 +121,7 @@ int __init mx27_clocks_init(unsigned long fref)  	clk[ssi1_sel] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));  	clk[ssi2_sel] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));  	clk[ssi1_div] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6); -	clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 3); +	clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6);  	clk[clko_en] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0);  	clk[ssi2_ipg_gate] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0);  	clk[ssi1_ipg_gate] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1); diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c index 9d2c843bde0..b5deb055455 100644 --- a/arch/arm/mach-imx/mm-imx3.c +++ b/arch/arm/mach-imx/mm-imx3.c @@ -108,9 +108,8 @@ void __init imx3_init_l2x0(void)  	}  	l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096); -	if (IS_ERR(l2x0_base)) { -		printk(KERN_ERR "remapping L2 cache area failed with %ld\n", -				PTR_ERR(l2x0_base)); +	if (!l2x0_base) { +		printk(KERN_ERR "remapping L2 cache area failed\n");  		return;  	} diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 2a1a898c7f9..d669e227e00 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -11,7 +11,6 @@ config ARCH_OMAP2PLUS_TYPICAL  	select I2C_OMAP  	select MENELAUS if ARCH_OMAP2  	select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5 -	select PINCTRL  	select PM_RUNTIME  	select REGULATOR  	select SERIAL_OMAP diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 388c431c745..d41ab98890f 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -24,6 +24,7 @@  #include <linux/input.h>  #include <linux/gpio_keys.h>  #include <linux/opp.h> +#include <linux/cpu.h>  #include <linux/mtd/mtd.h>  #include <linux/mtd/partitions.h> @@ -444,27 +445,31 @@ static struct omap_board_mux board_mux[] __initdata = {  };  #endif -static void __init beagle_opp_init(void) +static int __init beagle_opp_init(void)  {  	int r = 0; -	/* Initialize the omap3 opp table */ -	if (omap3_opp_init()) { +	if (!machine_is_omap3_beagle()) +		return 0; + +	/* Initialize the omap3 opp table if not already created. */ +	r = omap3_opp_init(); +	if (IS_ERR_VALUE(r) && (r != -EEXIST)) {  		pr_err("%s: opp default init failed\n", __func__); -		return; +		return r;  	}  	/* Custom OPP enabled for all xM versions */  	if (cpu_is_omap3630()) {  		struct device *mpu_dev, *iva_dev; -		mpu_dev = omap_device_get_by_hwmod_name("mpu"); +		mpu_dev = get_cpu_device(0);  		iva_dev = omap_device_get_by_hwmod_name("iva");  		if (IS_ERR(mpu_dev) || IS_ERR(iva_dev)) {  			pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",  				__func__, mpu_dev, iva_dev); -			return; +			return -ENODEV;  		}  		/* Enable MPU 1GHz and lower opps */  		r = opp_enable(mpu_dev, 800000000); @@ -484,8 +489,9 @@ static void __init beagle_opp_init(void)  			opp_disable(iva_dev, 660000000);  		}  	} -	return; +	return 0;  } +device_initcall(beagle_opp_init);  static void __init omap3_beagle_init(void)  { @@ -522,8 +528,6 @@ static void __init omap3_beagle_init(void)  	/* Ensure SDRC pins are mux'd for self-refresh */  	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);  	omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); - -	beagle_opp_init();  }  MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c index 114ab4b8e0e..1a45d6bd253 100644 --- a/arch/arm/mach-omap2/clock33xx_data.c +++ b/arch/arm/mach-omap2/clock33xx_data.c @@ -1073,6 +1073,8 @@ static struct omap_clk am33xx_clks[] = {  	CLK(NULL,	"gfx_fck_div_ck",	&gfx_fck_div_ck,	CK_AM33XX),  	CLK(NULL,	"sysclkout_pre_ck",	&sysclkout_pre_ck,	CK_AM33XX),  	CLK(NULL,	"clkout2_ck",		&clkout2_ck,	CK_AM33XX), +	CLK(NULL,	"timer_32k_ck",		&clkdiv32k_ick,	CK_AM33XX), +	CLK(NULL,	"timer_sys_ck",		&sys_clkin_ck,	CK_AM33XX),  };  int __init am33xx_clk_init(void) diff --git a/arch/arm/mach-omap2/mux34xx.c b/arch/arm/mach-omap2/mux34xx.c index 17f80e4ab16..c47140bbbec 100644 --- a/arch/arm/mach-omap2/mux34xx.c +++ b/arch/arm/mach-omap2/mux34xx.c @@ -614,16 +614,16 @@ static struct omap_mux __initdata omap3_muxmodes[] = {  		"sys_off_mode", NULL, NULL, NULL,  		"gpio_9", NULL, NULL, "safe_mode"),  	_OMAP3_MUXENTRY(UART1_CTS, 150, -		"uart1_cts", NULL, NULL, NULL, +		"uart1_cts", "ssi1_rdy_tx", NULL, NULL,  		"gpio_150", "hsusb3_tll_clk", NULL, "safe_mode"),  	_OMAP3_MUXENTRY(UART1_RTS, 149, -		"uart1_rts", NULL, NULL, NULL, +		"uart1_rts", "ssi1_flag_tx", NULL, NULL,  		"gpio_149", NULL, NULL, "safe_mode"),  	_OMAP3_MUXENTRY(UART1_RX, 151, -		"uart1_rx", NULL, "mcbsp1_clkr", "mcspi4_clk", +		"uart1_rx", "ss1_wake_tx", "mcbsp1_clkr", "mcspi4_clk",  		"gpio_151", NULL, NULL, "safe_mode"),  	_OMAP3_MUXENTRY(UART1_TX, 148, -		"uart1_tx", NULL, NULL, NULL, +		"uart1_tx", "ssi1_dat_tx", NULL, NULL,  		"gpio_148", NULL, NULL, "safe_mode"),  	_OMAP3_MUXENTRY(UART2_CTS, 144,  		"uart2_cts", "mcbsp3_dx", "gpt9_pwm_evt", NULL, diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 686137d164d..67d66131cfa 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -91,6 +91,7 @@ extern void omap3_save_scratchpad_contents(void);  #define PM_RTA_ERRATUM_i608		(1 << 0)  #define PM_SDRC_WAKEUP_ERRATUM_i583	(1 << 1) +#define PM_PER_MEMORIES_ERRATUM_i582	(1 << 2)  #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)  extern u16 pm34xx_errata; diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index ba670db1fd3..3a904de4313 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -652,14 +652,17 @@ static void __init pm_errata_configure(void)  		/* Enable the l2 cache toggling in sleep logic */  		enable_omap3630_toggle_l2_on_restore();  		if (omap_rev() < OMAP3630_REV_ES1_2) -			pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583; +			pm34xx_errata |= (PM_SDRC_WAKEUP_ERRATUM_i583 | +					  PM_PER_MEMORIES_ERRATUM_i582); +	} else if (cpu_is_omap34xx()) { +		pm34xx_errata |= PM_PER_MEMORIES_ERRATUM_i582;  	}  }  int __init omap3_pm_init(void)  {  	struct power_state *pwrst, *tmp; -	struct clockdomain *neon_clkdm, *mpu_clkdm; +	struct clockdomain *neon_clkdm, *mpu_clkdm, *per_clkdm, *wkup_clkdm;  	int ret;  	if (!omap3_has_io_chain_ctrl()) @@ -711,6 +714,8 @@ int __init omap3_pm_init(void)  	neon_clkdm = clkdm_lookup("neon_clkdm");  	mpu_clkdm = clkdm_lookup("mpu_clkdm"); +	per_clkdm = clkdm_lookup("per_clkdm"); +	wkup_clkdm = clkdm_lookup("wkup_clkdm");  #ifdef CONFIG_SUSPEND  	omap_pm_suspend = omap3_pm_suspend; @@ -727,6 +732,27 @@ int __init omap3_pm_init(void)  	if (IS_PM34XX_ERRATUM(PM_RTA_ERRATUM_i608))  		omap3630_ctrl_disable_rta(); +	/* +	 * The UART3/4 FIFO and the sidetone memory in McBSP2/3 are +	 * not correctly reset when the PER powerdomain comes back +	 * from OFF or OSWR when the CORE powerdomain is kept active. +	 * See OMAP36xx Erratum i582 "PER Domain reset issue after +	 * Domain-OFF/OSWR Wakeup".  This wakeup dependency is not a +	 * complete workaround.  The kernel must also prevent the PER +	 * powerdomain from going to OSWR/OFF while the CORE +	 * powerdomain is not going to OSWR/OFF.  And if PER last +	 * power state was off while CORE last power state was ON, the +	 * UART3/4 and McBSP2/3 SIDETONE devices need to run a +	 * self-test using their loopback tests; if that fails, those +	 * devices are unusable until the PER/CORE can complete a transition +	 * from ON to OSWR/OFF and then back to ON. +	 * +	 * XXX Technically this workaround is only needed if off-mode +	 * or OSWR is enabled. +	 */ +	if (IS_PM34XX_ERRATUM(PM_PER_MEMORIES_ERRATUM_i582)) +		clkdm_add_wkdep(per_clkdm, wkup_clkdm); +  	clkdm_add_wkdep(neon_clkdm, mpu_clkdm);  	if (omap_type() != OMAP2_DEVICE_TYPE_GP) {  		omap3_secure_ram_storage = diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 0405c819080..a507cd6cf4f 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -329,6 +329,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,  	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt); +	if (console_uart_id == bdata->id) { +		omap_device_enable(pdev); +		pm_runtime_set_active(&pdev->dev); +	} +  	oh->dev_attr = uart;  	if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) diff --git a/arch/arm/mach-s3c24xx/s3c2416.c b/arch/arm/mach-s3c24xx/s3c2416.c index ed5a95ece9e..77ee0b73223 100644 --- a/arch/arm/mach-s3c24xx/s3c2416.c +++ b/arch/arm/mach-s3c24xx/s3c2416.c @@ -61,6 +61,7 @@  #include <plat/nand-core.h>  #include <plat/adc-core.h>  #include <plat/rtc-core.h> +#include <plat/spi-core.h>  static struct map_desc s3c2416_iodesc[] __initdata = {  	IODESC_ENT(WATCHDOG), @@ -132,6 +133,7 @@ void __init s3c2416_map_io(void)  	/* initialize device information early */  	s3c2416_default_sdhci0();  	s3c2416_default_sdhci1(); +	s3c64xx_spi_setname("s3c2443-spi");  	iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc));  } diff --git a/arch/arm/mach-s3c24xx/s3c2443.c b/arch/arm/mach-s3c24xx/s3c2443.c index ab648ad8fa5..165b6a6b3da 100644 --- a/arch/arm/mach-s3c24xx/s3c2443.c +++ b/arch/arm/mach-s3c24xx/s3c2443.c @@ -43,6 +43,7 @@  #include <plat/nand-core.h>  #include <plat/adc-core.h>  #include <plat/rtc-core.h> +#include <plat/spi-core.h>  static struct map_desc s3c2443_iodesc[] __initdata = {  	IODESC_ENT(WATCHDOG), @@ -100,6 +101,9 @@ void __init s3c2443_map_io(void)  	s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull;  	s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull; +	/* initialize device information early */ +	s3c64xx_spi_setname("s3c2443-spi"); +  	iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));  } diff --git a/arch/arm/mach-s5p64x0/common.c b/arch/arm/mach-s5p64x0/common.c index 6e6a0a9d677..111e404a81f 100644 --- a/arch/arm/mach-s5p64x0/common.c +++ b/arch/arm/mach-s5p64x0/common.c @@ -44,6 +44,7 @@  #include <plat/sdhci.h>  #include <plat/adc-core.h>  #include <plat/fb-core.h> +#include <plat/spi-core.h>  #include <plat/gpio-cfg.h>  #include <plat/regs-irqtype.h>  #include <plat/regs-serial.h> @@ -179,6 +180,7 @@ void __init s5p6440_map_io(void)  	/* initialize any device information early */  	s3c_adc_setname("s3c64xx-adc");  	s3c_fb_setname("s5p64x0-fb"); +	s3c64xx_spi_setname("s5p64x0-spi");  	s5p64x0_default_sdhci0();  	s5p64x0_default_sdhci1(); @@ -193,6 +195,7 @@ void __init s5p6450_map_io(void)  	/* initialize any device information early */  	s3c_adc_setname("s3c64xx-adc");  	s3c_fb_setname("s5p64x0-fb"); +	s3c64xx_spi_setname("s5p64x0-spi");  	s5p64x0_default_sdhci0();  	s5p64x0_default_sdhci1(); diff --git a/arch/arm/mach-s5pc100/common.c b/arch/arm/mach-s5pc100/common.c index 62190865886..cc6e561c995 100644 --- a/arch/arm/mach-s5pc100/common.c +++ b/arch/arm/mach-s5pc100/common.c @@ -45,6 +45,7 @@  #include <plat/fb-core.h>  #include <plat/iic-core.h>  #include <plat/onenand-core.h> +#include <plat/spi-core.h>  #include <plat/regs-serial.h>  #include <plat/watchdog-reset.h> @@ -165,6 +166,8 @@ void __init s5pc100_map_io(void)  	s3c_onenand_setname("s5pc100-onenand");  	s3c_fb_setname("s5pc100-fb");  	s3c_cfcon_setname("s5pc100-pata"); + +	s3c64xx_spi_setname("s5pc100-spi");  }  void __init s5pc100_init_clocks(int xtal) diff --git a/arch/arm/mach-s5pv210/common.c b/arch/arm/mach-s5pv210/common.c index 4c9e9027df9..a0c50efe814 100644 --- a/arch/arm/mach-s5pv210/common.c +++ b/arch/arm/mach-s5pv210/common.c @@ -43,6 +43,7 @@  #include <plat/iic-core.h>  #include <plat/keypad-core.h>  #include <plat/tv-core.h> +#include <plat/spi-core.h>  #include <plat/regs-serial.h>  #include "common.h" @@ -196,6 +197,8 @@ void __init s5pv210_map_io(void)  	/* setup TV devices */  	s5p_hdmi_setname("s5pv210-hdmi"); + +	s3c64xx_spi_setname("s5pv210-spi");  }  void __init s5pv210_init_clocks(int xtal) diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index 2917668f009..ebbffc25f24 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c @@ -247,7 +247,7 @@ void __init r8a7779_add_standard_devices(void)  {  #ifdef CONFIG_CACHE_L2X0  	/* Early BRESP enable, Shared attribute override enable, 64K*16way */ -	l2x0_init((void __iomem __force *)(0xf0100000), 0x40470000, 0x82000fff); +	l2x0_init(IOMEM(0xf0100000), 0x40470000, 0x82000fff);  #endif  	r8a7779_pm_init(); diff --git a/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h b/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h deleted file mode 100644 index e69de29bb2d..00000000000 --- a/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h +++ /dev/null diff --git a/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h b/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h deleted file mode 100644 index e69de29bb2d..00000000000 --- a/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h +++ /dev/null diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 2236cbd03cd..1f3fbc2bb77 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -16,6 +16,7 @@  #include <linux/stat.h>  #include <linux/of.h>  #include <linux/of_irq.h> +#include <linux/irq.h>  #include <linux/platform_data/clk-ux500.h>  #include <asm/hardware/gic.h> diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index b9f60ebe3bc..b820edaf318 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -745,7 +745,7 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,  static int  do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)  { -	union offset_union offset; +	union offset_union uninitialized_var(offset);  	unsigned long instr = 0, instrptr;  	int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);  	unsigned int type; @@ -856,8 +856,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)  		if (thumb2_32b) {  			offset.un = 0;  			handler = do_alignment_t32_to_handler(&instr, regs, &offset); -		} else +		} else { +			offset.un = 0;  			handler = do_alignment_ldmstm; +		}  		break;  	default: diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 477a2d23ddf..58bc3e4d3bd 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -610,7 +610,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,  			 gfp_t gfp, pgprot_t prot, bool is_coherent, const void *caller)  {  	u64 mask = get_coherent_dma_mask(dev); -	struct page *page; +	struct page *page = NULL;  	void *addr;  #ifdef CONFIG_DMA_API_DEBUG diff --git a/arch/arm/mm/vmregion.h b/arch/arm/mm/vmregion.h index bf312c354a2..0f5a5f2a2c7 100644 --- a/arch/arm/mm/vmregion.h +++ b/arch/arm/mm/vmregion.h @@ -17,7 +17,6 @@ struct arm_vmregion {  	struct list_head	vm_list;  	unsigned long		vm_start;  	unsigned long		vm_end; -	void			*priv;  	int			vm_active;  	const void		*caller;  }; diff --git a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c index 540d3a7d92d..e7b920b5867 100644 --- a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c +++ b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c @@ -55,7 +55,7 @@ struct platform_device *__init imx_add_mxc_mmc(  	struct resource res[] = {  		{  			.start = data->iobase, -			.end = data->iobase + SZ_4K - 1, +			.end = data->iobase + data->iosize - 1,  			.flags = IORESOURCE_MEM,  		}, {  			.start = data->irq, diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 7cd56ed5cd9..82fcb206b5b 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -26,6 +26,7 @@ config ARCH_OMAP2PLUS  	select CLKDEV_LOOKUP  	select GENERIC_IRQ_CHIP  	select OMAP_DM_TIMER +	select PINCTRL  	select PROC_DEVICETREE if PROC_FS  	select SPARSE_IRQ  	select USE_OF diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index f4a4cd01479..1957a8516e9 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -40,10 +40,10 @@  #define OMAP_UART_WER_MOD_WKUP	0X7F  /* Enable XON/XOFF flow control on output */ -#define OMAP_UART_SW_TX		0x8 +#define OMAP_UART_SW_TX		0x04  /* Enable XON/XOFF flow control on input */ -#define OMAP_UART_SW_RX		0x2 +#define OMAP_UART_SW_RX		0x04  #define OMAP_UART_SYSC_RESET	0X07  #define OMAP_UART_TCR_TRIG	0X0F diff --git a/arch/arm/plat-samsung/include/plat/spi-core.h b/arch/arm/plat-samsung/include/plat/spi-core.h new file mode 100644 index 00000000000..0b9428ab3fc --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/spi-core.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __PLAT_S3C_SPI_CORE_H +#define __PLAT_S3C_SPI_CORE_H + +/* These functions are only for use with the core support code, such as + * the cpu specific initialisation code + */ + +/* re-define device name depending on support. */ +static inline void s3c64xx_spi_setname(char *name) +{ +#ifdef CONFIG_S3C64XX_DEV_SPI0 +	s3c64xx_device_spi0.name = name; +#endif +#ifdef CONFIG_S3C64XX_DEV_SPI1 +	s3c64xx_device_spi1.name = name; +#endif +#ifdef CONFIG_S3C64XX_DEV_SPI2 +	s3c64xx_device_spi2.name = name; +#endif +} + +#endif /* __PLAT_S3C_SPI_CORE_H */ diff --git a/arch/arm/tools/Makefile b/arch/arm/tools/Makefile index 635cb1865e4..cd60a81163e 100644 --- a/arch/arm/tools/Makefile +++ b/arch/arm/tools/Makefile @@ -5,6 +5,6 @@  #  include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types -	@echo '  Generating $@' +	$(kecho) '  Generating $@'  	@mkdir -p $(dir $@)  	$(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; } diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index c834b32af27..3b44e0dd0a9 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -701,11 +701,14 @@ static int __init vfp_init(void)  			elf_hwcap |= HWCAP_VFPv3;  			/* -			 * Check for VFPv3 D16. CPUs in this configuration -			 * only have 16 x 64bit registers. +			 * Check for VFPv3 D16 and VFPv4 D16.  CPUs in +			 * this configuration only have 16 x 64bit +			 * registers.  			 */  			if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1) -				elf_hwcap |= HWCAP_VFPv3D16; +				elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */ +			else +				elf_hwcap |= HWCAP_VFPD32;  		}  #endif  		/* diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 59bcb96ac36..f5760927544 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -166,3 +166,14 @@ void free_xenballooned_pages(int nr_pages, struct page **pages)  	*pages = NULL;  }  EXPORT_SYMBOL_GPL(free_xenballooned_pages); + +/* In the hypervisor.S file. */ +EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_xen_version); +EXPORT_SYMBOL_GPL(HYPERVISOR_console_io); +EXPORT_SYMBOL_GPL(HYPERVISOR_sched_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op); +EXPORT_SYMBOL_GPL(privcmd_call); diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S index 074f5ed101b..71f723984cb 100644 --- a/arch/arm/xen/hypercall.S +++ b/arch/arm/xen/hypercall.S @@ -48,20 +48,16 @@  #include <linux/linkage.h>  #include <asm/assembler.h> +#include <asm/opcodes-virt.h>  #include <xen/interface/xen.h> -/* HVC 0xEA1 */ -#ifdef CONFIG_THUMB2_KERNEL -#define xen_hvc .word 0xf7e08ea1 -#else -#define xen_hvc .word 0xe140ea71 -#endif +#define XEN_IMM 0xEA1  #define HYPERCALL_SIMPLE(hypercall)		\  ENTRY(HYPERVISOR_##hypercall)			\  	mov r12, #__HYPERVISOR_##hypercall;	\ -	xen_hvc;							\ +	__HVC(XEN_IMM);						\  	mov pc, lr;							\  ENDPROC(HYPERVISOR_##hypercall) @@ -76,7 +72,7 @@ ENTRY(HYPERVISOR_##hypercall)			\  	stmdb sp!, {r4}						\  	ldr r4, [sp, #4]					\  	mov r12, #__HYPERVISOR_##hypercall;	\ -	xen_hvc								\ +	__HVC(XEN_IMM);						\  	ldm sp!, {r4}						\  	mov pc, lr							\  ENDPROC(HYPERVISOR_##hypercall) @@ -100,7 +96,7 @@ ENTRY(privcmd_call)  	mov r2, r3  	ldr r3, [sp, #8]  	ldr r4, [sp, #4] -	xen_hvc +	__HVC(XEN_IMM)  	ldm sp!, {r4}  	mov pc, lr  ENDPROC(privcmd_call); diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index ef54a59a9e8..15ac18a56c9 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1,6 +1,7 @@  config ARM64  	def_bool y  	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE +	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION  	select GENERIC_CLOCKEVENTS  	select GENERIC_HARDIRQS_NO_DEPRECATED  	select GENERIC_IOMAP diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index cf284649dfc..07fea290d7c 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -25,12 +25,10 @@  #include <asm/user.h>  typedef unsigned long elf_greg_t; -typedef unsigned long elf_freg_t[3];  #define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))  typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef struct user_fp elf_fpregset_t; +typedef struct user_fpsimd_state elf_fpregset_t;  #define EM_AARCH64		183 @@ -87,7 +85,6 @@ typedef struct user_fp elf_fpregset_t;  #define R_AARCH64_MOVW_PREL_G2_NC	292  #define R_AARCH64_MOVW_PREL_G3		293 -  /*   * These are used to set parameters in the core dumps.   */ diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h index b42fab9f62a..c43b4ac1300 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -25,9 +25,8 @@   *  - FPSR and FPCR   *  - 32 128-bit data registers   * - * Note that user_fp forms a prefix of this structure, which is relied - * upon in the ptrace FP/SIMD accessors. struct user_fpsimd_state must - * form a prefix of struct fpsimd_state. + * Note that user_fpsimd forms a prefix of this structure, which is + * relied upon in the ptrace FP/SIMD accessors.   */  struct fpsimd_state {  	union { diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 74a2a7d304a..54f6116697f 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h @@ -114,7 +114,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)   *  I/O port access primitives.   */  #define IO_SPACE_LIMIT		0xffff -#define PCI_IOBASE		((void __iomem *)0xffffffbbfffe0000UL) +#define PCI_IOBASE		((void __iomem *)(MODULES_VADDR - SZ_2M))  static inline u8 inb(unsigned long addr)  { @@ -225,9 +225,9 @@ extern void __iounmap(volatile void __iomem *addr);  #define PROT_DEVICE_nGnRE	(PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE))  #define PROT_NORMAL_NC		(PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC)) -#define ioremap(addr, size)		__ioremap((addr), (size), PROT_DEVICE_nGnRE) -#define ioremap_nocache(addr, size)	__ioremap((addr), (size), PROT_DEVICE_nGnRE) -#define ioremap_wc(addr, size)		__ioremap((addr), (size), PROT_NORMAL_NC) +#define ioremap(addr, size)		__ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE)) +#define ioremap_nocache(addr, size)	__ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE)) +#define ioremap_wc(addr, size)		__ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))  #define iounmap				__iounmap  #define ARCH_HAS_IOREMAP_WC diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 5d810044fed..77f696c1433 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -43,6 +43,8 @@  #else  #define STACK_TOP		STACK_TOP_MAX  #endif /* CONFIG_COMPAT */ + +#define ARCH_LOW_ADDRESS_LIMIT	PHYS_MASK  #endif /* __KERNEL__ */  struct debug_info { diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 63f853f8b71..68aff2816e8 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -14,7 +14,6 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */  #ifdef CONFIG_COMPAT -#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION  #define __ARCH_WANT_COMPAT_STAT64  #define __ARCH_WANT_SYS_GETHOSTNAME  #define __ARCH_WANT_SYS_PAUSE diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index ecbf2d81ec5..c76c7241125 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -613,17 +613,11 @@ enum armv8_pmuv3_perf_types {  	ARMV8_PMUV3_PERFCTR_BUS_ACCESS				= 0x19,  	ARMV8_PMUV3_PERFCTR_MEM_ERROR				= 0x1A,  	ARMV8_PMUV3_PERFCTR_BUS_CYCLES				= 0x1D, - -	/* -	 * This isn't an architected event. -	 * We detect this event number and use the cycle counter instead. -	 */ -	ARMV8_PMUV3_PERFCTR_CPU_CYCLES				= 0xFF,  };  /* PMUv3 HW events mapping. */  static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = { -	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CPU_CYCLES, +	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,  	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,  	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,  	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, @@ -1106,7 +1100,7 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc,  	unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT;  	/* Always place a cycle counter into the cycle counter. */ -	if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) { +	if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) {  		if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask))  			return -EAGAIN; diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index f22965ea1cf..e04cebdbb47 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -310,24 +310,6 @@ struct task_struct *__switch_to(struct task_struct *prev,  }  /* - * Fill in the task's elfregs structure for a core dump. - */ -int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs) -{ -	elf_core_copy_regs(elfregs, task_pt_regs(t)); -	return 1; -} - -/* - * fill in the fpe structure for a core dump... - */ -int dump_fpu (struct pt_regs *regs, struct user_fp *fp) -{ -	return 0; -} -EXPORT_SYMBOL(dump_fpu); - -/*   * Shuffle the argument into the correct register before calling the   * thread function.  x1 is the thread argument, x2 is the pointer to   * the thread function, and x3 points to the exit function. diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 226b6bf6e9c..538300f2273 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -211,8 +211,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)  	 * before we continue.  	 */  	set_cpu_online(cpu, true); -	while (!cpu_active(cpu)) -		cpu_relax(); +	complete(&cpu_running);  	/*  	 * OK, it's off to the idle thread for us diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index efbf7df05d3..4cd28931dba 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -80,7 +80,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)  #ifdef CONFIG_ZONE_DMA32  	/* 4GB maximum for 32-bit only capable devices */  	max_dma32 = min(max, MAX_DMA32_PFN); -	zone_size[ZONE_DMA32] = max_dma32 - min; +	zone_size[ZONE_DMA32] = max(min, max_dma32) - min;  #endif  	zone_size[ZONE_NORMAL] = max - max_dma32; diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig index b7412504f08..df2eb4bd9fa 100644 --- a/arch/frv/Kconfig +++ b/arch/frv/Kconfig @@ -13,6 +13,7 @@ config FRV  	select GENERIC_CPU_DEVICES  	select ARCH_WANT_IPC_PARSE_VERSION  	select GENERIC_KERNEL_THREAD +	select GENERIC_KERNEL_EXECVE  config ZONE_DMA  	bool diff --git a/arch/frv/boot/Makefile b/arch/frv/boot/Makefile index 6ae3254da01..636d5bbcd53 100644 --- a/arch/frv/boot/Makefile +++ b/arch/frv/boot/Makefile @@ -17,6 +17,8 @@ PARAMS_PHYS	 = 0x0207c000  INITRD_PHYS	 = 0x02180000  INITRD_VIRT	 = 0x02180000 +OBJCOPYFLAGS	:=-O binary -R .note -R .note.gnu.build-id -R .comment +  #  # If you don't define ZRELADDR above,  # then it defaults to ZTEXTADDR @@ -32,18 +34,18 @@ Image: $(obj)/Image  targets: $(obj)/Image  $(obj)/Image: vmlinux FORCE -	$(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@ +	$(OBJCOPY) $(OBJCOPYFLAGS) -S vmlinux $@  #$(obj)/Image:	$(CONFIGURE) $(SYSTEM) -#	$(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@ +#	$(OBJCOPY) $(OBJCOPYFLAGS) -g -S $(SYSTEM) $@  bzImage: zImage  zImage:	$(CONFIGURE) compressed/$(LINUX) -	$(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@ +	$(OBJCOPY) $(OBJCOPYFLAGS) -S compressed/$(LINUX) $@  bootpImage: bootp/bootp -	$(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@ +	$(OBJCOPY) $(OBJCOPYFLAGS) -S bootp/bootp $@  compressed/$(LINUX): $(LINUX) dep  	@$(MAKE) -C compressed $(LINUX) diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h index 266a5b25a0c..2358634cacc 100644 --- a/arch/frv/include/asm/unistd.h +++ b/arch/frv/include/asm/unistd.h @@ -30,7 +30,6 @@  #define __ARCH_WANT_SYS_RT_SIGACTION  #define __ARCH_WANT_SYS_RT_SIGSUSPEND  #define __ARCH_WANT_SYS_EXECVE -#define __ARCH_WANT_KERNEL_EXECVE  /*   * "Conditional" syscalls diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index ee0beb354e4..dfcd263c051 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S @@ -869,11 +869,6 @@ ret_from_kernel_thread:  	call		schedule_tail  	calll.p		@(gr21,gr0)  	or		gr20,gr20,gr8 -	bra		sys_exit - -	.globl		ret_from_kernel_execve -ret_from_kernel_execve: -	ori		gr28,0,sp  	bra		__syscall_exit  ################################################################################################### @@ -1080,27 +1075,10 @@ __entry_return_from_kernel_interrupt:  	subicc		gr5,#0,gr0,icc0  	beq		icc0,#0,__entry_return_direct -__entry_preempt_need_resched: -	ldi		@(gr15,#TI_FLAGS),gr4 -	andicc		gr4,#_TIF_NEED_RESCHED,gr0,icc0 -	beq		icc0,#1,__entry_return_direct - -	setlos		#PREEMPT_ACTIVE,gr5 -	sti		gr5,@(gr15,#TI_FLAGS) - -	andi		gr23,#~PSR_PIL,gr23 -	movgs		gr23,psr - -	call		schedule -	sti		gr0,@(gr15,#TI_PRE_COUNT) - -	movsg		psr,gr23 -	ori		gr23,#PSR_PIL_14,gr23 -	movgs		gr23,psr -	bra		__entry_preempt_need_resched -#else -	bra		__entry_return_direct +	subcc		gr0,gr0,gr0,icc2		/* set Z and clear C */ +	call		preempt_schedule_irq  #endif +	bra		__entry_return_direct  ############################################################################### diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index e1e3aa196aa..7e33215f1d8 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -181,6 +181,9 @@ int copy_thread(unsigned long clone_flags,  	childregs = (struct pt_regs *)  		(task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE); +	/* set up the userspace frame (the only place that the USP is stored) */ +	*childregs = *__kernel_frame0_ptr; +  	p->set_child_tid = p->clear_child_tid = NULL;  	p->thread.frame	 = childregs; @@ -191,10 +194,8 @@ int copy_thread(unsigned long clone_flags,  	p->thread.frame0 = childregs;  	if (unlikely(!regs)) { -		memset(childregs, 0, sizeof(struct pt_regs));  		childregs->gr9 = usp; /* function */  		childregs->gr8 = arg; -		childregs->psr = PSR_S;  		p->thread.pc = (unsigned long) ret_from_kernel_thread;  		save_user_regs(p->thread.user);  		return 0; diff --git a/arch/frv/mb93090-mb00/pci-dma-nommu.c b/arch/frv/mb93090-mb00/pci-dma-nommu.c index e47857f889b..b99c2a7cc7a 100644 --- a/arch/frv/mb93090-mb00/pci-dma-nommu.c +++ b/arch/frv/mb93090-mb00/pci-dma-nommu.c @@ -11,6 +11,7 @@  #include <linux/types.h>  #include <linux/slab.h> +#include <linux/export.h>  #include <linux/dma-mapping.h>  #include <linux/list.h>  #include <linux/pci.h> diff --git a/arch/h8300/include/asm/cache.h b/arch/h8300/include/asm/cache.h index c6350283649..05887a1d80e 100644 --- a/arch/h8300/include/asm/cache.h +++ b/arch/h8300/include/asm/cache.h @@ -2,7 +2,8 @@  #define __ARCH_H8300_CACHE_H  /* bytes per L1 cache line */ -#define        L1_CACHE_BYTES  4 +#define        L1_CACHE_SHIFT  2 +#define        L1_CACHE_BYTES  (1 << L1_CACHE_SHIFT)  /* m68k-elf-gcc  2.95.2 doesn't like these */ diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h index 55bde603521..ad2b924167d 100644 --- a/arch/s390/include/asm/cio.h +++ b/arch/s390/include/asm/cio.h @@ -9,6 +9,8 @@  #define LPM_ANYPATH 0xff  #define __MAX_CSSID 0 +#define __MAX_SUBCHANNEL 65535 +#define __MAX_SSID 3  #include <asm/scsw.h> diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index dd647c919a6..2d3b7cb2600 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -506,12 +506,15 @@ static inline int pud_bad(pud_t pud)  static inline int pmd_present(pmd_t pmd)  { -	return (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) != 0UL; +	unsigned long mask = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO; +	return (pmd_val(pmd) & mask) == _HPAGE_TYPE_NONE || +	       !(pmd_val(pmd) & _SEGMENT_ENTRY_INV);  }  static inline int pmd_none(pmd_t pmd)  { -	return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL; +	return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) && +	       !(pmd_val(pmd) & _SEGMENT_ENTRY_RO);  }  static inline int pmd_large(pmd_t pmd) @@ -1223,6 +1226,11 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)  }  #ifdef CONFIG_TRANSPARENT_HUGEPAGE + +#define SEGMENT_NONE	__pgprot(_HPAGE_TYPE_NONE) +#define SEGMENT_RO	__pgprot(_HPAGE_TYPE_RO) +#define SEGMENT_RW	__pgprot(_HPAGE_TYPE_RW) +  #define __HAVE_ARCH_PGTABLE_DEPOSIT  extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable); @@ -1242,16 +1250,15 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,  static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)  { -	unsigned long pgprot_pmd = 0; - -	if (pgprot_val(pgprot) & _PAGE_INVALID) { -		if (pgprot_val(pgprot) & _PAGE_SWT) -			pgprot_pmd |= _HPAGE_TYPE_NONE; -		pgprot_pmd |= _SEGMENT_ENTRY_INV; -	} -	if (pgprot_val(pgprot) & _PAGE_RO) -		pgprot_pmd |= _SEGMENT_ENTRY_RO; -	return pgprot_pmd; +	/* +	 * pgprot is PAGE_NONE, PAGE_RO, or PAGE_RW (see __Pxxx / __Sxxx) +	 * Convert to segment table entry format. +	 */ +	if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE)) +		return pgprot_val(SEGMENT_NONE); +	if (pgprot_val(pgprot) == pgprot_val(PAGE_RO)) +		return pgprot_val(SEGMENT_RO); +	return pgprot_val(SEGMENT_RW);  }  static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) @@ -1269,7 +1276,9 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)  static inline pmd_t pmd_mkwrite(pmd_t pmd)  { -	pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO; +	/* Do not clobber _HPAGE_TYPE_NONE pages! */ +	if (!(pmd_val(pmd) & _SEGMENT_ENTRY_INV)) +		pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;  	return pmd;  } diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S index bf053898630..b6506ee32a3 100644 --- a/arch/s390/kernel/sclp.S +++ b/arch/s390/kernel/sclp.S @@ -44,6 +44,12 @@ _sclp_wait_int:  #endif  	mvc	.LoldpswS1-.LbaseS1(16,%r13),0(%r8)  	mvc	0(16,%r8),0(%r9) +#ifdef CONFIG_64BIT +	epsw	%r6,%r7				# set current addressing mode +	nill	%r6,0x1				# in new psw (31 or 64 bit mode) +	nilh	%r7,0x8000 +	stm	%r6,%r7,0(%r8) +#endif  	lhi	%r6,0x0200			# cr mask for ext int (cr0.54)  	ltr	%r2,%r2  	jz	.LsetctS1 @@ -87,7 +93,7 @@ _sclp_wait_int:  	.long	0x00080000, 0x80000000+.LwaitS1	# PSW to handle ext int  #ifdef CONFIG_64BIT  .LextpswS1_64: -	.quad	0x0000000180000000, .LwaitS1	# PSW to handle ext int, 64 bit +	.quad	0, .LwaitS1			# PSW to handle ext int, 64 bit  #endif  .LwaitpswS1:  	.long	0x010a0000, 0x00000000+.LloopS1	# PSW to wait for ext int diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index 2d37bb861fa..9017a63dda3 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c @@ -39,7 +39,7 @@ static __always_inline unsigned long follow_table(struct mm_struct *mm,  	pmd = pmd_offset(pud, addr);  	if (pmd_none(*pmd))  		return -0x10UL; -	if (pmd_huge(*pmd)) { +	if (pmd_large(*pmd)) {  		if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))  			return -0x04UL;  		return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK); diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index 60acb93a468..8b8285310b5 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c @@ -126,7 +126,7 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr,  		 */  		if (pmd_none(pmd) || pmd_trans_splitting(pmd))  			return 0; -		if (unlikely(pmd_huge(pmd))) { +		if (unlikely(pmd_large(pmd))) {  			if (!gup_huge_pmd(pmdp, pmd, addr, next,  					  write, pages, nr))  				return 0; diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index b6b442b0d79..9f2edb5c555 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -20,6 +20,7 @@ config SPARC  	select HAVE_ARCH_TRACEHOOK  	select SYSCTL_EXCEPTION_TRACE  	select ARCH_WANT_OPTIONAL_GPIOLIB +	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE  	select RTC_CLASS  	select RTC_DRV_M48T59  	select HAVE_IRQ_WORK diff --git a/arch/sparc/crypto/Makefile b/arch/sparc/crypto/Makefile index 6ae1ad5e502..5d469d81761 100644 --- a/arch/sparc/crypto/Makefile +++ b/arch/sparc/crypto/Makefile @@ -13,13 +13,13 @@ obj-$(CONFIG_CRYPTO_DES_SPARC64) += camellia-sparc64.o  obj-$(CONFIG_CRYPTO_CRC32C_SPARC64) += crc32c-sparc64.o -sha1-sparc64-y := sha1_asm.o sha1_glue.o crop_devid.o -sha256-sparc64-y := sha256_asm.o sha256_glue.o crop_devid.o -sha512-sparc64-y := sha512_asm.o sha512_glue.o crop_devid.o -md5-sparc64-y := md5_asm.o md5_glue.o crop_devid.o +sha1-sparc64-y := sha1_asm.o sha1_glue.o +sha256-sparc64-y := sha256_asm.o sha256_glue.o +sha512-sparc64-y := sha512_asm.o sha512_glue.o +md5-sparc64-y := md5_asm.o md5_glue.o -aes-sparc64-y := aes_asm.o aes_glue.o crop_devid.o -des-sparc64-y := des_asm.o des_glue.o crop_devid.o -camellia-sparc64-y := camellia_asm.o camellia_glue.o crop_devid.o +aes-sparc64-y := aes_asm.o aes_glue.o +des-sparc64-y := des_asm.o des_glue.o +camellia-sparc64-y := camellia_asm.o camellia_glue.o -crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o crop_devid.o +crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c index 8f1c9980f63..3965d1d36df 100644 --- a/arch/sparc/crypto/aes_glue.c +++ b/arch/sparc/crypto/aes_glue.c @@ -475,3 +475,5 @@ MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated");  MODULE_ALIAS("aes"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/camellia_glue.c b/arch/sparc/crypto/camellia_glue.c index 42905c08429..62c89af3fd3 100644 --- a/arch/sparc/crypto/camellia_glue.c +++ b/arch/sparc/crypto/camellia_glue.c @@ -320,3 +320,5 @@ MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");  MODULE_ALIAS("aes"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/crc32c_glue.c b/arch/sparc/crypto/crc32c_glue.c index 0bd89cea8d8..5162fad912c 100644 --- a/arch/sparc/crypto/crc32c_glue.c +++ b/arch/sparc/crypto/crc32c_glue.c @@ -177,3 +177,5 @@ MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated");  MODULE_ALIAS("crc32c"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/des_glue.c b/arch/sparc/crypto/des_glue.c index c4940c2d307..41524cebcc4 100644 --- a/arch/sparc/crypto/des_glue.c +++ b/arch/sparc/crypto/des_glue.c @@ -527,3 +527,5 @@ MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated");  MODULE_ALIAS("des"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/md5_glue.c b/arch/sparc/crypto/md5_glue.c index 603d723038c..09a9ea1dfb6 100644 --- a/arch/sparc/crypto/md5_glue.c +++ b/arch/sparc/crypto/md5_glue.c @@ -186,3 +186,5 @@ MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated");  MODULE_ALIAS("md5"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/sha1_glue.c b/arch/sparc/crypto/sha1_glue.c index 2bbb20bee9f..6cd5f29e1e0 100644 --- a/arch/sparc/crypto/sha1_glue.c +++ b/arch/sparc/crypto/sha1_glue.c @@ -181,3 +181,5 @@ MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated");  MODULE_ALIAS("sha1"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/sha256_glue.c b/arch/sparc/crypto/sha256_glue.c index 591e656bd89..04f555ab268 100644 --- a/arch/sparc/crypto/sha256_glue.c +++ b/arch/sparc/crypto/sha256_glue.c @@ -239,3 +239,5 @@ MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 op  MODULE_ALIAS("sha224");  MODULE_ALIAS("sha256"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/sha512_glue.c b/arch/sparc/crypto/sha512_glue.c index 486f0a2b700..f04d1994d19 100644 --- a/arch/sparc/crypto/sha512_glue.c +++ b/arch/sparc/crypto/sha512_glue.c @@ -224,3 +224,5 @@ MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 op  MODULE_ALIAS("sha384");  MODULE_ALIAS("sha512"); + +#include "crop_devid.c" diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h index ce35a1cf1a2..be56a244c9c 100644 --- a/arch/sparc/include/asm/atomic_64.h +++ b/arch/sparc/include/asm/atomic_64.h @@ -1,7 +1,7 @@  /* atomic.h: Thankfully the V9 is at least reasonable for this   *           stuff.   * - * Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com) + * Copyright (C) 1996, 1997, 2000, 2012 David S. Miller (davem@redhat.com)   */  #ifndef __ARCH_SPARC64_ATOMIC__ @@ -106,6 +106,8 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)  #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) +extern long atomic64_dec_if_positive(atomic64_t *v); +  /* Atomic operations are already serializing */  #define smp_mb__before_atomic_dec()	barrier()  #define smp_mb__after_atomic_dec()	barrier() diff --git a/arch/sparc/include/asm/backoff.h b/arch/sparc/include/asm/backoff.h index db3af0d30fb..4e02086b839 100644 --- a/arch/sparc/include/asm/backoff.h +++ b/arch/sparc/include/asm/backoff.h @@ -1,6 +1,46 @@  #ifndef _SPARC64_BACKOFF_H  #define _SPARC64_BACKOFF_H +/* The macros in this file implement an exponential backoff facility + * for atomic operations. + * + * When multiple threads compete on an atomic operation, it is + * possible for one thread to be continually denied a successful + * completion of the compare-and-swap instruction.  Heavily + * threaded cpu implementations like Niagara can compound this + * problem even further. + * + * When an atomic operation fails and needs to be retried, we spin a + * certain number of times.  At each subsequent failure of the same + * operation we double the spin count, realizing an exponential + * backoff. + * + * When we spin, we try to use an operation that will cause the + * current cpu strand to block, and therefore make the core fully + * available to any other other runnable strands.  There are two + * options, based upon cpu capabilities. + * + * On all cpus prior to SPARC-T4 we do three dummy reads of the + * condition code register.  Each read blocks the strand for something + * between 40 and 50 cpu cycles. + * + * For SPARC-T4 and later we have a special "pause" instruction + * available.  This is implemented using writes to register %asr27. + * The cpu will block the number of cycles written into the register, + * unless a disrupting trap happens first.  SPARC-T4 specifically + * implements pause with a granularity of 8 cycles.  Each strand has + * an internal pause counter which decrements every 8 cycles.  So the + * chip shifts the %asr27 value down by 3 bits, and writes the result + * into the pause counter.  If a value smaller than 8 is written, the + * chip blocks for 1 cycle. + * + * To achieve the same amount of backoff as the three %ccr reads give + * on earlier chips, we shift the backoff value up by 7 bits.  (Three + * %ccr reads block for about 128 cycles, 1 << 7 == 128) We write the + * whole amount we want to block into the pause register, rather than + * loop writing 128 each time. + */ +  #define BACKOFF_LIMIT	(4 * 1024)  #ifdef CONFIG_SMP @@ -11,16 +51,25 @@  #define BACKOFF_LABEL(spin_label, continue_label) \  	spin_label -#define BACKOFF_SPIN(reg, tmp, label)	\ -	mov	reg, tmp; \ -88:	brnz,pt	tmp, 88b; \ -	 sub	tmp, 1, tmp; \ -	set	BACKOFF_LIMIT, tmp; \ -	cmp	reg, tmp; \ -	bg,pn	%xcc, label; \ -	 nop; \ -	ba,pt	%xcc, label; \ -	 sllx	reg, 1, reg; +#define BACKOFF_SPIN(reg, tmp, label)		\ +	mov		reg, tmp;		\ +88:	rd		%ccr, %g0;		\ +	rd		%ccr, %g0;		\ +	rd		%ccr, %g0;		\ +	.section	.pause_3insn_patch,"ax";\ +	.word		88b;			\ +	sllx		tmp, 7, tmp;		\ +	wr		tmp, 0, %asr27;		\ +	clr		tmp;			\ +	.previous;				\ +	brnz,pt		tmp, 88b;		\ +	 sub		tmp, 1, tmp;		\ +	set		BACKOFF_LIMIT, tmp;	\ +	cmp		reg, tmp;		\ +	bg,pn		%xcc, label;		\ +	 nop;					\ +	ba,pt		%xcc, label;		\ +	 sllx		reg, 1, reg;  #else diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index cef99fbc0a2..830502fe62b 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h @@ -232,9 +232,10 @@ static inline void __user *arch_compat_alloc_user_space(long len)  	struct pt_regs *regs = current_thread_info()->kregs;  	unsigned long usp = regs->u_regs[UREG_I6]; -	if (!(test_thread_flag(TIF_32BIT))) +	if (test_thread_64bit_stack(usp))  		usp += STACK_BIAS; -	else + +	if (test_thread_flag(TIF_32BIT))  		usp &= 0xffffffffUL;  	usp -= len; diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h index 4e5a483122a..721e25f0e2e 100644 --- a/arch/sparc/include/asm/processor_64.h +++ b/arch/sparc/include/asm/processor_64.h @@ -196,7 +196,22 @@ extern unsigned long get_wchan(struct task_struct *task);  #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->tpc)  #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->u_regs[UREG_FP]) -#define cpu_relax()	barrier() +/* Please see the commentary in asm/backoff.h for a description of + * what these instructions are doing and how they have been choosen. + * To make a long story short, we are trying to yield the current cpu + * strand during busy loops. + */ +#define cpu_relax()	asm volatile("\n99:\n\t"			\ +				     "rd	%%ccr, %%g0\n\t"	\ +				     "rd	%%ccr, %%g0\n\t"	\ +				     "rd	%%ccr, %%g0\n\t"	\ +				     ".section	.pause_3insn_patch,\"ax\"\n\t"\ +				     ".word	99b\n\t"		\ +				     "wr	%%g0, 128, %%asr27\n\t"	\ +				     "nop\n\t"				\ +				     "nop\n\t"				\ +				     ".previous"			\ +				     ::: "memory")  /* Prefetch support.  This is tuned for UltraSPARC-III and later.   * UltraSPARC-I will treat these as nops, and UltraSPARC-II has diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h index c2876511070..f93003123bc 100644 --- a/arch/sparc/include/asm/prom.h +++ b/arch/sparc/include/asm/prom.h @@ -63,5 +63,10 @@ extern char *of_console_options;  extern void irq_trans_init(struct device_node *dp);  extern char *build_path_component(struct device_node *dp); +/* SPARC has a local implementation */ +extern int of_address_to_resource(struct device_node *dev, int index, +				  struct resource *r); +#define of_address_to_resource of_address_to_resource +  #endif /* __KERNEL__ */  #endif /* _SPARC_PROM_H */ diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index 4e227663108..a3fe4dcc0aa 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h @@ -259,6 +259,11 @@ static inline bool test_and_clear_restore_sigmask(void)  #define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG) +#define thread32_stack_is_64bit(__SP) (((__SP) & 0x1) != 0) +#define test_thread_64bit_stack(__SP) \ +	((test_thread_flag(TIF_32BIT) && !thread32_stack_is_64bit(__SP)) ? \ +	 false : true) +  #endif	/* !__ASSEMBLY__ */  #endif /* __KERNEL__ */ diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h index 48f2807d326..71b5a67522a 100644 --- a/arch/sparc/include/asm/ttable.h +++ b/arch/sparc/include/asm/ttable.h @@ -372,7 +372,9 @@ etrap_spill_fixup_64bit:				\  /* Normal 32bit spill */  #define SPILL_2_GENERIC(ASI)				\ -	srl	%sp, 0, %sp;				\ +	and	%sp, 1, %g3;				\ +	brnz,pn	%g3, (. - (128 + 4));			\ +	 srl	%sp, 0, %sp;				\  	stwa	%l0, [%sp + %g0] ASI;			\  	mov	0x04, %g3;				\  	stwa	%l1, [%sp + %g3] ASI;			\ @@ -398,14 +400,16 @@ etrap_spill_fixup_64bit:				\  	stwa	%i6, [%g1 + %g0] ASI;			\  	stwa	%i7, [%g1 + %g3] ASI;			\  	saved;						\ -        retry; nop; nop;				\ +        retry;						\  	b,a,pt	%xcc, spill_fixup_dax;			\  	b,a,pt	%xcc, spill_fixup_mna;			\  	b,a,pt	%xcc, spill_fixup;  #define SPILL_2_GENERIC_ETRAP		\  etrap_user_spill_32bit:			\ -	srl	%sp, 0, %sp;		\ +	and	%sp, 1, %g3;		\ +	brnz,pn	%g3, etrap_user_spill_64bit;	\ +	 srl	%sp, 0, %sp;		\  	stwa	%l0, [%sp + 0x00] %asi;	\  	stwa	%l1, [%sp + 0x04] %asi;	\  	stwa	%l2, [%sp + 0x08] %asi;	\ @@ -427,7 +431,7 @@ etrap_user_spill_32bit:			\  	ba,pt	%xcc, etrap_save;	\  	 wrpr	%g1, %cwp;		\  	nop; nop; nop; nop;		\ -	nop; nop; nop; nop;		\ +	nop; nop;			\  	ba,a,pt	%xcc, etrap_spill_fixup_32bit; \  	ba,a,pt	%xcc, etrap_spill_fixup_32bit; \  	ba,a,pt	%xcc, etrap_spill_fixup_32bit; @@ -592,7 +596,9 @@ user_rtt_fill_64bit:					\  /* Normal 32bit fill */  #define FILL_2_GENERIC(ASI)				\ -	srl	%sp, 0, %sp;				\ +	and	%sp, 1, %g3;				\ +	brnz,pn	%g3, (. - (128 + 4));			\ +	 srl	%sp, 0, %sp;				\  	lduwa	[%sp + %g0] ASI, %l0;			\  	mov	0x04, %g2;				\  	mov	0x08, %g3;				\ @@ -616,14 +622,16 @@ user_rtt_fill_64bit:					\  	lduwa	[%g1 + %g3] ASI, %i6;			\  	lduwa	[%g1 + %g5] ASI, %i7;			\  	restored;					\ -	retry; nop; nop; nop; nop;			\ +	retry; nop; nop;				\  	b,a,pt	%xcc, fill_fixup_dax;			\  	b,a,pt	%xcc, fill_fixup_mna;			\  	b,a,pt	%xcc, fill_fixup;  #define FILL_2_GENERIC_RTRAP				\  user_rtt_fill_32bit:					\ -	srl	%sp, 0, %sp;				\ +	and	%sp, 1, %g3;				\ +	brnz,pn	%g3, user_rtt_fill_64bit;		\ +	 srl	%sp, 0, %sp;				\  	lduwa	[%sp + 0x00] %asi, %l0;			\  	lduwa	[%sp + 0x04] %asi, %l1;			\  	lduwa	[%sp + 0x08] %asi, %l2;			\ @@ -643,7 +651,7 @@ user_rtt_fill_32bit:					\  	ba,pt	%xcc, user_rtt_pre_restore;		\  	 restored;					\  	nop; nop; nop; nop; nop;			\ -	nop; nop; nop; nop; nop;			\ +	nop; nop; nop;					\  	ba,a,pt	%xcc, user_rtt_fill_fixup;		\  	ba,a,pt	%xcc, user_rtt_fill_fixup;		\  	ba,a,pt	%xcc, user_rtt_fill_fixup; diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h index 8974ef7ae92..cac719d1bc5 100644 --- a/arch/sparc/include/uapi/asm/unistd.h +++ b/arch/sparc/include/uapi/asm/unistd.h @@ -405,8 +405,13 @@  #define __NR_setns		337  #define __NR_process_vm_readv	338  #define __NR_process_vm_writev	339 +#define __NR_kern_features	340 +#define __NR_kcmp		341 -#define NR_syscalls		340 +#define NR_syscalls		342 + +/* Bitmask values returned from kern_features system call.  */ +#define KERN_FEATURE_MIXED_MODE_STACK	0x00000001  #ifdef __32bit_syscall_numbers__  /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h index 0c218e4c088..cc3c5cb47cd 100644 --- a/arch/sparc/kernel/entry.h +++ b/arch/sparc/kernel/entry.h @@ -59,6 +59,13 @@ struct popc_6insn_patch_entry {  extern struct popc_6insn_patch_entry __popc_6insn_patch,  	__popc_6insn_patch_end; +struct pause_patch_entry { +	unsigned int	addr; +	unsigned int	insns[3]; +}; +extern struct pause_patch_entry __pause_3insn_patch, +	__pause_3insn_patch_end; +  extern void __init per_cpu_patch(void);  extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,  				    struct sun4v_1insn_patch_entry *); diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index f8b6eee40bd..87f60ee6543 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -56,11 +56,13 @@ static inline unsigned int leon_eirq_get(int cpu)  static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc)  {  	unsigned int eirq; +	struct irq_bucket *p;  	int cpu = sparc_leon3_cpuid();  	eirq = leon_eirq_get(cpu); -	if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */ -		generic_handle_irq(irq_map[eirq]->irq); +	p = irq_map[eirq]; +	if ((eirq & 0x10) && p && p->irq) /* bit4 tells if IRQ happened */ +		generic_handle_irq(p->irq);  }  /* The extended IRQ controller has been found, this function registers it */ diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 885a8af7406..b5c38faa4ea 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -1762,15 +1762,25 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,  	ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;  	do { -		struct sparc_stackf32 *usf, sf;  		unsigned long pc; -		usf = (struct sparc_stackf32 *) ufp; -		if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) -			break; +		if (thread32_stack_is_64bit(ufp)) { +			struct sparc_stackf *usf, sf; -		pc = sf.callers_pc; -		ufp = (unsigned long)sf.fp; +			ufp += STACK_BIAS; +			usf = (struct sparc_stackf *) ufp; +			if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) +				break; +			pc = sf.callers_pc & 0xffffffff; +			ufp = ((unsigned long) sf.fp) & 0xffffffff; +		} else { +			struct sparc_stackf32 *usf, sf; +			usf = (struct sparc_stackf32 *) ufp; +			if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) +				break; +			pc = sf.callers_pc; +			ufp = (unsigned long)sf.fp; +		}  		perf_callchain_store(entry, pc);  	} while (entry->nr < PERF_MAX_STACK_DEPTH);  } diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index d778248ef3f..c6e0c291004 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -452,13 +452,16 @@ void flush_thread(void)  /* It's a bit more tricky when 64-bit tasks are involved... */  static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)  { +	bool stack_64bit = test_thread_64bit_stack(psp);  	unsigned long fp, distance, rval; -	if (!(test_thread_flag(TIF_32BIT))) { +	if (stack_64bit) {  		csp += STACK_BIAS;  		psp += STACK_BIAS;  		__get_user(fp, &(((struct reg_window __user *)psp)->ins[6]));  		fp += STACK_BIAS; +		if (test_thread_flag(TIF_32BIT)) +			fp &= 0xffffffff;  	} else  		__get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6])); @@ -472,7 +475,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)  	rval = (csp - distance);  	if (copy_in_user((void __user *) rval, (void __user *) psp, distance))  		rval = 0; -	else if (test_thread_flag(TIF_32BIT)) { +	else if (!stack_64bit) {  		if (put_user(((u32)csp),  			     &(((struct reg_window32 __user *)rval)->ins[6])))  			rval = 0; @@ -507,18 +510,18 @@ void synchronize_user_stack(void)  	flush_user_windows();  	if ((window = get_thread_wsaved()) != 0) { -		int winsize = sizeof(struct reg_window); -		int bias = 0; - -		if (test_thread_flag(TIF_32BIT)) -			winsize = sizeof(struct reg_window32); -		else -			bias = STACK_BIAS; -  		window -= 1;  		do { -			unsigned long sp = (t->rwbuf_stkptrs[window] + bias);  			struct reg_window *rwin = &t->reg_window[window]; +			int winsize = sizeof(struct reg_window); +			unsigned long sp; + +			sp = t->rwbuf_stkptrs[window]; + +			if (test_thread_64bit_stack(sp)) +				sp += STACK_BIAS; +			else +				winsize = sizeof(struct reg_window32);  			if (!copy_to_user((char __user *)sp, rwin, winsize)) {  				shift_window_buffer(window, get_thread_wsaved() - 1, t); @@ -544,13 +547,6 @@ void fault_in_user_windows(void)  {  	struct thread_info *t = current_thread_info();  	unsigned long window; -	int winsize = sizeof(struct reg_window); -	int bias = 0; - -	if (test_thread_flag(TIF_32BIT)) -		winsize = sizeof(struct reg_window32); -	else -		bias = STACK_BIAS;  	flush_user_windows();  	window = get_thread_wsaved(); @@ -558,8 +554,16 @@ void fault_in_user_windows(void)  	if (likely(window != 0)) {  		window -= 1;  		do { -			unsigned long sp = (t->rwbuf_stkptrs[window] + bias);  			struct reg_window *rwin = &t->reg_window[window]; +			int winsize = sizeof(struct reg_window); +			unsigned long sp; + +			sp = t->rwbuf_stkptrs[window]; + +			if (test_thread_64bit_stack(sp)) +				sp += STACK_BIAS; +			else +				winsize = sizeof(struct reg_window32);  			if (unlikely(sp & 0x7UL))  				stack_unaligned(sp); diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c index 484dabac704..7ff45e4ba68 100644 --- a/arch/sparc/kernel/ptrace_64.c +++ b/arch/sparc/kernel/ptrace_64.c @@ -151,7 +151,7 @@ static int regwindow64_get(struct task_struct *target,  {  	unsigned long rw_addr = regs->u_regs[UREG_I6]; -	if (test_tsk_thread_flag(current, TIF_32BIT)) { +	if (!test_thread_64bit_stack(rw_addr)) {  		struct reg_window32 win32;  		int i; @@ -176,7 +176,7 @@ static int regwindow64_set(struct task_struct *target,  {  	unsigned long rw_addr = regs->u_regs[UREG_I6]; -	if (test_tsk_thread_flag(current, TIF_32BIT)) { +	if (!test_thread_64bit_stack(rw_addr)) {  		struct reg_window32 win32;  		int i; diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 0800e71d8a8..0eaf0059aae 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -316,6 +316,25 @@ static void __init popc_patch(void)  	}  } +static void __init pause_patch(void) +{ +	struct pause_patch_entry *p; + +	p = &__pause_3insn_patch; +	while (p < &__pause_3insn_patch_end) { +		unsigned long i, addr = p->addr; + +		for (i = 0; i < 3; i++) { +			*(unsigned int *) (addr +  (i * 4)) = p->insns[i]; +			wmb(); +			__asm__ __volatile__("flush	%0" +					     : : "r" (addr +  (i * 4))); +		} + +		p++; +	} +} +  #ifdef CONFIG_SMP  void __init boot_cpu_id_too_large(int cpu)  { @@ -528,6 +547,8 @@ static void __init init_sparc64_elf_hwcap(void)  	if (sparc64_elf_hwcap & AV_SPARC_POPC)  		popc_patch(); +	if (sparc64_elf_hwcap & AV_SPARC_PAUSE) +		pause_patch();  }  void __init setup_arch(char **cmdline_p) diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 11c6c9603e7..878ef3d5fec 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -751,3 +751,8 @@ int kernel_execve(const char *filename,  		      : "cc");  	return __res;  } + +asmlinkage long sys_kern_features(void) +{ +	return KERN_FEATURE_MIXED_MODE_STACK; +} diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index 63402f9e9f5..5147f574f12 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -85,3 +85,4 @@ sys_call_table:  /*325*/	.long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init  /*330*/	.long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime  /*335*/	.long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev +/*340*/	.long sys_ni_syscall, sys_kcmp diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 3a58e0d66f5..1c9af9fa38e 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -86,6 +86,7 @@ sys_call_table32:  	.word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init  /*330*/	.word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime  	.word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev +/*340*/	.word sys_kern_features, sys_kcmp  #endif /* CONFIG_COMPAT */ @@ -163,3 +164,4 @@ sys_call_table:  	.word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init  /*330*/	.word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime  	.word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev +/*340*/	.word sys_kern_features, sys_kcmp diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c index f81d038f734..8201c25e766 100644 --- a/arch/sparc/kernel/unaligned_64.c +++ b/arch/sparc/kernel/unaligned_64.c @@ -113,21 +113,24 @@ static inline long sign_extend_imm13(long imm)  static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)  { -	unsigned long value; +	unsigned long value, fp;  	if (reg < 16)  		return (!reg ? 0 : regs->u_regs[reg]); + +	fp = regs->u_regs[UREG_FP]; +  	if (regs->tstate & TSTATE_PRIV) {  		struct reg_window *win; -		win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); +		win = (struct reg_window *)(fp + STACK_BIAS);  		value = win->locals[reg - 16]; -	} else if (test_thread_flag(TIF_32BIT)) { +	} else if (!test_thread_64bit_stack(fp)) {  		struct reg_window32 __user *win32; -		win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); +		win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));  		get_user(value, &win32->locals[reg - 16]);  	} else {  		struct reg_window __user *win; -		win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); +		win = (struct reg_window __user *)(fp + STACK_BIAS);  		get_user(value, &win->locals[reg - 16]);  	}  	return value; @@ -135,19 +138,24 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)  static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)  { +	unsigned long fp; +  	if (reg < 16)  		return ®s->u_regs[reg]; + +	fp = regs->u_regs[UREG_FP]; +  	if (regs->tstate & TSTATE_PRIV) {  		struct reg_window *win; -		win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); +		win = (struct reg_window *)(fp + STACK_BIAS);  		return &win->locals[reg - 16]; -	} else if (test_thread_flag(TIF_32BIT)) { +	} else if (!test_thread_64bit_stack(fp)) {  		struct reg_window32 *win32; -		win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP])); +		win32 = (struct reg_window32 *)((unsigned long)((u32)fp));  		return (unsigned long *)&win32->locals[reg - 16];  	} else {  		struct reg_window *win; -		win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); +		win = (struct reg_window *)(fp + STACK_BIAS);  		return &win->locals[reg - 16];  	}  } @@ -392,13 +400,15 @@ int handle_popc(u32 insn, struct pt_regs *regs)  		if (rd)  			regs->u_regs[rd] = ret;  	} else { -		if (test_thread_flag(TIF_32BIT)) { +		unsigned long fp = regs->u_regs[UREG_FP]; + +		if (!test_thread_64bit_stack(fp)) {  			struct reg_window32 __user *win32; -			win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); +			win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));  			put_user(ret, &win32->locals[rd - 16]);  		} else {  			struct reg_window __user *win; -			win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); +			win = (struct reg_window __user *)(fp + STACK_BIAS);  			put_user(ret, &win->locals[rd - 16]);  		}  	} @@ -554,7 +564,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs)  		reg[0] = 0;  		if ((insn & 0x780000) == 0x180000)  			reg[1] = 0; -	} else if (test_thread_flag(TIF_32BIT)) { +	} else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {  		put_user(0, (int __user *) reg);  		if ((insn & 0x780000) == 0x180000)  			put_user(0, ((int __user *) reg) + 1); diff --git a/arch/sparc/kernel/visemul.c b/arch/sparc/kernel/visemul.c index 08e074b7eb6..c096c624ac4 100644 --- a/arch/sparc/kernel/visemul.c +++ b/arch/sparc/kernel/visemul.c @@ -149,21 +149,24 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,  static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)  { -	unsigned long value; +	unsigned long value, fp;  	if (reg < 16)  		return (!reg ? 0 : regs->u_regs[reg]); + +	fp = regs->u_regs[UREG_FP]; +  	if (regs->tstate & TSTATE_PRIV) {  		struct reg_window *win; -		win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); +		win = (struct reg_window *)(fp + STACK_BIAS);  		value = win->locals[reg - 16]; -	} else if (test_thread_flag(TIF_32BIT)) { +	} else if (!test_thread_64bit_stack(fp)) {  		struct reg_window32 __user *win32; -		win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); +		win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));  		get_user(value, &win32->locals[reg - 16]);  	} else {  		struct reg_window __user *win; -		win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); +		win = (struct reg_window __user *)(fp + STACK_BIAS);  		get_user(value, &win->locals[reg - 16]);  	}  	return value; @@ -172,16 +175,18 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)  static inline unsigned long __user *__fetch_reg_addr_user(unsigned int reg,  							  struct pt_regs *regs)  { +	unsigned long fp = regs->u_regs[UREG_FP]; +  	BUG_ON(reg < 16);  	BUG_ON(regs->tstate & TSTATE_PRIV); -	if (test_thread_flag(TIF_32BIT)) { +	if (!test_thread_64bit_stack(fp)) {  		struct reg_window32 __user *win32; -		win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); +		win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));  		return (unsigned long __user *)&win32->locals[reg - 16];  	} else {  		struct reg_window __user *win; -		win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); +		win = (struct reg_window __user *)(fp + STACK_BIAS);  		return &win->locals[reg - 16];  	}  } @@ -204,7 +209,7 @@ static void store_reg(struct pt_regs *regs, unsigned long val, unsigned long rd)  	} else {  		unsigned long __user *rd_user = __fetch_reg_addr_user(rd, regs); -		if (test_thread_flag(TIF_32BIT)) +		if (!test_thread_64bit_stack(regs->u_regs[UREG_FP]))  			__put_user((u32)val, (u32 __user *)rd_user);  		else  			__put_user(val, rd_user); diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 89c2c29f154..0bacceb1915 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -132,6 +132,11 @@ SECTIONS  		*(.popc_6insn_patch)  		__popc_6insn_patch_end = .;  	} +	.pause_3insn_patch : { +		__pause_3insn_patch = .; +		*(.pause_3insn_patch) +		__pause_3insn_patch_end = .; +	}  	PERCPU_SECTION(SMP_CACHE_BYTES)  	. = ALIGN(PAGE_SIZE); diff --git a/arch/sparc/kernel/winfixup.S b/arch/sparc/kernel/winfixup.S index a6b0863c27d..1e67ce95836 100644 --- a/arch/sparc/kernel/winfixup.S +++ b/arch/sparc/kernel/winfixup.S @@ -43,6 +43,8 @@ spill_fixup_mna:  spill_fixup_dax:  	TRAP_LOAD_THREAD_REG(%g6, %g1)  	ldx	[%g6 + TI_FLAGS], %g1 +	andcc	%sp, 0x1, %g0 +	movne	%icc, 0, %g1  	andcc	%g1, _TIF_32BIT, %g0  	ldub	[%g6 + TI_WSAVED], %g1  	sll	%g1, 3, %g3 diff --git a/arch/sparc/lib/atomic_64.S b/arch/sparc/lib/atomic_64.S index 4d502da3de7..85c233d0a34 100644 --- a/arch/sparc/lib/atomic_64.S +++ b/arch/sparc/lib/atomic_64.S @@ -1,6 +1,6 @@  /* atomic.S: These things are too big to do inline.   * - * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 1999, 2007 2012 David S. Miller (davem@davemloft.net)   */  #include <linux/linkage.h> @@ -117,3 +117,17 @@ ENTRY(atomic64_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */  	 sub	%g1, %o0, %o0  2:	BACKOFF_SPIN(%o2, %o3, 1b)  ENDPROC(atomic64_sub_ret) + +ENTRY(atomic64_dec_if_positive) /* %o0 = atomic_ptr */ +	BACKOFF_SETUP(%o2) +1:	ldx	[%o0], %g1 +	brlez,pn %g1, 3f +	 sub	%g1, 1, %g7 +	casx	[%o0], %g1, %g7 +	cmp	%g1, %g7 +	bne,pn	%xcc, BACKOFF_LABEL(2f, 1b) +	 nop +3:	retl +	 sub	%g1, 1, %o0 +2:	BACKOFF_SPIN(%o2, %o3, 1b) +ENDPROC(atomic64_dec_if_positive) diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c index ee31b884c61..0c4e35e522f 100644 --- a/arch/sparc/lib/ksyms.c +++ b/arch/sparc/lib/ksyms.c @@ -116,6 +116,7 @@ EXPORT_SYMBOL(atomic64_add);  EXPORT_SYMBOL(atomic64_add_ret);  EXPORT_SYMBOL(atomic64_sub);  EXPORT_SYMBOL(atomic64_sub_ret); +EXPORT_SYMBOL(atomic64_dec_if_positive);  /* Atomic bit operations. */  EXPORT_SYMBOL(test_and_set_bit); diff --git a/arch/sparc/math-emu/math_64.c b/arch/sparc/math-emu/math_64.c index 1704068da92..034aadbff03 100644 --- a/arch/sparc/math-emu/math_64.c +++ b/arch/sparc/math-emu/math_64.c @@ -320,7 +320,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap)  					XR = 0;  				else if (freg < 16)  					XR = regs->u_regs[freg]; -				else if (test_thread_flag(TIF_32BIT)) { +				else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {  					struct reg_window32 __user *win32;  					flushw_user ();  					win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index c9dcc181d4d..6e8fdf5ad11 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -35,7 +35,7 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);  #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)	\  	efi_call_virt(f, a1, a2, a3, a4, a5, a6) -#define efi_ioremap(addr, size, type)		ioremap_cache(addr, size) +#define efi_ioremap(addr, size, type, attr)	ioremap_cache(addr, size)  #else /* !CONFIG_X86_32 */ @@ -89,7 +89,7 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,  		  (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))  extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, -				 u32 type); +				 u32 type, u64 attribute);  #endif /* CONFIG_X86_32 */ @@ -98,6 +98,8 @@ extern void efi_set_executable(efi_memory_desc_t *md, bool executable);  extern int efi_memblock_x86_reserve_range(void);  extern void efi_call_phys_prelog(void);  extern void efi_call_phys_epilog(void); +extern void efi_unmap_memmap(void); +extern void efi_memory_uc(u64 addr, unsigned long size);  #ifndef CONFIG_EFI  /* diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h index 59c226d120c..c20d1ce62dc 100644 --- a/arch/x86/include/asm/xen/hypercall.h +++ b/arch/x86/include/asm/xen/hypercall.h @@ -359,18 +359,14 @@ HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,  		return _hypercall4(int, update_va_mapping, va,  				   new_val.pte, new_val.pte >> 32, flags);  } +extern int __must_check xen_event_channel_op_compat(int, void *);  static inline int  HYPERVISOR_event_channel_op(int cmd, void *arg)  {  	int rc = _hypercall2(int, event_channel_op, cmd, arg); -	if (unlikely(rc == -ENOSYS)) { -		struct evtchn_op op; -		op.cmd = cmd; -		memcpy(&op.u, arg, sizeof(op.u)); -		rc = _hypercall1(int, event_channel_op_compat, &op); -		memcpy(arg, &op.u, sizeof(op.u)); -	} +	if (unlikely(rc == -ENOSYS)) +		rc = xen_event_channel_op_compat(cmd, arg);  	return rc;  } @@ -386,17 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str)  	return _hypercall3(int, console_io, cmd, count, str);  } +extern int __must_check HYPERVISOR_physdev_op_compat(int, void *); +  static inline int  HYPERVISOR_physdev_op(int cmd, void *arg)  {  	int rc = _hypercall2(int, physdev_op, cmd, arg); -	if (unlikely(rc == -ENOSYS)) { -		struct physdev_op op; -		op.cmd = cmd; -		memcpy(&op.u, arg, sizeof(op.u)); -		rc = _hypercall1(int, physdev_op_compat, &op); -		memcpy(arg, &op.u, sizeof(op.u)); -	} +	if (unlikely(rc == -ENOSYS)) +		rc = HYPERVISOR_physdev_op_compat(cmd, arg);  	return rc;  } diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h index 66d0fff1ee8..125f344f06a 100644 --- a/arch/x86/include/asm/xen/hypervisor.h +++ b/arch/x86/include/asm/xen/hypervisor.h @@ -33,7 +33,6 @@  #ifndef _ASM_X86_XEN_HYPERVISOR_H  #define _ASM_X86_XEN_HYPERVISOR_H -/* arch/i386/kernel/setup.c */  extern struct shared_info *HYPERVISOR_shared_info;  extern struct start_info *xen_start_info; diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index c265593ec2c..1817fa91102 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2257,6 +2257,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)  			continue;  		cfg = irq_cfg(irq); +		if (!cfg) +			continue; +  		raw_spin_lock(&desc->lock);  		/* diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 3373f84d139..4a3374e61a9 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -208,12 +208,14 @@ static bool check_hw_exists(void)  	}  	/* -	 * Now write a value and read it back to see if it matches, -	 * this is needed to detect certain hardware emulators (qemu/kvm) -	 * that don't trap on the MSR access and always return 0s. +	 * Read the current value, change it and read it back to see if it +	 * matches, this is needed to detect certain hardware emulators +	 * (qemu/kvm) that don't trap on the MSR access and always return 0s.  	 */ -	val = 0xabcdUL;  	reg = x86_pmu_event_addr(0); +	if (rdmsrl_safe(reg, &val)) +		goto msr_fail; +	val ^= 0xffffUL;  	ret = wrmsrl_safe(reg, val);  	ret |= rdmsrl_safe(reg, &val_new);  	if (ret || val != val_new) diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 5df8d32ba91..3cf3d97cce3 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -118,22 +118,24 @@ static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box)  {  	struct pci_dev *pdev = box->pci_dev;  	int box_ctl = uncore_pci_box_ctl(box); -	u32 config; +	u32 config = 0; -	pci_read_config_dword(pdev, box_ctl, &config); -	config |= SNBEP_PMON_BOX_CTL_FRZ; -	pci_write_config_dword(pdev, box_ctl, config); +	if (!pci_read_config_dword(pdev, box_ctl, &config)) { +		config |= SNBEP_PMON_BOX_CTL_FRZ; +		pci_write_config_dword(pdev, box_ctl, config); +	}  }  static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box)  {  	struct pci_dev *pdev = box->pci_dev;  	int box_ctl = uncore_pci_box_ctl(box); -	u32 config; +	u32 config = 0; -	pci_read_config_dword(pdev, box_ctl, &config); -	config &= ~SNBEP_PMON_BOX_CTL_FRZ; -	pci_write_config_dword(pdev, box_ctl, config); +	if (!pci_read_config_dword(pdev, box_ctl, &config)) { +		config &= ~SNBEP_PMON_BOX_CTL_FRZ; +		pci_write_config_dword(pdev, box_ctl, config); +	}  }  static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, struct perf_event *event) @@ -156,7 +158,7 @@ static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, struct pe  {  	struct pci_dev *pdev = box->pci_dev;  	struct hw_perf_event *hwc = &event->hw; -	u64 count; +	u64 count = 0;  	pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count);  	pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1); @@ -603,11 +605,12 @@ static struct pci_driver snbep_uncore_pci_driver = {  /*   * build pci bus to socket mapping   */ -static void snbep_pci2phy_map_init(void) +static int snbep_pci2phy_map_init(void)  {  	struct pci_dev *ubox_dev = NULL;  	int i, bus, nodeid; -	u32 config; +	int err = 0; +	u32 config = 0;  	while (1) {  		/* find the UBOX device */ @@ -618,10 +621,14 @@ static void snbep_pci2phy_map_init(void)  			break;  		bus = ubox_dev->bus->number;  		/* get the Node ID of the local register */ -		pci_read_config_dword(ubox_dev, 0x40, &config); +		err = pci_read_config_dword(ubox_dev, 0x40, &config); +		if (err) +			break;  		nodeid = config;  		/* get the Node ID mapping */ -		pci_read_config_dword(ubox_dev, 0x54, &config); +		err = pci_read_config_dword(ubox_dev, 0x54, &config); +		if (err) +			break;  		/*  		 * every three bits in the Node ID mapping register maps  		 * to a particular node. @@ -633,7 +640,11 @@ static void snbep_pci2phy_map_init(void)  			}  		}  	}; -	return; + +	if (ubox_dev) +		pci_dev_put(ubox_dev); + +	return err ? pcibios_err_to_errno(err) : 0;  }  /* end of Sandy Bridge-EP uncore support */ @@ -1547,7 +1558,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)  {  	struct hw_perf_event *hwc = &event->hw;  	struct hw_perf_event_extra *reg1 = &hwc->extra_reg; -	int port;  	/* adjust the main event selector and extra register index */  	if (reg1->idx % 2) { @@ -1559,7 +1569,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)  	}  	/* adjust extra register config */ -	port = reg1->idx / 6 + box->pmu->pmu_idx * 4;  	switch (reg1->idx % 6) {  	case 2:  		/* shift the 8~15 bits to the 0~7 bits */ @@ -2578,9 +2587,11 @@ static int __init uncore_pci_init(void)  	switch (boot_cpu_data.x86_model) {  	case 45: /* Sandy Bridge-EP */ +		ret = snbep_pci2phy_map_init(); +		if (ret) +			return ret;  		pci_uncores = snbep_pci_uncores;  		uncore_pci_driver = &snbep_uncore_pci_driver; -		snbep_pci2phy_map_init();  		break;  	default:  		return 0; diff --git a/arch/x86/kernel/cpu/perf_event_knc.c b/arch/x86/kernel/cpu/perf_event_knc.c index 7c46bfdbc37..4b7731bf23a 100644 --- a/arch/x86/kernel/cpu/perf_event_knc.c +++ b/arch/x86/kernel/cpu/perf_event_knc.c @@ -3,6 +3,8 @@  #include <linux/perf_event.h>  #include <linux/types.h> +#include <asm/hardirq.h> +  #include "perf_event.h"  static const u64 knc_perfmon_event_map[] = @@ -173,30 +175,100 @@ static void knc_pmu_enable_all(int added)  static inline void  knc_pmu_disable_event(struct perf_event *event)  { -	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);  	struct hw_perf_event *hwc = &event->hw;  	u64 val;  	val = hwc->config; -	if (cpuc->enabled) -		val &= ~ARCH_PERFMON_EVENTSEL_ENABLE; +	val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;  	(void)wrmsrl_safe(hwc->config_base + hwc->idx, val);  }  static void knc_pmu_enable_event(struct perf_event *event)  { -	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);  	struct hw_perf_event *hwc = &event->hw;  	u64 val;  	val = hwc->config; -	if (cpuc->enabled) -		val |= ARCH_PERFMON_EVENTSEL_ENABLE; +	val |= ARCH_PERFMON_EVENTSEL_ENABLE;  	(void)wrmsrl_safe(hwc->config_base + hwc->idx, val);  } +static inline u64 knc_pmu_get_status(void) +{ +	u64 status; + +	rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_STATUS, status); + +	return status; +} + +static inline void knc_pmu_ack_status(u64 ack) +{ +	wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL, ack); +} + +static int knc_pmu_handle_irq(struct pt_regs *regs) +{ +	struct perf_sample_data data; +	struct cpu_hw_events *cpuc; +	int handled = 0; +	int bit, loops; +	u64 status; + +	cpuc = &__get_cpu_var(cpu_hw_events); + +	knc_pmu_disable_all(); + +	status = knc_pmu_get_status(); +	if (!status) { +		knc_pmu_enable_all(0); +		return handled; +	} + +	loops = 0; +again: +	knc_pmu_ack_status(status); +	if (++loops > 100) { +		WARN_ONCE(1, "perf: irq loop stuck!\n"); +		perf_event_print_debug(); +		goto done; +	} + +	inc_irq_stat(apic_perf_irqs); + +	for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { +		struct perf_event *event = cpuc->events[bit]; + +		handled++; + +		if (!test_bit(bit, cpuc->active_mask)) +			continue; + +		if (!intel_pmu_save_and_restart(event)) +			continue; + +		perf_sample_data_init(&data, 0, event->hw.last_period); + +		if (perf_event_overflow(event, &data, regs)) +			x86_pmu_stop(event, 0); +	} + +	/* +	 * Repeat if there is more work to be done: +	 */ +	status = knc_pmu_get_status(); +	if (status) +		goto again; + +done: +	knc_pmu_enable_all(0); + +	return handled; +} + +  PMU_FORMAT_ATTR(event,	"config:0-7"	);  PMU_FORMAT_ATTR(umask,	"config:8-15"	);  PMU_FORMAT_ATTR(edge,	"config:18"	); @@ -214,7 +286,7 @@ static struct attribute *intel_knc_formats_attr[] = {  static __initconst struct x86_pmu knc_pmu = {  	.name			= "knc", -	.handle_irq		= x86_pmu_handle_irq, +	.handle_irq		= knc_pmu_handle_irq,  	.disable_all		= knc_pmu_disable_all,  	.enable_all		= knc_pmu_enable_all,  	.enable			= knc_pmu_enable_event, @@ -226,12 +298,11 @@ static __initconst struct x86_pmu knc_pmu = {  	.event_map		= knc_pmu_event_map,  	.max_events             = ARRAY_SIZE(knc_perfmon_event_map),  	.apic			= 1, -	.max_period		= (1ULL << 31) - 1, +	.max_period		= (1ULL << 39) - 1,  	.version		= 0,  	.num_counters		= 2, -	/* in theory 40 bits, early silicon is buggy though */ -	.cntval_bits		= 32, -	.cntval_mask		= (1ULL << 32) - 1, +	.cntval_bits		= 40, +	.cntval_mask		= (1ULL << 40) - 1,  	.get_event_constraints	= x86_get_event_constraints,  	.event_constraints	= knc_event_constraints,  	.format_attrs		= intel_knc_formats_attr, diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index e4dd0f7a045..7d0270bd793 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -8,13 +8,106 @@   */  static const u64 p6_perfmon_event_map[] =  { -  [PERF_COUNT_HW_CPU_CYCLES]		= 0x0079, -  [PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0, -  [PERF_COUNT_HW_CACHE_REFERENCES]	= 0x0f2e, -  [PERF_COUNT_HW_CACHE_MISSES]		= 0x012e, -  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x00c4, -  [PERF_COUNT_HW_BRANCH_MISSES]		= 0x00c5, -  [PERF_COUNT_HW_BUS_CYCLES]		= 0x0062, +  [PERF_COUNT_HW_CPU_CYCLES]		= 0x0079,	/* CPU_CLK_UNHALTED */ +  [PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0,	/* INST_RETIRED     */ +  [PERF_COUNT_HW_CACHE_REFERENCES]	= 0x0f2e,	/* L2_RQSTS:M:E:S:I */ +  [PERF_COUNT_HW_CACHE_MISSES]		= 0x012e,	/* L2_RQSTS:I       */ +  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x00c4,	/* BR_INST_RETIRED  */ +  [PERF_COUNT_HW_BRANCH_MISSES]		= 0x00c5,	/* BR_MISS_PRED_RETIRED */ +  [PERF_COUNT_HW_BUS_CYCLES]		= 0x0062,	/* BUS_DRDY_CLOCKS  */ +  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2,	/* RESOURCE_STALLS  */ + +}; + +static __initconst u64 p6_hw_cache_event_ids +				[PERF_COUNT_HW_CACHE_MAX] +				[PERF_COUNT_HW_CACHE_OP_MAX] +				[PERF_COUNT_HW_CACHE_RESULT_MAX] = +{ + [ C(L1D) ] = { +	[ C(OP_READ) ] = { +		[ C(RESULT_ACCESS) ] = 0x0043,	/* DATA_MEM_REFS       */ +                [ C(RESULT_MISS)   ] = 0x0045,	/* DCU_LINES_IN        */ +	}, +	[ C(OP_WRITE) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0x0f29,	/* L2_LD:M:E:S:I       */ +	}, +        [ C(OP_PREFETCH) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0, +        }, + }, + [ C(L1I ) ] = { +	[ C(OP_READ) ] = { +		[ C(RESULT_ACCESS) ] = 0x0080,	/* IFU_IFETCH         */ +		[ C(RESULT_MISS)   ] = 0x0f28,	/* L2_IFETCH:M:E:S:I  */ +	}, +	[ C(OP_WRITE) ] = { +		[ C(RESULT_ACCESS) ] = -1, +		[ C(RESULT_MISS)   ] = -1, +	}, +	[ C(OP_PREFETCH) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0, +	}, + }, + [ C(LL  ) ] = { +	[ C(OP_READ) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0, +	}, +	[ C(OP_WRITE) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0x0025,	/* L2_M_LINES_INM     */ +	}, +	[ C(OP_PREFETCH) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0, +	}, + }, + [ C(DTLB) ] = { +	[ C(OP_READ) ] = { +		[ C(RESULT_ACCESS) ] = 0x0043,	/* DATA_MEM_REFS      */ +		[ C(RESULT_MISS)   ] = 0, +	}, +	[ C(OP_WRITE) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0, +	}, +	[ C(OP_PREFETCH) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0, +	}, + }, + [ C(ITLB) ] = { +	[ C(OP_READ) ] = { +		[ C(RESULT_ACCESS) ] = 0x0080,	/* IFU_IFETCH         */ +		[ C(RESULT_MISS)   ] = 0x0085,	/* ITLB_MISS          */ +	}, +	[ C(OP_WRITE) ] = { +		[ C(RESULT_ACCESS) ] = -1, +		[ C(RESULT_MISS)   ] = -1, +	}, +	[ C(OP_PREFETCH) ] = { +		[ C(RESULT_ACCESS) ] = -1, +		[ C(RESULT_MISS)   ] = -1, +	}, + }, + [ C(BPU ) ] = { +	[ C(OP_READ) ] = { +		[ C(RESULT_ACCESS) ] = 0x00c4,	/* BR_INST_RETIRED      */ +		[ C(RESULT_MISS)   ] = 0x00c5,	/* BR_MISS_PRED_RETIRED */ +        }, +	[ C(OP_WRITE) ] = { +		[ C(RESULT_ACCESS) ] = -1, +		[ C(RESULT_MISS)   ] = -1, +	}, +	[ C(OP_PREFETCH) ] = { +		[ C(RESULT_ACCESS) ] = -1, +		[ C(RESULT_MISS)   ] = -1, +	}, + },  };  static u64 p6_pmu_event_map(int hw_event) @@ -34,7 +127,7 @@ static struct event_constraint p6_event_constraints[] =  {  	INTEL_EVENT_CONSTRAINT(0xc1, 0x1),	/* FLOPS */  	INTEL_EVENT_CONSTRAINT(0x10, 0x1),	/* FP_COMP_OPS_EXE */ -	INTEL_EVENT_CONSTRAINT(0x11, 0x1),	/* FP_ASSIST */ +	INTEL_EVENT_CONSTRAINT(0x11, 0x2),	/* FP_ASSIST */  	INTEL_EVENT_CONSTRAINT(0x12, 0x2),	/* MUL */  	INTEL_EVENT_CONSTRAINT(0x13, 0x2),	/* DIV */  	INTEL_EVENT_CONSTRAINT(0x14, 0x1),	/* CYCLES_DIV_BUSY */ @@ -64,25 +157,25 @@ static void p6_pmu_enable_all(int added)  static inline void  p6_pmu_disable_event(struct perf_event *event)  { -	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);  	struct hw_perf_event *hwc = &event->hw;  	u64 val = P6_NOP_EVENT; -	if (cpuc->enabled) -		val |= ARCH_PERFMON_EVENTSEL_ENABLE; -  	(void)wrmsrl_safe(hwc->config_base, val);  }  static void p6_pmu_enable_event(struct perf_event *event)  { -	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);  	struct hw_perf_event *hwc = &event->hw;  	u64 val;  	val = hwc->config; -	if (cpuc->enabled) -		val |= ARCH_PERFMON_EVENTSEL_ENABLE; + +	/* +	 * p6 only has a global event enable, set on PerfEvtSel0 +	 * We "disable" events by programming P6_NOP_EVENT +	 * and we rely on p6_pmu_enable_all() being called +	 * to actually enable the events. +	 */  	(void)wrmsrl_safe(hwc->config_base, val);  } @@ -158,5 +251,9 @@ __init int p6_pmu_init(void)  	x86_pmu = p6_pmu; +	memcpy(hw_cache_event_ids, p6_hw_cache_event_ids, +		sizeof(hw_cache_event_ids)); + +  	return 0;  } diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index ed858e9e9a7..df06ade26be 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1077,6 +1077,9 @@ void __init memblock_x86_fill(void)  		memblock_add(ei->addr, ei->size);  	} +	/* throw away partial pages */ +	memblock_trim_memory(PAGE_SIZE); +  	memblock_dump_all();  } diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 468e98dfd44..ca45696f30f 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -921,18 +921,19 @@ void __init setup_arch(char **cmdline_p)  #ifdef CONFIG_X86_64  	if (max_pfn > max_low_pfn) {  		int i; -		for (i = 0; i < e820.nr_map; i++) { -			struct e820entry *ei = &e820.map[i]; +		unsigned long start, end; +		unsigned long start_pfn, end_pfn; -			if (ei->addr + ei->size <= 1UL << 32) -				continue; +		for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, +							 NULL) { -			if (ei->type == E820_RESERVED) +			end = PFN_PHYS(end_pfn); +			if (end <= (1UL<<32))  				continue; +			start = PFN_PHYS(start_pfn);  			max_pfn_mapped = init_memory_mapping( -				ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr, -				ei->addr + ei->size); +						max((1UL<<32), start), end);  		}  		/* can we preseve max_low_pfn ?*/ @@ -1048,6 +1049,18 @@ void __init setup_arch(char **cmdline_p)  	arch_init_ideal_nops();  	register_refined_jiffies(CLOCK_TICK_RATE); + +#ifdef CONFIG_EFI +	/* Once setup is done above, disable efi_enabled on mismatched +	 * firmware/kernel archtectures since there is no support for +	 * runtime services. +	 */ +	if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) { +		pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); +		efi_unmap_memmap(); +		efi_enabled = 0; +	} +#endif  }  #ifdef CONFIG_X86_32 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1eefebe5d72..224a7e78cb6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3779,7 +3779,7 @@ static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,  {  	struct kvm_mmio_fragment *frag = &vcpu->mmio_fragments[0]; -	memcpy(vcpu->run->mmio.data, frag->data, frag->len); +	memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len));  	return X86EMUL_CONTINUE;  } @@ -3832,18 +3832,11 @@ mmio:  	bytes -= handled;  	val += handled; -	while (bytes) { -		unsigned now = min(bytes, 8U); - -		frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++]; -		frag->gpa = gpa; -		frag->data = val; -		frag->len = now; - -		gpa += now; -		val += now; -		bytes -= now; -	} +	WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS); +	frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++]; +	frag->gpa = gpa; +	frag->data = val; +	frag->len = bytes;  	return X86EMUL_CONTINUE;  } @@ -3890,7 +3883,7 @@ int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,  	vcpu->mmio_needed = 1;  	vcpu->mmio_cur_fragment = 0; -	vcpu->run->mmio.len = vcpu->mmio_fragments[0].len; +	vcpu->run->mmio.len = min(8u, vcpu->mmio_fragments[0].len);  	vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write;  	vcpu->run->exit_reason = KVM_EXIT_MMIO;  	vcpu->run->mmio.phys_addr = gpa; @@ -5522,28 +5515,44 @@ static int complete_emulated_pio(struct kvm_vcpu *vcpu)   *   * read:   *   for each fragment - *     write gpa, len - *     exit - *     copy data + *     for each mmio piece in the fragment + *       write gpa, len + *       exit + *       copy data   *   execute insn   *   * write:   *   for each fragment - *      write gpa, len - *      copy data - *      exit + *     for each mmio piece in the fragment + *       write gpa, len + *       copy data + *       exit   */  static int complete_emulated_mmio(struct kvm_vcpu *vcpu)  {  	struct kvm_run *run = vcpu->run;  	struct kvm_mmio_fragment *frag; +	unsigned len;  	BUG_ON(!vcpu->mmio_needed);  	/* Complete previous fragment */ -	frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++]; +	frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment]; +	len = min(8u, frag->len);  	if (!vcpu->mmio_is_write) -		memcpy(frag->data, run->mmio.data, frag->len); +		memcpy(frag->data, run->mmio.data, len); + +	if (frag->len <= 8) { +		/* Switch to the next fragment. */ +		frag++; +		vcpu->mmio_cur_fragment++; +	} else { +		/* Go forward to the next mmio piece. */ +		frag->data += len; +		frag->gpa += len; +		frag->len -= len; +	} +  	if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {  		vcpu->mmio_needed = 0;  		if (vcpu->mmio_is_write) @@ -5551,13 +5560,12 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)  		vcpu->mmio_read_completed = 1;  		return complete_emulated_io(vcpu);  	} -	/* Initiate next fragment */ -	++frag; +  	run->exit_reason = KVM_EXIT_MMIO;  	run->mmio.phys_addr = frag->gpa;  	if (vcpu->mmio_is_write) -		memcpy(run->mmio.data, frag->data, frag->len); -	run->mmio.len = frag->len; +		memcpy(run->mmio.data, frag->data, min(8u, frag->len)); +	run->mmio.len = min(8u, frag->len);  	run->mmio.is_write = vcpu->mmio_is_write;  	vcpu->arch.complete_userspace_io = complete_emulated_mmio;  	return 0; diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index ab1f6a93b52..d7aea41563b 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -35,40 +35,44 @@ struct map_range {  	unsigned page_size_mask;  }; -static void __init find_early_table_space(struct map_range *mr, unsigned long end, -					  int use_pse, int use_gbpages) +/* + * First calculate space needed for kernel direct mapping page tables to cover + * mr[0].start to mr[nr_range - 1].end, while accounting for possible 2M and 1GB + * pages. Then find enough contiguous space for those page tables. + */ +static void __init find_early_table_space(struct map_range *mr, int nr_range)  { -	unsigned long puds, pmds, ptes, tables, start = 0, good_end = end; +	int i; +	unsigned long puds = 0, pmds = 0, ptes = 0, tables; +	unsigned long start = 0, good_end;  	phys_addr_t base; -	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; -	tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); - -	if (use_gbpages) { -		unsigned long extra; - -		extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); -		pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; -	} else -		pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; +	for (i = 0; i < nr_range; i++) { +		unsigned long range, extra; -	tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); +		range = mr[i].end - mr[i].start; +		puds += (range + PUD_SIZE - 1) >> PUD_SHIFT; -	if (use_pse) { -		unsigned long extra; +		if (mr[i].page_size_mask & (1 << PG_LEVEL_1G)) { +			extra = range - ((range >> PUD_SHIFT) << PUD_SHIFT); +			pmds += (extra + PMD_SIZE - 1) >> PMD_SHIFT; +		} else { +			pmds += (range + PMD_SIZE - 1) >> PMD_SHIFT; +		} -		extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); +		if (mr[i].page_size_mask & (1 << PG_LEVEL_2M)) { +			extra = range - ((range >> PMD_SHIFT) << PMD_SHIFT);  #ifdef CONFIG_X86_32 -		extra += PMD_SIZE; +			extra += PMD_SIZE;  #endif -		/* The first 2/4M doesn't use large pages. */ -		if (mr->start < PMD_SIZE) -			extra += mr->end - mr->start; - -		ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; -	} else -		ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; +			ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; +		} else { +			ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT; +		} +	} +	tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); +	tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);  	tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);  #ifdef CONFIG_X86_32 @@ -86,7 +90,7 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en  	pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);  	printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n", -		end - 1, pgt_buf_start << PAGE_SHIFT, +		mr[nr_range - 1].end - 1, pgt_buf_start << PAGE_SHIFT,  		(pgt_buf_top << PAGE_SHIFT) - 1);  } @@ -267,7 +271,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,  	 * nodes are discovered.  	 */  	if (!after_bootmem) -		find_early_table_space(&mr[0], end, use_pse, use_gbpages); +		find_early_table_space(mr, nr_range);  	for (i = 0; i < nr_range; i++)  		ret = kernel_physical_mapping_init(mr[i].start, mr[i].end, diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 2b6b4a3c8be..3baff255ada 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -386,7 +386,8 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end,  		 * these mappings are more intelligent.  		 */  		if (pte_val(*pte)) { -			pages++; +			if (!after_bootmem) +				pages++;  			continue;  		} @@ -451,6 +452,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,  			 * attributes.  			 */  			if (page_size_mask & (1 << PG_LEVEL_2M)) { +				if (!after_bootmem) +					pages++;  				last_map_addr = next;  				continue;  			} @@ -526,6 +529,8 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,  			 * attributes.  			 */  			if (page_size_mask & (1 << PG_LEVEL_1G)) { +				if (!after_bootmem) +					pages++;  				last_map_addr = next;  				continue;  			} diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index aded2a91162..ad4439145f8 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -70,11 +70,15 @@ EXPORT_SYMBOL(efi);  struct efi_memory_map memmap;  bool efi_64bit; -static bool efi_native;  static struct efi efi_phys __initdata;  static efi_system_table_t efi_systab __initdata; +static inline bool efi_is_native(void) +{ +	return IS_ENABLED(CONFIG_X86_64) == efi_64bit; +} +  static int __init setup_noefi(char *arg)  {  	efi_enabled = 0; @@ -420,7 +424,7 @@ void __init efi_reserve_boot_services(void)  	}  } -static void __init efi_unmap_memmap(void) +void __init efi_unmap_memmap(void)  {  	if (memmap.map) {  		early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); @@ -432,7 +436,7 @@ void __init efi_free_boot_services(void)  {  	void *p; -	if (!efi_native) +	if (!efi_is_native())  		return;  	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { @@ -684,12 +688,10 @@ void __init efi_init(void)  		return;  	}  	efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; -	efi_native = !efi_64bit;  #else  	efi_phys.systab = (efi_system_table_t *)  			  (boot_params.efi_info.efi_systab |  			  ((__u64)boot_params.efi_info.efi_systab_hi<<32)); -	efi_native = efi_64bit;  #endif  	if (efi_systab_init(efi_phys.systab)) { @@ -723,7 +725,7 @@ void __init efi_init(void)  	 * that doesn't match the kernel 32/64-bit mode.  	 */ -	if (!efi_native) +	if (!efi_is_native())  		pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");  	else if (efi_runtime_init()) {  		efi_enabled = 0; @@ -735,7 +737,7 @@ void __init efi_init(void)  		return;  	}  #ifdef CONFIG_X86_32 -	if (efi_native) { +	if (efi_is_native()) {  		x86_platform.get_wallclock = efi_get_time;  		x86_platform.set_wallclock = efi_set_rtc_mmss;  	} @@ -810,6 +812,16 @@ void __iomem *efi_lookup_mapped_addr(u64 phys_addr)  	return NULL;  } +void efi_memory_uc(u64 addr, unsigned long size) +{ +	unsigned long page_shift = 1UL << EFI_PAGE_SHIFT; +	u64 npages; + +	npages = round_up(size, page_shift) / page_shift; +	memrange_efi_to_native(&addr, &npages); +	set_memory_uc(addr, npages); +} +  /*   * This function will switch the EFI runtime services to virtual mode.   * Essentially, look through the EFI memmap and map every region that @@ -823,7 +835,7 @@ void __init efi_enter_virtual_mode(void)  	efi_memory_desc_t *md, *prev_md = NULL;  	efi_status_t status;  	unsigned long size; -	u64 end, systab, addr, npages, end_pfn; +	u64 end, systab, end_pfn;  	void *p, *va, *new_memmap = NULL;  	int count = 0; @@ -834,7 +846,7 @@ void __init efi_enter_virtual_mode(void)  	 * non-native EFI  	 */ -	if (!efi_native) { +	if (!efi_is_native()) {  		efi_unmap_memmap();  		return;  	} @@ -879,10 +891,14 @@ void __init efi_enter_virtual_mode(void)  		end_pfn = PFN_UP(end);  		if (end_pfn <= max_low_pfn_mapped  		    || (end_pfn > (1UL << (32 - PAGE_SHIFT)) -			&& end_pfn <= max_pfn_mapped)) +			&& end_pfn <= max_pfn_mapped)) {  			va = __va(md->phys_addr); -		else -			va = efi_ioremap(md->phys_addr, size, md->type); + +			if (!(md->attribute & EFI_MEMORY_WB)) +				efi_memory_uc((u64)(unsigned long)va, size); +		} else +			va = efi_ioremap(md->phys_addr, size, +					 md->type, md->attribute);  		md->virt_addr = (u64) (unsigned long) va; @@ -892,13 +908,6 @@ void __init efi_enter_virtual_mode(void)  			continue;  		} -		if (!(md->attribute & EFI_MEMORY_WB)) { -			addr = md->virt_addr; -			npages = md->num_pages; -			memrange_efi_to_native(&addr, &npages); -			set_memory_uc(addr, npages); -		} -  		systab = (u64) (unsigned long) efi_phys.systab;  		if (md->phys_addr <= systab && systab < end) {  			systab += md->virt_addr - md->phys_addr; diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index ac3aa54e265..95fd505dfeb 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -82,7 +82,7 @@ void __init efi_call_phys_epilog(void)  }  void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, -				 u32 type) +				 u32 type, u64 attribute)  {  	unsigned long last_map_pfn; @@ -92,8 +92,11 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,  	last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size);  	if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) {  		unsigned long top = last_map_pfn << PAGE_SHIFT; -		efi_ioremap(top, size - (top - phys_addr), type); +		efi_ioremap(top, size - (top - phys_addr), type, attribute);  	} +	if (!(attribute & EFI_MEMORY_WB)) +		efi_memory_uc((u64)(unsigned long)__va(phys_addr), size); +  	return (void __iomem *)__va(phys_addr);  } diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 6226c99729b..dcf5f2dd91e 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1288,6 +1288,25 @@ unsigned long xen_read_cr2_direct(void)  	return this_cpu_read(xen_vcpu_info.arch.cr2);  } +void xen_flush_tlb_all(void) +{ +	struct mmuext_op *op; +	struct multicall_space mcs; + +	trace_xen_mmu_flush_tlb_all(0); + +	preempt_disable(); + +	mcs = xen_mc_entry(sizeof(*op)); + +	op = mcs.args; +	op->cmd = MMUEXT_TLB_FLUSH_ALL; +	MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); + +	xen_mc_issue(PARAVIRT_LAZY_MMU); + +	preempt_enable(); +}  static void xen_flush_tlb(void)  {  	struct mmuext_op *op; @@ -2518,7 +2537,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,  	err = 0;  out: -	flush_tlb_all(); +	xen_flush_tlb_all();  	return err;  } diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index cdcb48adee4..0d1f36a22c9 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -13,6 +13,8 @@ config XTENSA  	select GENERIC_CPU_DEVICES  	select MODULES_USE_ELF_RELA  	select GENERIC_PCI_IOMAP +	select GENERIC_KERNEL_THREAD +	select GENERIC_KERNEL_EXECVE  	select ARCH_WANT_OPTIONAL_GPIOLIB  	help  	  Xtensa processors are 32-bit RISC machines designed by Tensilica diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h index e6be5b9091c..700c2e6f2d2 100644 --- a/arch/xtensa/include/asm/io.h +++ b/arch/xtensa/include/asm/io.h @@ -62,6 +62,10 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)  static inline void iounmap(volatile void __iomem *addr)  {  } + +#define virt_to_bus     virt_to_phys +#define bus_to_virt     phys_to_virt +  #endif /* CONFIG_MMU */  /* diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h index 5c371d8d452..2d630e7399c 100644 --- a/arch/xtensa/include/asm/processor.h +++ b/arch/xtensa/include/asm/processor.h @@ -152,6 +152,7 @@ struct thread_struct {  /* Clearing a0 terminates the backtrace. */  #define start_thread(regs, new_pc, new_sp) \ +	memset(regs, 0, sizeof(*regs)); \  	regs->pc = new_pc; \  	regs->ps = USER_PS_VALUE; \  	regs->areg[1] = new_sp; \ @@ -168,9 +169,6 @@ struct mm_struct;  /* Free all resources held by a thread. */  #define release_thread(thread) do { } while(0) -/* Create a kernel thread without removing it from tasklists */ -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); -  /* Copy and release all segment info associated with a VM */  #define copy_segments(p, mm)	do { } while(0)  #define release_segments(mm)	do { } while(0) diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index c1dacca312f..124aeee0d38 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h @@ -10,7 +10,7 @@  struct pt_regs;  struct sigaction; -asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*); +asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*);  asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);  asmlinkage long xtensa_ptrace(long, long, long, long);  asmlinkage long xtensa_sigreturn(struct pt_regs*); diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index 9ef1c31d2c8..f4e6eaa40d1 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h @@ -1,16 +1,9 @@ -/* - * include/asm-xtensa/unistd.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License.  See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ +#ifndef _XTENSA_UNISTD_H +#define _XTENSA_UNISTD_H +#define __ARCH_WANT_SYS_EXECVE  #include <uapi/asm/unistd.h> -  /*   * "Conditional" syscalls   * @@ -37,3 +30,5 @@  #define __IGNORE_mmap				/* use mmap2 */  #define __IGNORE_vfork				/* use clone */  #define __IGNORE_fadvise64			/* use fadvise64_64 */ + +#endif /* _XTENSA_UNISTD_H */ diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h index 479abaea5aa..9f36d0e3e0a 100644 --- a/arch/xtensa/include/uapi/asm/unistd.h +++ b/arch/xtensa/include/uapi/asm/unistd.h @@ -1,14 +1,4 @@ -/* - * include/asm-xtensa/unistd.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License.  See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2012 Tensilica Inc. - */ - -#ifndef _UAPI_XTENSA_UNISTD_H +#if !defined(_UAPI_XTENSA_UNISTD_H) || defined(__SYSCALL)  #define _UAPI_XTENSA_UNISTD_H  #ifndef __SYSCALL @@ -272,7 +262,7 @@ __SYSCALL(115, sys_sendmmsg, 4)  #define __NR_clone 				116  __SYSCALL(116, xtensa_clone, 5)  #define __NR_execve 				117 -__SYSCALL(117, xtensa_execve, 3) +__SYSCALL(117, sys_execve, 3)  #define __NR_exit 				118  __SYSCALL(118, sys_exit, 1)  #define __NR_exit_group 			119 @@ -759,4 +749,6 @@ __SYSCALL(331, sys_kcmp, 5)  #define SYS_XTENSA_COUNT                  5     /* count */ +#undef __SYSCALL +  #endif /* _UAPI_XTENSA_UNISTD_H */ diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 18453067c25..90bfc1dbc13 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1833,50 +1833,6 @@ ENTRY(system_call)  /* - * Create a kernel thread - * - * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) - * a2                    a2                 a3             a4 - */ - -ENTRY(kernel_thread) -	entry	a1, 16 - -	mov	a5, a2			# preserve fn over syscall -	mov	a7, a3			# preserve args over syscall - -	movi	a3, _CLONE_VM | _CLONE_UNTRACED -	movi	a2, __NR_clone -	or	a6, a4, a3		# arg0: flags -	mov	a3, a1			# arg1: sp -	syscall - -	beq	a3, a1, 1f		# branch if parent -	mov	a6, a7			# args -	callx4	a5			# fn(args) - -	movi	a2, __NR_exit -	syscall				# return value of fn(args) still in a6 - -1:	retw - -/* - * Do a system call from kernel instead of calling sys_execve, so we end up - * with proper pt_regs. - * - * int kernel_execve(const char *fname, char *const argv[], charg *const envp[]) - * a2                        a2               a3                  a4 - */ - -ENTRY(kernel_execve) -	entry	a1, 16 -	mov	a6, a2			# arg0 is in a6 -	movi	a2, __NR_execve -	syscall - -	retw - -/*   * Task switch.   *   * struct task*  _switch_to (struct task* prev, struct task* next) @@ -1958,3 +1914,16 @@ ENTRY(ret_from_fork)  	j	common_exception_return +/* + * Kernel thread creation helper + * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg + *           left from _switch_to: a6 = prev + */ +ENTRY(ret_from_kernel_thread) + +	call4	schedule_tail +	mov	a6, a3 +	callx4	a2 +	j	common_exception_return + +ENDPROC(ret_from_kernel_thread) diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 1908f6642d3..09ae7bfab9a 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -45,6 +45,7 @@  #include <asm/regs.h>  extern void ret_from_fork(void); +extern void ret_from_kernel_thread(void);  struct task_struct *current_set[NR_CPUS] = {&init_task, }; @@ -158,18 +159,30 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)  /*   * Copy thread.   * + * There are two modes in which this function is called: + * 1) Userspace thread creation, + *    regs != NULL, usp_thread_fn is userspace stack pointer. + *    It is expected to copy parent regs (in case CLONE_VM is not set + *    in the clone_flags) and set up passed usp in the childregs. + * 2) Kernel thread creation, + *    regs == NULL, usp_thread_fn is the function to run in the new thread + *    and thread_fn_arg is its parameter. + *    childregs are not used for the kernel threads. + *   * The stack layout for the new thread looks like this:   * - *	+------------------------+ <- sp in childregs (= tos) + *	+------------------------+   *	|       childregs        |   *	+------------------------+ <- thread.sp = sp in dummy-frame   *	|      dummy-frame       |    (saved in dummy-frame spill-area)   *	+------------------------+   * - * We create a dummy frame to return to ret_from_fork: - *   a0 points to ret_from_fork (simulating a call4) + * We create a dummy frame to return to either ret_from_fork or + *   ret_from_kernel_thread: + *   a0 points to ret_from_fork/ret_from_kernel_thread (simulating a call4)   *   sp points to itself (thread.sp) - *   a2, a3 are unused. + *   a2, a3 are unused for userspace threads, + *   a2 points to thread_fn, a3 holds thread_fn arg for kernel threads.   *   * Note: This is a pristine frame, so we don't need any spill region on top of   *       childregs. @@ -185,43 +198,63 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)   * involved.  Much simpler to just not copy those live frames across.   */ -int copy_thread(unsigned long clone_flags, unsigned long usp, -		unsigned long unused, -                struct task_struct * p, struct pt_regs * regs) +int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, +		unsigned long thread_fn_arg, +		struct task_struct *p, struct pt_regs *unused)  { -	struct pt_regs *childregs; -	unsigned long tos; -	int user_mode = user_mode(regs); +	struct pt_regs *childregs = task_pt_regs(p);  #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)  	struct thread_info *ti;  #endif -	/* Set up new TSS. */ -	tos = (unsigned long)task_stack_page(p) + THREAD_SIZE; -	if (user_mode) -		childregs = (struct pt_regs*)(tos - PT_USER_SIZE); -	else -		childregs = (struct pt_regs*)tos - 1; - -	/* This does not copy all the regs.  In a bout of brilliance or madness, -	   ARs beyond a0-a15 exist past the end of the struct. */ -	*childregs = *regs; -  	/* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */  	*((int*)childregs - 3) = (unsigned long)childregs;  	*((int*)childregs - 4) = 0; -	childregs->areg[2] = 0; -	p->set_child_tid = p->clear_child_tid = NULL; -	p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1);  	p->thread.sp = (unsigned long)childregs; -	if (user_mode(regs)) { +	if (!(p->flags & PF_KTHREAD)) { +		struct pt_regs *regs = current_pt_regs(); +		unsigned long usp = usp_thread_fn ? +			usp_thread_fn : regs->areg[1]; + +		p->thread.ra = MAKE_RA_FOR_CALL( +				(unsigned long)ret_from_fork, 0x1); +		/* This does not copy all the regs. +		 * In a bout of brilliance or madness, +		 * ARs beyond a0-a15 exist past the end of the struct. +		 */ +		*childregs = *regs;  		childregs->areg[1] = usp; +		childregs->areg[2] = 0; + +		/* When sharing memory with the parent thread, the child +		   usually starts on a pristine stack, so we have to reset +		   windowbase, windowstart and wmask. +		   (Note that such a new thread is required to always create +		   an initial call4 frame) +		   The exception is vfork, where the new thread continues to +		   run on the parent's stack until it calls execve. This could +		   be a call8 or call12, which requires a legal stack frame +		   of the previous caller for the overflow handlers to work. +		   (Note that it's always legal to overflow live registers). +		   In this case, ensure to spill at least the stack pointer +		   of that frame. */ +  		if (clone_flags & CLONE_VM) { -			childregs->wmask = 1;	/* can't share live windows */ +			/* check that caller window is live and same stack */ +			int len = childregs->wmask & ~0xf; +			if (regs->areg[1] == usp && len != 0) { +				int callinc = (regs->areg[0] >> 30) & 3; +				int caller_ars = XCHAL_NUM_AREGS - callinc * 4; +				put_user(regs->areg[caller_ars+1], +					 (unsigned __user*)(usp - 12)); +			} +			childregs->wmask = 1; +			childregs->windowstart = 1; +			childregs->windowbase = 0;  		} else {  			int len = childregs->wmask & ~0xf;  			memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4], @@ -230,11 +263,19 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,  // FIXME: we need to set THREADPTR in thread_info...  		if (clone_flags & CLONE_SETTLS)  			childregs->areg[2] = childregs->areg[6]; -  	} else { -		/* In kernel space, we start a new thread with a new stack. */ -		childregs->wmask = 1; -		childregs->areg[1] = tos; +		p->thread.ra = MAKE_RA_FOR_CALL( +				(unsigned long)ret_from_kernel_thread, 1); + +		/* pass parameters to ret_from_kernel_thread: +		 * a2 = thread_fn, a3 = thread_fn arg +		 */ +		*((int *)childregs - 1) = thread_fn_arg; +		*((int *)childregs - 2) = usp_thread_fn; + +		/* Childregs are only used when we're going to userspace +		 * in which case start_thread will set them up. +		 */  	}  #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) @@ -330,32 +371,5 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp,                    void __user *child_tid, long a5,                    struct pt_regs *regs)  { -        if (!newsp) -                newsp = regs->areg[1];          return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);  } - -/* - * xtensa_execve() executes a new program. - */ - -asmlinkage -long xtensa_execve(const char __user *name, -		   const char __user *const __user *argv, -                   const char __user *const __user *envp, -                   long a3, long a4, long a5, -                   struct pt_regs *regs) -{ -	long error; -	struct filename *filename; - -	filename = getname(name); -	error = PTR_ERR(filename); -	if (IS_ERR(filename)) -		goto out; -	error = do_execve(filename->name, argv, envp, regs); -	putname(filename); -out: -	return error; -} - diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c index a5c01e74d5d..5702065f472 100644 --- a/arch/xtensa/kernel/syscall.c +++ b/arch/xtensa/kernel/syscall.c @@ -32,10 +32,8 @@ typedef void (*syscall_t)(void);  syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {  	[0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall, -#undef __SYSCALL  #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol, -#undef  __KERNEL_SYSCALLS__ -#include <asm/unistd.h> +#include <uapi/asm/unistd.h>  };  asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) @@ -49,7 +47,8 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)  	return (long)ret;  } -asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len) +asmlinkage long xtensa_fadvise64_64(int fd, int advice, +		unsigned long long offset, unsigned long long len)  {  	return sys_fadvise64_64(fd, offset, len, advice);  } diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index a8b9f1fd1e1..afe058b24e6 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c @@ -43,7 +43,6 @@ EXPORT_SYMBOL(__strncpy_user);  EXPORT_SYMBOL(clear_page);  EXPORT_SYMBOL(copy_page); -EXPORT_SYMBOL(kernel_thread);  EXPORT_SYMBOL(empty_zero_page);  /* diff --git a/block/Kconfig b/block/Kconfig index 09acf1b3990..a7e40a7c821 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -89,7 +89,7 @@ config BLK_DEV_INTEGRITY  config BLK_DEV_THROTTLING  	bool "Block layer bio throttling support" -	depends on BLK_CGROUP=y && EXPERIMENTAL +	depends on BLK_CGROUP=y  	default n  	---help---  	Block layer bio throttling support. It can be used to limit diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index cafcd743118..d0b770391ad 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -285,6 +285,13 @@ static void blkg_destroy_all(struct request_queue *q)  		blkg_destroy(blkg);  		spin_unlock(&blkcg->lock);  	} + +	/* +	 * root blkg is destroyed.  Just clear the pointer since +	 * root_rl does not take reference on root blkg. +	 */ +	q->root_blkg = NULL; +	q->root_rl.blkg = NULL;  }  static void blkg_rcu_free(struct rcu_head *rcu_head) @@ -326,6 +333,9 @@ struct request_list *__blk_queue_next_rl(struct request_list *rl,  	 */  	if (rl == &q->root_rl) {  		ent = &q->blkg_list; +		/* There are no more block groups, hence no request lists */ +		if (list_empty(ent)) +			return NULL;  	} else {  		blkg = container_of(rl, struct blkcg_gq, rl);  		ent = &blkg->q_node; diff --git a/block/blk-core.c b/block/blk-core.c index a33870b1847..3c95c4d6e31 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2868,7 +2868,8 @@ static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b)  	struct request *rqa = container_of(a, struct request, queuelist);  	struct request *rqb = container_of(b, struct request, queuelist); -	return !(rqa->q <= rqb->q); +	return !(rqa->q < rqb->q || +		(rqa->q == rqb->q && blk_rq_pos(rqa) < blk_rq_pos(rqb)));  }  /* diff --git a/crypto/cryptd.c b/crypto/cryptd.c index 671d4d6d14d..7bdd61b867c 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct work_struct *work)  	struct crypto_async_request *req, *backlog;  	cpu_queue = container_of(work, struct cryptd_cpu_queue, work); -	/* Only handle one request at a time to avoid hogging crypto -	 * workqueue. preempt_disable/enable is used to prevent -	 * being preempted by cryptd_enqueue_request() */ +	/* +	 * Only handle one request at a time to avoid hogging crypto workqueue. +	 * preempt_disable/enable is used to prevent being preempted by +	 * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent +	 * cryptd_enqueue_request() being accessed from software interrupts. +	 */ +	local_bh_disable();  	preempt_disable();  	backlog = crypto_get_backlog(&cpu_queue->queue);  	req = crypto_dequeue_request(&cpu_queue->queue);  	preempt_enable(); +	local_bh_enable();  	if (!req)  		return; diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index d1a2d74033e..08373086cd7 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -159,6 +159,7 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)  	if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {  		retval = -ENOSPC;  		mutex_unlock(&acpi_dev->physical_node_lock); +		kfree(physical_node);  		goto err;  	} diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index e78c2a52ea4..bd4e5dca3ff 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -409,6 +409,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event)  		acpi_bus_generate_proc_event(device, event, 0);  		acpi_bus_generate_netlink_event(device->pnp.device_class,  						  dev_name(&device->dev), event, 0); +		break;  	default:  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,  				  "Unsupported event [0x%x]\n", event)); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index f94d4c818fc..0230cb6cbb3 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1345,12 +1345,15 @@ static int  acpi_video_bus_get_devices(struct acpi_video_bus *video,  			   struct acpi_device *device)  { -	int status; +	int status = 0;  	struct acpi_device *dev; -	status = acpi_video_device_enumerate(video); -	if (status) -		return status; +	/* +	 * There are systems where video module known to work fine regardless +	 * of broken _DOD and ignoring returned value here doesn't cause +	 * any issues later. +	 */ +	acpi_video_device_enumerate(video);  	list_for_each_entry(dev, &device->children, node) { diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 08b4c520938..b34b5cda5ae 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -236,7 +236,7 @@ config CMA_SIZE_PERCENTAGE  choice  	prompt "Selected region size" -	default CMA_SIZE_SEL_ABSOLUTE +	default CMA_SIZE_SEL_MBYTES  config CMA_SIZE_SEL_MBYTES  	bool "Use mega bytes value only" diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 560a7173f81..bc256b64102 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -191,9 +191,8 @@ EXPORT_SYMBOL(dma_release_from_coherent);   * This checks whether the memory was allocated from the per-device   * coherent memory pool and if so, maps that memory to the provided vma.   * - * Returns 1 if we correctly mapped the memory, or 0 if - * dma_release_coherent() should proceed with mapping memory from - * generic pools. + * Returns 1 if we correctly mapped the memory, or 0 if the caller should + * proceed with mapping memory from generic pools.   */  int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,  			   void *vaddr, size_t size, int *ret) diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 9a1469474f5..612afcc5a93 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -27,15 +27,12 @@  #include <linux/mm.h>  #include <linux/mutex.h>  #include <linux/page-isolation.h> +#include <linux/sizes.h>  #include <linux/slab.h>  #include <linux/swap.h>  #include <linux/mm_types.h>  #include <linux/dma-contiguous.h> -#ifndef SZ_1M -#define SZ_1M (1 << 20) -#endif -  struct cma {  	unsigned long	base_pfn;  	unsigned long	count; diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 81541452887..8945f4e489e 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -36,68 +36,6 @@ MODULE_AUTHOR("Manuel Estrada Sainz");  MODULE_DESCRIPTION("Multi purpose firmware loading support");  MODULE_LICENSE("GPL"); -static const char *fw_path[] = { -	"/lib/firmware/updates/" UTS_RELEASE, -	"/lib/firmware/updates", -	"/lib/firmware/" UTS_RELEASE, -	"/lib/firmware" -}; - -/* Don't inline this: 'struct kstat' is biggish */ -static noinline long fw_file_size(struct file *file) -{ -	struct kstat st; -	if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) -		return -1; -	if (!S_ISREG(st.mode)) -		return -1; -	if (st.size != (long)st.size) -		return -1; -	return st.size; -} - -static bool fw_read_file_contents(struct file *file, struct firmware *fw) -{ -	long size; -	char *buf; - -	size = fw_file_size(file); -	if (size < 0) -		return false; -	buf = vmalloc(size); -	if (!buf) -		return false; -	if (kernel_read(file, 0, buf, size) != size) { -		vfree(buf); -		return false; -	} -	fw->data = buf; -	fw->size = size; -	return true; -} - -static bool fw_get_filesystem_firmware(struct firmware *fw, const char *name) -{ -	int i; -	bool success = false; -	char *path = __getname(); - -	for (i = 0; i < ARRAY_SIZE(fw_path); i++) { -		struct file *file; -		snprintf(path, PATH_MAX, "%s/%s", fw_path[i], name); - -		file = filp_open(path, O_RDONLY, 0); -		if (IS_ERR(file)) -			continue; -		success = fw_read_file_contents(file, fw); -		fput(file); -		if (success) -			break; -	} -	__putname(path); -	return success; -} -  /* Builtin firmware support */  #ifdef CONFIG_FW_LOADER @@ -150,6 +88,11 @@ enum {  	FW_STATUS_ABORT,  }; +enum fw_buf_fmt { +	VMALLOC_BUF,	/* used in direct loading */ +	PAGE_BUF,	/* used in loading via userspace */ +}; +  static int loading_timeout = 60;	/* In seconds */  static inline long firmware_loading_timeout(void) @@ -173,8 +116,6 @@ struct firmware_cache {  	spinlock_t name_lock;  	struct list_head fw_names; -	wait_queue_head_t wait_queue; -	int cnt;  	struct delayed_work work;  	struct notifier_block   pm_notify; @@ -187,6 +128,7 @@ struct firmware_buf {  	struct completion completion;  	struct firmware_cache *fwc;  	unsigned long status; +	enum fw_buf_fmt fmt;  	void *data;  	size_t size;  	struct page **pages; @@ -240,6 +182,7 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name,  	strcpy(buf->fw_id, fw_name);  	buf->fwc = fwc;  	init_completion(&buf->completion); +	buf->fmt = VMALLOC_BUF;  	pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf); @@ -307,10 +250,14 @@ static void __fw_free_buf(struct kref *ref)  	list_del(&buf->list);  	spin_unlock(&fwc->lock); -	vunmap(buf->data); -	for (i = 0; i < buf->nr_pages; i++) -		__free_page(buf->pages[i]); -	kfree(buf->pages); + +	if (buf->fmt == PAGE_BUF) { +		vunmap(buf->data); +		for (i = 0; i < buf->nr_pages; i++) +			__free_page(buf->pages[i]); +		kfree(buf->pages); +	} else +		vfree(buf->data);  	kfree(buf);  } @@ -319,6 +266,69 @@ static void fw_free_buf(struct firmware_buf *buf)  	kref_put(&buf->ref, __fw_free_buf);  } +/* direct firmware loading support */ +static const char *fw_path[] = { +	"/lib/firmware/updates/" UTS_RELEASE, +	"/lib/firmware/updates", +	"/lib/firmware/" UTS_RELEASE, +	"/lib/firmware" +}; + +/* Don't inline this: 'struct kstat' is biggish */ +static noinline long fw_file_size(struct file *file) +{ +	struct kstat st; +	if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) +		return -1; +	if (!S_ISREG(st.mode)) +		return -1; +	if (st.size != (long)st.size) +		return -1; +	return st.size; +} + +static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf) +{ +	long size; +	char *buf; + +	size = fw_file_size(file); +	if (size < 0) +		return false; +	buf = vmalloc(size); +	if (!buf) +		return false; +	if (kernel_read(file, 0, buf, size) != size) { +		vfree(buf); +		return false; +	} +	fw_buf->data = buf; +	fw_buf->size = size; +	return true; +} + +static bool fw_get_filesystem_firmware(struct firmware_buf *buf) +{ +	int i; +	bool success = false; +	char *path = __getname(); + +	for (i = 0; i < ARRAY_SIZE(fw_path); i++) { +		struct file *file; +		snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id); + +		file = filp_open(path, O_RDONLY, 0); +		if (IS_ERR(file)) +			continue; +		success = fw_read_file_contents(file, buf); +		fput(file); +		if (success) +			break; +	} +	__putname(path); +	return success; +} +  static struct firmware_priv *to_firmware_priv(struct device *dev)  {  	return container_of(dev, struct firmware_priv, dev); @@ -423,6 +433,21 @@ static void firmware_free_data(const struct firmware *fw)  #ifndef PAGE_KERNEL_RO  #define PAGE_KERNEL_RO PAGE_KERNEL  #endif + +/* one pages buffer should be mapped/unmapped only once */ +static int fw_map_pages_buf(struct firmware_buf *buf) +{ +	if (buf->fmt != PAGE_BUF) +		return 0; + +	if (buf->data) +		vunmap(buf->data); +	buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO); +	if (!buf->data) +		return -ENOMEM; +	return 0; +} +  /**   * firmware_loading_store - set value in the 'loading' control file   * @dev: device pointer @@ -467,6 +492,14 @@ static ssize_t firmware_loading_store(struct device *dev,  		if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {  			set_bit(FW_STATUS_DONE, &fw_buf->status);  			clear_bit(FW_STATUS_LOADING, &fw_buf->status); + +			/* +			 * Several loading requests may be pending on +			 * one same firmware buf, so let all requests +			 * see the mapped 'buf->data' once the loading +			 * is completed. +			 * */ +			fw_map_pages_buf(fw_buf);  			complete_all(&fw_buf->completion);  			break;  		} @@ -670,15 +703,6 @@ exit:  	return fw_priv;  } -/* one pages buffer is mapped/unmapped only once */ -static int fw_map_pages_buf(struct firmware_buf *buf) -{ -	buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO); -	if (!buf->data) -		return -ENOMEM; -	return 0; -} -  /* store the pages buffer info firmware from buf */  static void fw_set_page_data(struct firmware_buf *buf, struct firmware *fw)  { @@ -778,11 +802,6 @@ _request_firmware_prepare(const struct firmware **firmware_p, const char *name,  		return NULL;  	} -	if (fw_get_filesystem_firmware(firmware, name)) { -		dev_dbg(device, "firmware: direct-loading firmware %s\n", name); -		return NULL; -	} -  	ret = fw_lookup_and_allocate_buf(name, &fw_cache, &buf);  	if (!ret)  		fw_priv = fw_create_instance(firmware, name, device, @@ -832,6 +851,21 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,  	struct device *f_dev = &fw_priv->dev;  	struct firmware_buf *buf = fw_priv->buf;  	struct firmware_cache *fwc = &fw_cache; +	int direct_load = 0; + +	/* try direct loading from fs first */ +	if (fw_get_filesystem_firmware(buf)) { +		dev_dbg(f_dev->parent, "firmware: direct-loading" +			" firmware %s\n", buf->fw_id); + +		set_bit(FW_STATUS_DONE, &buf->status); +		complete_all(&buf->completion); +		direct_load = 1; +		goto handle_fw; +	} + +	/* fall back on userspace loading */ +	buf->fmt = PAGE_BUF;  	dev_set_uevent_suppress(f_dev, true); @@ -870,6 +904,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,  	del_timer_sync(&fw_priv->timeout); +handle_fw:  	mutex_lock(&fw_lock);  	if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status))  		retval = -ENOENT; @@ -884,9 +919,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,  	if (!retval && f_dev->parent)  		fw_add_devm_name(f_dev->parent, buf->fw_id); -	if (!retval) -		retval = fw_map_pages_buf(buf); -  	/*  	 * After caching firmware image is started, let it piggyback  	 * on request firmware. @@ -902,6 +934,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,  	fw_priv->buf = NULL;  	mutex_unlock(&fw_lock); +	if (direct_load) +		goto err_put_dev; +  	device_remove_file(f_dev, &dev_attr_loading);  err_del_bin_attr:  	device_remove_bin_file(f_dev, &firmware_attr_data); @@ -1129,6 +1164,8 @@ int uncache_firmware(const char *fw_name)  }  #ifdef CONFIG_PM_SLEEP +static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); +  static struct fw_cache_entry *alloc_fw_cache_entry(const char *name)  {  	struct fw_cache_entry *fce; @@ -1142,17 +1179,27 @@ exit:  	return fce;  } -static int fw_cache_piggyback_on_request(const char *name) +static int __fw_entry_found(const char *name)  {  	struct firmware_cache *fwc = &fw_cache;  	struct fw_cache_entry *fce; -	int ret = 0; -	spin_lock(&fwc->name_lock);  	list_for_each_entry(fce, &fwc->fw_names, list) {  		if (!strcmp(fce->name, name)) -			goto found; +			return 1;  	} +	return 0; +} + +static int fw_cache_piggyback_on_request(const char *name) +{ +	struct firmware_cache *fwc = &fw_cache; +	struct fw_cache_entry *fce; +	int ret = 0; + +	spin_lock(&fwc->name_lock); +	if (__fw_entry_found(name)) +		goto found;  	fce = alloc_fw_cache_entry(name);  	if (fce) { @@ -1185,12 +1232,6 @@ static void __async_dev_cache_fw_image(void *fw_entry,  		free_fw_cache_entry(fce);  	} - -	spin_lock(&fwc->name_lock); -	fwc->cnt--; -	spin_unlock(&fwc->name_lock); - -	wake_up(&fwc->wait_queue);  }  /* called with dev->devres_lock held */ @@ -1229,11 +1270,19 @@ static void dev_cache_fw_image(struct device *dev, void *data)  		list_del(&fce->list);  		spin_lock(&fwc->name_lock); -		fwc->cnt++; -		list_add(&fce->list, &fwc->fw_names); +		/* only one cache entry for one firmware */ +		if (!__fw_entry_found(fce->name)) { +			list_add(&fce->list, &fwc->fw_names); +		} else { +			free_fw_cache_entry(fce); +			fce = NULL; +		}  		spin_unlock(&fwc->name_lock); -		async_schedule(__async_dev_cache_fw_image, (void *)fce); +		if (fce) +			async_schedule_domain(__async_dev_cache_fw_image, +					      (void *)fce, +					      &fw_cache_domain);  	}  } @@ -1275,6 +1324,9 @@ static void device_cache_fw_images(void)  	pr_debug("%s\n", __func__); +	/* cancel uncache work */ +	cancel_delayed_work_sync(&fwc->work); +  	/*  	 * use small loading timeout for caching devices' firmware  	 * because all these firmware images have been loaded @@ -1292,21 +1344,7 @@ static void device_cache_fw_images(void)  	mutex_unlock(&fw_lock);  	/* wait for completion of caching firmware for all devices */ -	spin_lock(&fwc->name_lock); -	for (;;) { -		prepare_to_wait(&fwc->wait_queue, &wait, -				TASK_UNINTERRUPTIBLE); -		if (!fwc->cnt) -			break; - -		spin_unlock(&fwc->name_lock); - -		schedule(); - -		spin_lock(&fwc->name_lock); -	} -	spin_unlock(&fwc->name_lock); -	finish_wait(&fwc->wait_queue, &wait); +	async_synchronize_full_domain(&fw_cache_domain);  	loading_timeout = old_timeout;  } @@ -1394,9 +1432,7 @@ static void __init fw_cache_init(void)  #ifdef CONFIG_PM_SLEEP  	spin_lock_init(&fw_cache.name_lock);  	INIT_LIST_HEAD(&fw_cache.fw_names); -	fw_cache.cnt = 0; -	init_waitqueue_head(&fw_cache.wait_queue);  	INIT_DELAYED_WORK(&fw_cache.work,  			  device_uncache_fw_images_work); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 8727e9c5eea..72c776f2a1f 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -83,9 +83,16 @@ EXPORT_SYMBOL_GPL(platform_get_resource);   */  int platform_get_irq(struct platform_device *dev, unsigned int num)  { +#ifdef CONFIG_SPARC +	/* sparc does not have irqs represented as IORESOURCE_IRQ resources */ +	if (!dev || num >= dev->archdata.num_irqs) +		return -ENXIO; +	return dev->archdata.irqs[num]; +#else  	struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);  	return r ? r->start : -ENXIO; +#endif  }  EXPORT_SYMBOL_GPL(platform_get_irq); diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index c22b869245d..96b71b6536d 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1862,7 +1862,7 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)  	cpuidle_drv = cpuidle_driver_ref();  	if (!cpuidle_drv) {  		ret = -ENODEV; -		goto out; +		goto err_drv;  	}  	if (cpuidle_drv->state_count <= state) {  		ret = -EINVAL; @@ -1884,6 +1884,9 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)   err:  	cpuidle_driver_unref(); + + err_drv: +	kfree(cpu_data);  	goto out;  } diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 432aeeedfd5..d865470bc95 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -158,9 +158,10 @@ static int bcma_register_cores(struct bcma_bus *bus)  static void bcma_unregister_cores(struct bcma_bus *bus)  { -	struct bcma_device *core; +	struct bcma_device *core, *tmp; -	list_for_each_entry(core, &bus->cores, list) { +	list_for_each_entry_safe(core, tmp, &bus->cores, list) { +		list_del(&core->list);  		if (core->dev_registered)  			device_unregister(&core->dev);  	} diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index f529407db93..824e09c4d0d 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -131,6 +131,7 @@ config BLK_CPQ_DA  config BLK_CPQ_CISS_DA  	tristate "Compaq Smart Array 5xxx support"  	depends on PCI +	select CHECK_SIGNATURE  	help  	  This is the driver for Compaq Smart Array 5xxx controllers.  	  Everyone using these boards should say Y here. @@ -166,8 +167,8 @@ config BLK_DEV_DAC960  	  module will be called DAC960.  config BLK_DEV_UMEM -	tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)" -	depends on PCI && EXPERIMENTAL +	tristate "Micro Memory MM5415 Battery Backed RAM support" +	depends on PCI  	---help---  	  Saying Y here will include support for the MM5415 family of  	  battery backed (Non-volatile) RAM cards. @@ -430,8 +431,8 @@ config CDROM_PKTCDVD_BUFFERS  	  a disc is opened for writing.  config CDROM_PKTCDVD_WCACHE -	bool "Enable write caching (EXPERIMENTAL)" -	depends on CDROM_PKTCDVD && EXPERIMENTAL +	bool "Enable write caching" +	depends on CDROM_PKTCDVD  	help  	  If enabled, write caching will be set for the CD-R/W device. For now  	  this option is dangerous unless the CD-RW media is known good, as we @@ -508,8 +509,8 @@ config XEN_BLKDEV_BACKEND  config VIRTIO_BLK -	tristate "Virtio block driver (EXPERIMENTAL)" -	depends on EXPERIMENTAL && VIRTIO +	tristate "Virtio block driver" +	depends on VIRTIO  	---help---  	  This is the virtual block driver for virtio.  It can be used with            lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M. @@ -528,7 +529,7 @@ config BLK_DEV_HD  config BLK_DEV_RBD  	tristate "Rados block device (RBD)" -	depends on INET && EXPERIMENTAL && BLOCK +	depends on INET && BLOCK  	select CEPH_LIB  	select LIBCRC32C  	select CRYPTO_AES diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index b0f553b26d0..ca83f96756a 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -5205,7 +5205,6 @@ static void cciss_shutdown(struct pci_dev *pdev)  		return;  	}  	/* write all data in the battery backed cache to disk */ -	memset(flush_buf, 0, 4);  	return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf,  		4, 0, CTLR_LUNID, TYPE_CMD);  	kfree(flush_buf); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 17c675c5229..1c49d717396 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4109,12 +4109,19 @@ static struct platform_driver floppy_driver = {  static struct platform_device floppy_device[N_DRIVE]; +static bool floppy_available(int drive) +{ +	if (!(allowed_drive_mask & (1 << drive))) +		return false; +	if (fdc_state[FDC(drive)].version == FDC_NONE) +		return false; +	return true; +} +  static struct kobject *floppy_find(dev_t dev, int *part, void *data)  {  	int drive = (*part & 3) | ((*part & 0x80) >> 5); -	if (drive >= N_DRIVE || -	    !(allowed_drive_mask & (1 << drive)) || -	    fdc_state[FDC(drive)].version == FDC_NONE) +	if (drive >= N_DRIVE || !floppy_available(drive))  		return NULL;  	if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))  		return NULL; @@ -4124,8 +4131,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)  static int __init do_floppy_init(void)  { -	int i, unit, drive; -	int err, dr; +	int i, unit, drive, err;  	set_debugt();  	interruptjiffies = resultjiffies = jiffies; @@ -4137,34 +4143,32 @@ static int __init do_floppy_init(void)  	raw_cmd = NULL; -	for (dr = 0; dr < N_DRIVE; dr++) { -		disks[dr] = alloc_disk(1); -		if (!disks[dr]) { -			err = -ENOMEM; -			goto out_put_disk; -		} +	floppy_wq = alloc_ordered_workqueue("floppy", 0); +	if (!floppy_wq) +		return -ENOMEM; -		floppy_wq = alloc_ordered_workqueue("floppy", 0); -		if (!floppy_wq) { +	for (drive = 0; drive < N_DRIVE; drive++) { +		disks[drive] = alloc_disk(1); +		if (!disks[drive]) {  			err = -ENOMEM;  			goto out_put_disk;  		} -		disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); -		if (!disks[dr]->queue) { +		disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock); +		if (!disks[drive]->queue) {  			err = -ENOMEM; -			goto out_destroy_workq; +			goto out_put_disk;  		} -		blk_queue_max_hw_sectors(disks[dr]->queue, 64); -		disks[dr]->major = FLOPPY_MAJOR; -		disks[dr]->first_minor = TOMINOR(dr); -		disks[dr]->fops = &floppy_fops; -		sprintf(disks[dr]->disk_name, "fd%d", dr); +		blk_queue_max_hw_sectors(disks[drive]->queue, 64); +		disks[drive]->major = FLOPPY_MAJOR; +		disks[drive]->first_minor = TOMINOR(drive); +		disks[drive]->fops = &floppy_fops; +		sprintf(disks[drive]->disk_name, "fd%d", drive); -		init_timer(&motor_off_timer[dr]); -		motor_off_timer[dr].data = dr; -		motor_off_timer[dr].function = motor_off_callback; +		init_timer(&motor_off_timer[drive]); +		motor_off_timer[drive].data = drive; +		motor_off_timer[drive].function = motor_off_callback;  	}  	err = register_blkdev(FLOPPY_MAJOR, "fd"); @@ -4282,9 +4286,7 @@ static int __init do_floppy_init(void)  	}  	for (drive = 0; drive < N_DRIVE; drive++) { -		if (!(allowed_drive_mask & (1 << drive))) -			continue; -		if (fdc_state[FDC(drive)].version == FDC_NONE) +		if (!floppy_available(drive))  			continue;  		floppy_device[drive].name = floppy_device_name; @@ -4293,7 +4295,7 @@ static int __init do_floppy_init(void)  		err = platform_device_register(&floppy_device[drive]);  		if (err) -			goto out_release_dma; +			goto out_remove_drives;  		err = device_create_file(&floppy_device[drive].dev,  					 &dev_attr_cmos); @@ -4311,29 +4313,34 @@ static int __init do_floppy_init(void)  out_unreg_platform_dev:  	platform_device_unregister(&floppy_device[drive]); +out_remove_drives: +	while (drive--) { +		if (floppy_available(drive)) { +			del_gendisk(disks[drive]); +			device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); +			platform_device_unregister(&floppy_device[drive]); +		} +	}  out_release_dma:  	if (atomic_read(&usage_count))  		floppy_release_irq_and_dma();  out_unreg_region:  	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);  	platform_driver_unregister(&floppy_driver); -out_destroy_workq: -	destroy_workqueue(floppy_wq);  out_unreg_blkdev:  	unregister_blkdev(FLOPPY_MAJOR, "fd");  out_put_disk: -	while (dr--) { -		del_timer_sync(&motor_off_timer[dr]); -		if (disks[dr]->queue) { -			blk_cleanup_queue(disks[dr]->queue); -			/* -			 * put_disk() is not paired with add_disk() and -			 * will put queue reference one extra time. fix it. -			 */ -			disks[dr]->queue = NULL; +	for (drive = 0; drive < N_DRIVE; drive++) { +		if (!disks[drive]) +			break; +		if (disks[drive]->queue) { +			del_timer_sync(&motor_off_timer[drive]); +			blk_cleanup_queue(disks[drive]->queue); +			disks[drive]->queue = NULL;  		} -		put_disk(disks[dr]); +		put_disk(disks[drive]);  	} +	destroy_workqueue(floppy_wq);  	return err;  } @@ -4551,8 +4558,7 @@ static void __exit floppy_module_exit(void)  	for (drive = 0; drive < N_DRIVE; drive++) {  		del_timer_sync(&motor_off_timer[drive]); -		if ((allowed_drive_mask & (1 << drive)) && -		    fdc_state[FDC(drive)].version != FDC_NONE) { +		if (floppy_available(drive)) {  			del_gendisk(disks[drive]);  			device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);  			platform_device_unregister(&floppy_device[drive]); diff --git a/drivers/block/loop.c b/drivers/block/loop.c index e9d594fd12c..54046e51160 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo)  	if (lo->lo_state != Lo_bound)  		return -ENXIO; -	if (lo->lo_refcnt > 1)	/* we needed one fd for the ioctl */ -		return -EBUSY; +	/* +	 * If we've explicitly asked to tear down the loop device, +	 * and it has an elevated reference count, set it for auto-teardown when +	 * the last reference goes away. This stops $!~#$@ udev from +	 * preventing teardown because it decided that it needs to run blkid on +	 * the loopback device whenever they appear. xfstests is notorious for +	 * failing tests because blkid via udev races with a losetup +	 * <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d +	 * command to fail with EBUSY. +	 */ +	if (lo->lo_refcnt > 1) { +		lo->lo_flags |= LO_FLAGS_AUTOCLEAR; +		mutex_unlock(&lo->lo_ctl_mutex); +		return 0; +	}  	if (filp == NULL)  		return -EINVAL; diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index f946d31d691..adc6f36564c 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -2035,8 +2035,9 @@ static unsigned int implicit_sector(unsigned char command,  	}  	return rv;  } - -static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout) +static void mtip_set_timeout(struct driver_data *dd, +					struct host_to_dev_fis *fis, +					unsigned int *timeout, u8 erasemode)  {  	switch (fis->command) {  	case ATA_CMD_DOWNLOAD_MICRO: @@ -2044,7 +2045,10 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)  		break;  	case ATA_CMD_SEC_ERASE_UNIT:  	case 0xFC: -		*timeout = 240000; /* 4 minutes */ +		if (erasemode) +			*timeout = ((*(dd->port->identify + 90) * 2) * 60000); +		else +			*timeout = ((*(dd->port->identify + 89) * 2) * 60000);  		break;  	case ATA_CMD_STANDBYNOW1:  		*timeout = 120000;  /* 2 minutes */ @@ -2087,6 +2091,7 @@ static int exec_drive_taskfile(struct driver_data *dd,  	unsigned int transfer_size;  	unsigned long task_file_data;  	int intotal = outtotal + req_task->out_size; +	int erasemode = 0;  	taskout = req_task->out_size;  	taskin = req_task->in_size; @@ -2212,7 +2217,13 @@ static int exec_drive_taskfile(struct driver_data *dd,  		fis.lba_hi,  		fis.device); -	mtip_set_timeout(&fis, &timeout); +	/* check for erase mode support during secure erase.*/ +	if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) +					&& (outbuf[0] & MTIP_SEC_ERASE_MODE)) { +		erasemode = 1; +	} + +	mtip_set_timeout(dd, &fis, &timeout, erasemode);  	/* Determine the correct transfer size.*/  	if (force_single_sector) diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 18627a1d04c..5f4a917bd8b 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -33,6 +33,9 @@  /* offset of Device Control register in PCIe extended capabilites space */  #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET	0x48 +/* check for erase mode support during secure erase */ +#define MTIP_SEC_ERASE_MODE     0x3 +  /* # of times to retry timed out/failed IOs */  #define MTIP_MAX_RETRIES	2 diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 9ad3b5ec1dc..9a54623e52d 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -158,8 +158,8 @@ struct xen_vbd {  	struct block_device	*bdev;  	/* Cached size parameter. */  	sector_t		size; -	bool			flush_support; -	bool			discard_secure; +	unsigned int		flush_support:1; +	unsigned int		discard_secure:1;  };  struct backend_info; diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 4f66171c668..f58434c2617 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)  {  	struct xen_blkif *blkif; -	blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL); +	blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL);  	if (!blkif)  		return ERR_PTR(-ENOMEM); -	memset(blkif, 0, sizeof(*blkif));  	blkif->domid = domid;  	spin_lock_init(&blkif->blk_ring_lock);  	atomic_set(&blkif->refcnt, 1); @@ -196,7 +195,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)  	}  } -void xen_blkif_free(struct xen_blkif *blkif) +static void xen_blkif_free(struct xen_blkif *blkif)  {  	if (!atomic_dec_and_test(&blkif->refcnt))  		BUG(); @@ -257,7 +256,7 @@ static struct attribute_group xen_vbdstat_group = {  VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);  VBD_SHOW(mode, "%s\n", be->mode); -int xenvbd_sysfs_addif(struct xenbus_device *dev) +static int xenvbd_sysfs_addif(struct xenbus_device *dev)  {  	int error; @@ -281,7 +280,7 @@ fail1:	device_remove_file(&dev->dev, &dev_attr_physical_device);  	return error;  } -void xenvbd_sysfs_delif(struct xenbus_device *dev) +static void xenvbd_sysfs_delif(struct xenbus_device *dev)  {  	sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group);  	device_remove_file(&dev->dev, &dev_attr_mode); diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 320debbe32f..9b4f0116ff2 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -1456,7 +1456,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int old_camera_power;  static int sonypi_suspend(struct device *dev) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index b40ee1403be..399831690fe 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -328,6 +328,7 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,  		cpufreq_update_policy(cpu);  		break;  	case CPU_DOWN_PREPARE: +	case CPU_DOWN_PREPARE_FROZEN:  		cpufreq_stats_free_sysfs(cpu);  		break;  	case CPU_DEAD: diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 129e80bfff2..e3ebb4fa2c3 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -5,7 +5,7 @@   *  http://www.gnu.org/licenses/gpl.html   *   *  Maintainer: - *  Andreas Herrmann <andreas.herrmann3@amd.com> + *  Andreas Herrmann <herrmann.der.user@googlemail.com>   *   *  Based on the powernow-k7.c module written by Dave Jones.   *  (C) 2003 Dave Jones on behalf of SuSE Labs @@ -1052,14 +1052,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,  	struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq,  					     .relation = relation }; -	/* -	 * Must run on @pol->cpu.  cpufreq core is responsible for ensuring -	 * that we're bound to the current CPU and pol->cpu stays online. -	 */ -	if (smp_processor_id() == pol->cpu) -		return powernowk8_target_fn(&pta); -	else -		return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); +	return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);  }  /* Driver entry point to verify the policy and range of frequencies */ diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 677cd6e4e1a..d4c12180c65 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -90,6 +90,17 @@ config DW_DMAC  	  Support the Synopsys DesignWare AHB DMA controller.  This  	  can be integrated in chips such as the Atmel AT32ap7000. +config DW_DMAC_BIG_ENDIAN_IO +	bool "Use big endian I/O register access" +	default y if AVR32 +	depends on DW_DMAC +	help +	  Say yes here to use big endian I/O access when reading and writing +	  to the DMA controller registers. This is needed on some platforms, +	  like the Atmel AVR32 architecture. + +	  If unsure, use the default setting. +  config AT_HDMAC  	tristate "Atmel AHB DMA support"  	depends on ARCH_AT91 diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index ff39fa6cd2b..88965597b7d 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h @@ -98,9 +98,17 @@ struct dw_dma_regs {  	u32	DW_PARAMS;  }; +#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO +#define dma_readl_native ioread32be +#define dma_writel_native iowrite32be +#else +#define dma_readl_native readl +#define dma_writel_native writel +#endif +  /* To access the registers in early stage of probe */  #define dma_read_byaddr(addr, name) \ -	readl((addr) + offsetof(struct dw_dma_regs, name)) +	dma_readl_native((addr) + offsetof(struct dw_dma_regs, name))  /* Bitfields in DW_PARAMS */  #define DW_PARAMS_NR_CHAN	8		/* number of channels */ @@ -216,9 +224,9 @@ __dwc_regs(struct dw_dma_chan *dwc)  }  #define channel_readl(dwc, name) \ -	readl(&(__dwc_regs(dwc)->name)) +	dma_readl_native(&(__dwc_regs(dwc)->name))  #define channel_writel(dwc, name, val) \ -	writel((val), &(__dwc_regs(dwc)->name)) +	dma_writel_native((val), &(__dwc_regs(dwc)->name))  static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)  { @@ -246,9 +254,9 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)  }  #define dma_readl(dw, name) \ -	readl(&(__dw_regs(dw)->name)) +	dma_readl_native(&(__dw_regs(dw)->name))  #define dma_writel(dw, name, val) \ -	writel((val), &(__dw_regs(dw)->name)) +	dma_writel_native((val), &(__dw_regs(dw)->name))  #define channel_set_bit(dw, reg, mask) \  	dma_writel(dw, reg, ((mask) << 8) | (mask)) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index f11b5b2b1a1..7d9554cc497 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -474,8 +474,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)  			slot = i;  			break;  		} -		if (slot < 0) +		if (slot < 0) { +			spin_unlock_irqrestore(&imxdma->lock, flags);  			return -EBUSY; +		}  		imxdma->slots_2d[slot].xsr = d->x;  		imxdma->slots_2d[slot].ysr = d->y; diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 64385cde044..d451caace80 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan)  	sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc,  		node);  	/* Move the first queued descriptor to active list */ -	list_move_tail(&schan->queued, &schan->active); +	list_move_tail(&sdesc->node, &schan->active);  	/* Start the DMA transfer */  	writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 + @@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved(  	unsigned long iflags;  	int ret; -	if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) { +	if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) {  		ret = -EINVAL;  		goto err_dir;  	} diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 5a297a26211..cc8e7c78a23 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -170,8 +170,11 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)  	 * memory controller and apply to register. Search for the first  	 * bandwidth entry that is greater or equal than the setting requested  	 * and program that. If at last entry, turn off DRAM scrubbing. +	 * +	 * If no suitable bandwidth is found, turn off DRAM scrubbing entirely +	 * by falling back to the last element in scrubrates[].  	 */ -	for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { +	for (i = 0; i < ARRAY_SIZE(scrubrates) - 1; i++) {  		/*  		 * skip scrub rates which aren't recommended  		 * (see F10 BKDG, F3x58) @@ -181,12 +184,6 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)  		if (scrubrates[i].bandwidth <= new_bw)  			break; - -		/* -		 * if no suitable bandwidth found, turn off DRAM scrubbing -		 * entirely by falling back to the last element in the -		 * scrubrates array. -		 */  	}  	scrubval = scrubrates[i].scrubval; diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index 725eb5aa8d8..e87196f6d2d 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c @@ -14,6 +14,7 @@   *   */ +#include <linux/module.h>  #include <linux/slab.h>  #include <linux/device.h>  #include <linux/platform_device.h> @@ -161,13 +162,12 @@ static int __devinit adc_jack_probe(struct platform_device *pdev)  	err = request_any_context_irq(data->irq, adc_jack_irq_thread,  			pdata->irq_flags, pdata->name, data); -	if (err) { +	if (err < 0) {  		dev_err(&pdev->dev, "error: irq %d\n", data->irq); -		err = -EINVAL;  		goto err_irq;  	} -	goto out; +	return 0;  err_irq:  	extcon_dev_unregister(&data->edev); @@ -196,3 +196,7 @@ static struct platform_driver adc_jack_driver = {  };  module_platform_driver(adc_jack_driver); + +MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); +MODULE_DESCRIPTION("ADC Jack extcon driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 946a3188b2b..d398821097f 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -41,7 +41,7 @@   * every single port-type of the following cable names. Please choose cable   * names that are actually used in your extcon device.   */ -const char *extcon_cable_name[] = { +const char extcon_cable_name[][CABLE_NAME_MAX + 1] = {  	[EXTCON_USB]		= "USB",  	[EXTCON_USB_HOST]	= "USB-Host",  	[EXTCON_TA]		= "TA", @@ -62,8 +62,6 @@ const char *extcon_cable_name[] = {  	[EXTCON_VIDEO_IN]	= "Video-in",  	[EXTCON_VIDEO_OUT]	= "Video-out",  	[EXTCON_MECHANICAL]	= "Mechanical", - -	NULL,  };  static struct class *extcon_class; @@ -91,17 +89,13 @@ static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)  		return 0;  	for (i = 0; edev->mutually_exclusive[i]; i++) { -		int count = 0, j; +		int weight;  		u32 correspondants = new_state & edev->mutually_exclusive[i]; -		u32 exp = 1; -		for (j = 0; j < 32; j++) { -			if (exp & correspondants) -				count++; -			if (count > 1) -				return i + 1; -			exp <<= 1; -		} +		/* calculate the total number of bits set */ +		weight = hweight32(correspondants); +		if (weight > 1) +			return i + 1;  	}  	return 0; @@ -362,7 +356,7 @@ int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)  EXPORT_SYMBOL_GPL(extcon_get_cable_state);  /** - * extcon_get_cable_state_() - Set the status of a specific cable. + * extcon_set_cable_state_() - Set the status of a specific cable.   * @edev:	the extcon device that has the cable.   * @index:	cable index that can be retrieved by extcon_find_cable_index().   * @cable_state:	the new cable status. The default semantics is @@ -382,7 +376,7 @@ int extcon_set_cable_state_(struct extcon_dev *edev,  EXPORT_SYMBOL_GPL(extcon_set_cable_state_);  /** - * extcon_get_cable_state() - Set the status of a specific cable. + * extcon_set_cable_state() - Set the status of a specific cable.   * @edev:	the extcon device that has the cable.   * @cable_name:	cable name.   * @cable_state:	the new cable status. The default semantics is @@ -447,6 +441,8 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val,   *			      extcon device.   * @obj:	an empty extcon_specific_cable_nb object to be returned.   * @extcon_name:	the name of extcon device. + *			if NULL, extcon_register_interest will register + *			every cable with the target cable_name given.   * @cable_name:		the target cable name.   * @nb:		the notifier block to get notified.   * @@ -466,22 +462,44 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,  			     const char *extcon_name, const char *cable_name,  			     struct notifier_block *nb)  { -	if (!obj || !extcon_name || !cable_name || !nb) +	if (!obj || !cable_name || !nb)  		return -EINVAL; -	obj->edev = extcon_get_extcon_dev(extcon_name); -	if (!obj->edev) -		return -ENODEV; +	if (extcon_name) { +		obj->edev = extcon_get_extcon_dev(extcon_name); +		if (!obj->edev) +			return -ENODEV; -	obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); -	if (obj->cable_index < 0) -		return -ENODEV; +		obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); +		if (obj->cable_index < 0) +			return -ENODEV; + +		obj->user_nb = nb; + +		obj->internal_nb.notifier_call = _call_per_cable; + +		return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb); +	} else { +		struct class_dev_iter iter; +		struct extcon_dev *extd; +		struct device *dev; + +		if (!extcon_class) +			return -ENODEV; +		class_dev_iter_init(&iter, extcon_class, NULL, NULL); +		while ((dev = class_dev_iter_next(&iter))) { +			extd = (struct extcon_dev *)dev_get_drvdata(dev); -	obj->user_nb = nb; +			if (extcon_find_cable_index(extd, cable_name) < 0) +				continue; -	obj->internal_nb.notifier_call = _call_per_cable; +			class_dev_iter_exit(&iter); +			return extcon_register_interest(obj, extd->name, +						cable_name, nb); +		} -	return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb); +		return -ENODEV; +	}  }  /** @@ -551,43 +569,9 @@ static int create_extcon_class(void)  	return 0;  } -static void extcon_cleanup(struct extcon_dev *edev, bool skip) -{ -	mutex_lock(&extcon_dev_list_lock); -	list_del(&edev->entry); -	mutex_unlock(&extcon_dev_list_lock); - -	if (!skip && get_device(edev->dev)) { -		int index; - -		if (edev->mutually_exclusive && edev->max_supported) { -			for (index = 0; edev->mutually_exclusive[index]; -			     index++) -				kfree(edev->d_attrs_muex[index].attr.name); -			kfree(edev->d_attrs_muex); -			kfree(edev->attrs_muex); -		} - -		for (index = 0; index < edev->max_supported; index++) -			kfree(edev->cables[index].attr_g.name); - -		if (edev->max_supported) { -			kfree(edev->extcon_dev_type.groups); -			kfree(edev->cables); -		} - -		device_unregister(edev->dev); -		put_device(edev->dev); -	} - -	kfree(edev->dev); -} -  static void extcon_dev_release(struct device *dev)  { -	struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); - -	extcon_cleanup(edev, true); +	kfree(dev);  }  static const char *muex_name = "mutually_exclusive"; @@ -813,7 +797,40 @@ EXPORT_SYMBOL_GPL(extcon_dev_register);   */  void extcon_dev_unregister(struct extcon_dev *edev)  { -	extcon_cleanup(edev, false); +	int index; + +	mutex_lock(&extcon_dev_list_lock); +	list_del(&edev->entry); +	mutex_unlock(&extcon_dev_list_lock); + +	if (IS_ERR_OR_NULL(get_device(edev->dev))) { +		dev_err(edev->dev, "Failed to unregister extcon_dev (%s)\n", +				dev_name(edev->dev)); +		return; +	} + +	if (edev->mutually_exclusive && edev->max_supported) { +		for (index = 0; edev->mutually_exclusive[index]; +				index++) +			kfree(edev->d_attrs_muex[index].attr.name); +		kfree(edev->d_attrs_muex); +		kfree(edev->attrs_muex); +	} + +	for (index = 0; index < edev->max_supported; index++) +		kfree(edev->cables[index].attr_g.name); + +	if (edev->max_supported) { +		kfree(edev->extcon_dev_type.groups); +		kfree(edev->cables); +	} + +#if defined(CONFIG_ANDROID) +	if (switch_class) +		class_compat_remove_link(switch_class, edev->dev, NULL); +#endif +	device_unregister(edev->dev); +	put_device(edev->dev);  }  EXPORT_SYMBOL_GPL(extcon_dev_unregister); @@ -825,6 +842,9 @@ module_init(extcon_class_init);  static void __exit extcon_class_exit(void)  { +#if defined(CONFIG_ANDROID) +	class_compat_unregister(switch_class); +#endif  	class_destroy(extcon_class);  }  module_exit(extcon_class_exit); diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index 3cc152e690b..71d3ab7b3d8 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -26,7 +26,6 @@  #include <linux/interrupt.h>  #include <linux/platform_device.h>  #include <linux/slab.h> -#include <linux/extcon.h>  #include <linux/workqueue.h>  #include <linux/gpio.h>  #include <linux/extcon.h> diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index e21387e2da5..a17d0d91ada 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -239,25 +239,19 @@ const char *max77693_extcon_cable[] = {  static int max77693_muic_set_debounce_time(struct max77693_muic_info *info,  		enum max77693_muic_adc_debounce_time time)  { -	int ret = 0; -	u8 ctrl3; +	int ret;  	switch (time) {  	case ADC_DEBOUNCE_TIME_5MS:  	case ADC_DEBOUNCE_TIME_10MS:  	case ADC_DEBOUNCE_TIME_25MS:  	case ADC_DEBOUNCE_TIME_38_62MS: -		ret = max77693_read_reg(info->max77693->regmap_muic, -				MAX77693_MUIC_REG_CTRL3, &ctrl3); -		ctrl3 &= ~CONTROL3_ADCDBSET_MASK; -		ctrl3 |= (time << CONTROL3_ADCDBSET_SHIFT); - -		ret = max77693_write_reg(info->max77693->regmap_muic, -				MAX77693_MUIC_REG_CTRL3, ctrl3); -		if (ret) { +		ret = max77693_update_reg(info->max77693->regmap_muic, +					  MAX77693_MUIC_REG_CTRL3, +					  time << CONTROL3_ADCDBSET_SHIFT, +					  CONTROL3_ADCDBSET_MASK); +		if (ret)  			dev_err(info->dev, "failed to set ADC debounce time\n"); -			ret = -EINVAL; -		}  		break;  	default:  		dev_err(info->dev, "invalid ADC debounce time\n"); @@ -657,6 +651,8 @@ out:  static int __devinit max77693_muic_probe(struct platform_device *pdev)  {  	struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent); +	struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev); +	struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;  	struct max77693_muic_info *info;  	int ret, i;  	u8 id; @@ -727,6 +723,31 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)  		goto err_extcon;  	} +	/* Initialize MUIC register by using platform data */ +	for (i = 0 ; i < muic_pdata->num_init_data ; i++) { +		enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR; + +		max77693_write_reg(info->max77693->regmap_muic, +				muic_pdata->init_data[i].addr, +				muic_pdata->init_data[i].data); + +		switch (muic_pdata->init_data[i].addr) { +		case MAX77693_MUIC_REG_INTMASK1: +			irq_src = MUIC_INT1; +			break; +		case MAX77693_MUIC_REG_INTMASK2: +			irq_src = MUIC_INT2; +			break; +		case MAX77693_MUIC_REG_INTMASK3: +			irq_src = MUIC_INT3; +			break; +		} + +		if (irq_src < MAX77693_IRQ_GROUP_NR) +			info->max77693->irq_masks_cur[irq_src] +				= muic_pdata->init_data[i].data; +	} +  	/* Check revision number of MUIC device*/  	ret = max77693_read_reg(info->max77693->regmap_muic,  			MAX77693_MUIC_REG_ID, &id); @@ -762,6 +783,7 @@ static int __devexit max77693_muic_remove(struct platform_device *pdev)  		free_irq(muic_irqs[i].virq, info);  	cancel_work_sync(&info->irq_work);  	extcon_dev_unregister(info->edev); +	kfree(info->edev);  	kfree(info);  	return 0; diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index ef9090a4271..77b66b0cc8f 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -271,8 +271,6 @@ out:  static int max8997_muic_handle_charger_type_detach(  				struct max8997_muic_info *info)  { -	int ret = 0; -  	switch (info->pre_charger_type) {  	case MAX8997_CHARGER_TYPE_USB:  		extcon_set_cable_state(info->edev, "USB", false); @@ -290,11 +288,11 @@ static int max8997_muic_handle_charger_type_detach(  		extcon_set_cable_state(info->edev, "Fast-charger", false);  		break;  	default: -		ret = -EINVAL; +		return -EINVAL;  		break;  	} -	return ret; +	return 0;  }  static int max8997_muic_handle_charger_type(struct max8997_muic_info *info, diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d055cee3694..f11d8e3b404 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -47,7 +47,7 @@ if GPIOLIB  config OF_GPIO  	def_bool y -	depends on OF && !SPARC +	depends on OF  config DEBUG_GPIO  	bool "Debug GPIO calls" diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index ed3e55161bd..f05e54258ff 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -153,7 +153,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)  	}  	chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers; -	chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL); +	chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL);  	if (!chip->buffer) {  		ret = -ENOMEM;  		goto exit_destroy; diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 7a874129e5d..cf7afb9eb61 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -244,6 +244,8 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,  	if (ret)  		return ret; +	mvebu_gpio_set(chip, pin, value); +  	spin_lock_irqsave(&mvchip->lock, flags);  	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));  	u &= ~(1 << pin); @@ -644,7 +646,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)  	ct->handler = handle_edge_irq;  	ct->chip.name = mvchip->chip.label; -	irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE, +	irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,  			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);  	/* Setup irq domain on top of the generic chip. */ diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 94cbc842fbc..d335af1d4d8 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -251,6 +251,40 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,  	}  } +/** + * _clear_gpio_debounce - clear debounce settings for a gpio + * @bank: the gpio bank we're acting upon + * @gpio: the gpio number on this @gpio + * + * If a gpio is using debounce, then clear the debounce enable bit and if + * this is the only gpio in this bank using debounce, then clear the debounce + * time too. The debounce clock will also be disabled when calling this function + * if this is the only gpio in the bank using debounce. + */ +static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio) +{ +	u32 gpio_bit = GPIO_BIT(bank, gpio); + +	if (!bank->dbck_flag) +		return; + +	if (!(bank->dbck_enable_mask & gpio_bit)) +		return; + +	bank->dbck_enable_mask &= ~gpio_bit; +	bank->context.debounce_en &= ~gpio_bit; +	__raw_writel(bank->context.debounce_en, +		     bank->base + bank->regs->debounce_en); + +	if (!bank->dbck_enable_mask) { +		bank->context.debounce = 0; +		__raw_writel(bank->context.debounce, bank->base + +			     bank->regs->debounce); +		clk_disable(bank->dbck); +		bank->dbck_enabled = false; +	} +} +  static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,  						unsigned trigger)  { @@ -539,6 +573,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)  	_set_gpio_irqenable(bank, gpio, 0);  	_clear_gpio_irqstatus(bank, gpio);  	_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); +	_clear_gpio_debounce(bank, gpio);  }  /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 031c6adf5b6..1a3e2b9b477 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d)  	unsigned long flags;  	spin_lock_irqsave(&tgpio->lock, flags); -	tgpio->last_ier &= ~(1 << offset); +	tgpio->last_ier &= ~(1UL << offset);  	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);  	spin_unlock_irqrestore(&tgpio->lock, flags);  } @@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d)  	unsigned long flags;  	spin_lock_irqsave(&tgpio->lock, flags); -	tgpio->last_ier |= 1 << offset; +	tgpio->last_ier |= 1UL << offset;  	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);  	spin_unlock_irqrestore(&tgpio->lock, flags);  } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5d6c71edc73..1c8d9e3380e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class,  	 */  	status = gpio_request(gpio, "sysfs"); -	if (status < 0) +	if (status < 0) { +		if (status == -EPROBE_DEFER) +			status = -ENODEV;  		goto done; - +	}  	status = gpio_export(gpio, true);  	if (status < 0)  		gpio_free(gpio); @@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label)  	spin_lock_irqsave(&gpio_lock, flags); -	if (!gpio_is_valid(gpio)) +	if (!gpio_is_valid(gpio)) { +		status = -EINVAL;  		goto done; +	}  	desc = &gpio_desc[gpio];  	chip = desc->chip;  	if (chip == NULL) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 7ef1b673e1b..133b4132983 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp)  	int minor_id = iminor(inode);  	struct drm_minor *minor;  	int retcode = 0; +	int need_setup = 0; +	struct address_space *old_mapping;  	minor = idr_find(&drm_minors_idr, minor_id);  	if (!minor) @@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp)  	if (drm_device_is_unplugged(dev))  		return -ENODEV; +	if (!dev->open_count++) +		need_setup = 1; +	mutex_lock(&dev->struct_mutex); +	old_mapping = dev->dev_mapping; +	if (old_mapping == NULL) +		dev->dev_mapping = &inode->i_data; +	/* ihold ensures nobody can remove inode with our i_data */ +	ihold(container_of(dev->dev_mapping, struct inode, i_data)); +	inode->i_mapping = dev->dev_mapping; +	filp->f_mapping = dev->dev_mapping; +	mutex_unlock(&dev->struct_mutex); +  	retcode = drm_open_helper(inode, filp, dev); -	if (!retcode) { -		atomic_inc(&dev->counts[_DRM_STAT_OPENS]); -		if (!dev->open_count++) -			retcode = drm_setup(dev); -	} -	if (!retcode) { -		mutex_lock(&dev->struct_mutex); -		if (dev->dev_mapping == NULL) -			dev->dev_mapping = &inode->i_data; -		/* ihold ensures nobody can remove inode with our i_data */ -		ihold(container_of(dev->dev_mapping, struct inode, i_data)); -		inode->i_mapping = dev->dev_mapping; -		filp->f_mapping = dev->dev_mapping; -		mutex_unlock(&dev->struct_mutex); +	if (retcode) +		goto err_undo; +	atomic_inc(&dev->counts[_DRM_STAT_OPENS]); +	if (need_setup) { +		retcode = drm_setup(dev); +		if (retcode) +			goto err_undo;  	} +	return 0; +err_undo: +	mutex_lock(&dev->struct_mutex); +	filp->f_mapping = old_mapping; +	inode->i_mapping = old_mapping; +	iput(container_of(dev->dev_mapping, struct inode, i_data)); +	dev->dev_mapping = old_mapping; +	mutex_unlock(&dev->struct_mutex); +	dev->open_count--;  	return retcode;  }  EXPORT_SYMBOL(drm_open); diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 59a26e577b5..fc345d4ebb0 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -1,6 +1,6 @@  config DRM_EXYNOS  	tristate "DRM Support for Samsung SoC EXYNOS Series" -	depends on DRM && PLAT_SAMSUNG +	depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)  	select DRM_KMS_HELPER  	select FB_CFB_FILLRECT  	select FB_CFB_COPYAREA diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index 18c271862ca..0f68a287267 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,  	exynos_connector->encoder_id = encoder->base.id;  	exynos_connector->manager = manager;  	exynos_connector->dpms = DRM_MODE_DPMS_OFF; +	connector->dpms = DRM_MODE_DPMS_OFF;  	connector->encoder = encoder;  	err = drm_mode_connector_attach_encoder(connector, encoder); diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index e51503fbaf2..241ad1eeec6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -43,12 +43,14 @@   * @manager: specific encoder has its own manager to control a hardware   *	appropriately and we can access a hardware drawing on this manager.   * @dpms: store the encoder dpms value. + * @updated: indicate whether overlay data updating is needed or not.   */  struct exynos_drm_encoder {  	struct drm_crtc			*old_crtc;  	struct drm_encoder		drm_encoder;  	struct exynos_drm_manager	*manager; -	int dpms; +	int				dpms; +	bool				updated;  };  static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode) @@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)  	switch (mode) {  	case DRM_MODE_DPMS_ON:  		if (manager_ops && manager_ops->apply) -			manager_ops->apply(manager->dev); +			if (!exynos_encoder->updated) +				manager_ops->apply(manager->dev); +  		exynos_drm_connector_power(encoder, mode);  		exynos_encoder->dpms = mode;  		break; @@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)  	case DRM_MODE_DPMS_OFF:  		exynos_drm_connector_power(encoder, mode);  		exynos_encoder->dpms = mode; +		exynos_encoder->updated = false;  		break;  	default:  		DRM_ERROR("unspecified mode %d\n", mode); @@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)  static void exynos_drm_encoder_commit(struct drm_encoder *encoder)  { -	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); +	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); +	struct exynos_drm_manager *manager = exynos_encoder->manager;  	struct exynos_drm_manager_ops *manager_ops = manager->ops;  	DRM_DEBUG_KMS("%s\n", __FILE__);  	if (manager_ops && manager_ops->commit)  		manager_ops->commit(manager->dev); + +	/* +	 * this will avoid one issue that overlay data is updated to +	 * real hardware two times. +	 * And this variable will be used to check if the data was +	 * already updated or not by exynos_drm_encoder_dpms function. +	 */ +	exynos_encoder->updated = true;  }  static void exynos_drm_encoder_disable(struct drm_encoder *encoder) @@ -401,19 +415,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)  		manager_ops->dpms(manager->dev, mode);  	/* -	 * set current mode to new one so that data aren't updated into -	 * registers by drm_helper_connector_dpms two times. -	 * -	 * in case that drm_crtc_helper_set_mode() is called, -	 * overlay_ops->commit() and manager_ops->commit() callbacks -	 * can be called two times, first at drm_crtc_helper_set_mode() -	 * and second at drm_helper_connector_dpms(). -	 * so with this setting, when drm_helper_connector_dpms() is called -	 * encoder->funcs->dpms() will be ignored. -	 */ -	exynos_encoder->dpms = mode; - -	/*  	 * if this condition is ok then it means that the crtc is already  	 * detached from encoder and last function for detaching is properly  	 * done, so clear pipe from manager to prevent repeated call. diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 614b2e9ac46..e7fbb823fd8 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)  		const struct of_device_id *match;  		match = of_match_node(of_match_ptr(mixer_match_types),  							  pdev->dev.of_node); -		drv = match->data; +		drv = (struct mixer_drv_data *)match->data;  	} else {  		drv = (struct mixer_drv_data *)  			platform_get_device_id(pdev)->driver_data; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index c9bfd83dde6..61ae104dca8 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  		goto put_gmch;  	} -	i915_kick_out_firmware_fb(dev_priv); +	if (drm_core_check_feature(dev, DRIVER_MODESET)) +		i915_kick_out_firmware_fb(dev_priv);  	pci_set_master(dev->pdev); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index f78061af704..b726b478a4f 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -729,7 +729,7 @@ void intel_crt_init(struct drm_device *dev)  	crt->base.type = INTEL_OUTPUT_ANALOG;  	crt->base.cloneable = true; -	if (IS_HASWELL(dev)) +	if (IS_HASWELL(dev) || IS_I830(dev))  		crt->base.crtc_mask = (1 << 0);  	else  		crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 495625914e4..d7bc817f51a 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -341,9 +341,17 @@ static int intel_overlay_off(struct intel_overlay *overlay)  	intel_ring_emit(ring, flip_addr);  	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);  	/* turn overlay off */ -	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); -	intel_ring_emit(ring, flip_addr); -	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); +	if (IS_I830(dev)) { +		/* Workaround: Don't disable the overlay fully, since otherwise +		 * it dies on the next OVERLAY_ON cmd. */ +		intel_ring_emit(ring, MI_NOOP); +		intel_ring_emit(ring, MI_NOOP); +		intel_ring_emit(ring, MI_NOOP); +	} else { +		intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); +		intel_ring_emit(ring, flip_addr); +		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); +	}  	intel_ring_advance(ring);  	return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index e019b236986..e2aacd32954 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev)  	props.type = BACKLIGHT_RAW;  	props.max_brightness = _intel_panel_get_max_backlight(dev);  	if (props.max_brightness == 0) { -		DRM_ERROR("Failed to get maximum backlight value\n"); +		DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");  		return -ENODEV;  	}  	dev_priv->backlight = diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index c01d97db006..79d308da29f 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -894,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)  }  #endif +static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, +				       unsigned if_index, uint8_t tx_rate, +				       uint8_t *data, unsigned length) +{ +	uint8_t set_buf_index[2] = { if_index, 0 }; +	uint8_t hbuf_size, tmp[8]; +	int i; + +	if (!intel_sdvo_set_value(intel_sdvo, +				  SDVO_CMD_SET_HBUF_INDEX, +				  set_buf_index, 2)) +		return false; + +	if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO, +				  &hbuf_size, 1)) +		return false; + +	/* Buffer size is 0 based, hooray! */ +	hbuf_size++; + +	DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n", +		      if_index, length, hbuf_size); + +	for (i = 0; i < hbuf_size; i += 8) { +		memset(tmp, 0, 8); +		if (i < length) +			memcpy(tmp, data + i, min_t(unsigned, 8, length - i)); + +		if (!intel_sdvo_set_value(intel_sdvo, +					  SDVO_CMD_SET_HBUF_DATA, +					  tmp, 8)) +			return false; +	} + +	return intel_sdvo_set_value(intel_sdvo, +				    SDVO_CMD_SET_HBUF_TXRATE, +				    &tx_rate, 1); +} +  static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)  {  	struct dip_infoframe avi_if = { @@ -901,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)  		.ver = DIP_VERSION_AVI,  		.len = DIP_LEN_AVI,  	}; -	uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; -	uint8_t set_buf_index[2] = { 1, 0 };  	uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; -	uint64_t *data = (uint64_t *)sdvo_data; -	unsigned i;  	intel_dip_infoframe_csum(&avi_if); @@ -915,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)  	sdvo_data[3] = avi_if.checksum;  	memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); -	if (!intel_sdvo_set_value(intel_sdvo, -				  SDVO_CMD_SET_HBUF_INDEX, -				  set_buf_index, 2)) -		return false; - -	for (i = 0; i < sizeof(sdvo_data); i += 8) { -		if (!intel_sdvo_set_value(intel_sdvo, -					  SDVO_CMD_SET_HBUF_DATA, -					  data, 8)) -			return false; -		data++; -	} - -	return intel_sdvo_set_value(intel_sdvo, -				    SDVO_CMD_SET_HBUF_TXRATE, -				    &tx_rate, 1); +	return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, +					  SDVO_HBUF_TX_VSYNC, +					  sdvo_data, sizeof(sdvo_data));  }  static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 9d030142ee4..770bdd6ecd9 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {  #define SDVO_CMD_SET_AUDIO_STAT		0x91  #define SDVO_CMD_GET_AUDIO_STAT		0x92  #define SDVO_CMD_SET_HBUF_INDEX		0x93 +  #define SDVO_HBUF_INDEX_ELD		0 +  #define SDVO_HBUF_INDEX_AVI_IF	1  #define SDVO_CMD_GET_HBUF_INDEX		0x94  #define SDVO_CMD_GET_HBUF_INFO		0x95  #define SDVO_CMD_SET_HBUF_AV_SPLIT	0x96 diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c index 4d620644867..a6d3cd6490f 100644 --- a/drivers/gpu/drm/nouveau/core/core/mm.c +++ b/drivers/gpu/drm/nouveau/core/core/mm.c @@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)  	node = kzalloc(sizeof(*node), GFP_KERNEL);  	if (!node)  		return -ENOMEM; -	node->offset = roundup(offset, mm->block_size); -	node->length = rounddown(offset + length, mm->block_size) - node->offset; + +	if (length) { +		node->offset  = roundup(offset, mm->block_size); +		node->length  = rounddown(offset + length, mm->block_size); +		node->length -= node->offset; +	}  	list_add_tail(&node->nl_entry, &mm->nodes);  	list_add_tail(&node->fl_entry, &mm->free);  	mm->heap_nodes++; -	mm->heap_size += length;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 16a9afb1060..05a909a17ce 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -22,6 +22,8 @@   * Authors: Ben Skeggs   */ +#include <subdev/bar.h> +  #include <engine/software.h>  #include <engine/disp.h> @@ -37,6 +39,7 @@ nv50_disp_sclass[] = {  static void  nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)  { +	struct nouveau_bar *bar = nouveau_bar(priv);  	struct nouveau_disp *disp = &priv->base;  	struct nouveau_software_chan *chan, *temp;  	unsigned long flags; @@ -46,18 +49,19 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)  		if (chan->vblank.crtc != crtc)  			continue; -		nv_wr32(priv, 0x001704, chan->vblank.channel); -		nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); -  		if (nv_device(priv)->chipset == 0x50) { +			nv_wr32(priv, 0x001704, chan->vblank.channel); +			nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); +			bar->flush(bar);  			nv_wr32(priv, 0x001570, chan->vblank.offset);  			nv_wr32(priv, 0x001574, chan->vblank.value);  		} else { -			if (nv_device(priv)->chipset >= 0xc0) { -				nv_wr32(priv, 0x06000c, -					upper_32_bits(chan->vblank.offset)); -			} -			nv_wr32(priv, 0x060010, chan->vblank.offset); +			nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); +			bar->flush(bar); +			nv_wr32(priv, 0x06000c, +				upper_32_bits(chan->vblank.offset)); +			nv_wr32(priv, 0x060010, +				lower_32_bits(chan->vblank.offset));  			nv_wr32(priv, 0x060014, chan->vblank.value);  		} diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 8d0021049ec..425001204a8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -156,8 +156,8 @@ nv40_graph_context_ctor(struct nouveau_object *parent,  static int  nv40_graph_context_fini(struct nouveau_object *object, bool suspend)  { -	struct nv04_graph_priv *priv = (void *)object->engine; -	struct nv04_graph_chan *chan = (void *)object; +	struct nv40_graph_priv *priv = (void *)object->engine; +	struct nv40_graph_chan *chan = (void *)object;  	u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4;  	int ret = 0; diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c index 12418574efe..f7c581ad199 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c @@ -38,7 +38,7 @@ struct nv40_mpeg_priv {  };  struct nv40_mpeg_chan { -	struct nouveau_mpeg base; +	struct nouveau_mpeg_chan base;  };  /******************************************************************************* diff --git a/drivers/gpu/drm/nouveau/core/include/core/mm.h b/drivers/gpu/drm/nouveau/core/include/core/mm.h index 9ee9bf4028c..975137ba34a 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/mm.h +++ b/drivers/gpu/drm/nouveau/core/include/core/mm.h @@ -19,7 +19,6 @@ struct nouveau_mm {  	u32 block_size;  	int heap_nodes; -	u32 heap_size;  };  int  nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index 27fb1af7a77..5f570806143 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  			     ((priv->base.ram.size & 0x000000ff) << 32);  	tags = nv_rd32(priv, 0x100320); -	if (tags) { -		ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); -		if (ret) -			return ret; +	ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); +	if (ret) +		return ret; -		nv_debug(priv, "%d compression tags\n", tags); -	} +	nv_debug(priv, "%d compression tags\n", tags);  	size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;  	switch (device->chipset) { diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 3d2c88310f9..dbfc2abf0cf 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		case DCB_I2C_NVIO_BIT:  			port->drive = info.drive & 0x0f;  			if (device->card_type < NV_D0) { -				if (info.drive >= ARRAY_SIZE(nv50_i2c_port)) +				if (port->drive >= ARRAY_SIZE(nv50_i2c_port))  					break;  				port->drive = nv50_i2c_port[port->drive];  				port->sense = port->drive; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c index 49050d991e7..9474cfca6e4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c @@ -67,7 +67,7 @@ nv41_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)  static void  nv41_vm_flush(struct nouveau_vm *vm)  { -	struct nv04_vm_priv *priv = (void *)vm->vmm; +	struct nv04_vmmgr_priv *priv = (void *)vm->vmm;  	mutex_lock(&nv_subdev(priv)->mutex);  	nv_wr32(priv, 0x100810, 0x00000022); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 9a6e2cb282d..d3595b23434 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -355,7 +355,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)  	 * valid - it's not (rh#613284)  	 */  	if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { -		if (!(nv_connector->edid = nouveau_acpi_edid(dev, connector))) { +		if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) {  			status = connector_status_connected;  			goto out;  		} diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index d2f8ffeed74..86124b131f4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_disp *pdisp = nouveau_disp(drm->device);  	struct nouveau_display *disp; +	u32 pclass = dev->pdev->class >> 8;  	int ret, gen;  	disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); @@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev)  	drm_kms_helper_poll_init(dev);  	drm_kms_helper_poll_disable(dev); -	if (nv_device(drm->device)->card_type < NV_50) -		ret = nv04_display_create(dev); -	else -	if (nv_device(drm->device)->card_type < NV_D0) -		ret = nv50_display_create(dev); -	else -		ret = nvd0_display_create(dev); -	if (ret) -		goto disp_create_err; - -	if (dev->mode_config.num_crtc) { -		ret = drm_vblank_init(dev, dev->mode_config.num_crtc); +	if (nouveau_modeset == 1 || +	    (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) { +		if (nv_device(drm->device)->card_type < NV_50) +			ret = nv04_display_create(dev); +		else +		if (nv_device(drm->device)->card_type < NV_D0) +			ret = nv50_display_create(dev); +		else +			ret = nvd0_display_create(dev);  		if (ret) -			goto vblank_err; +			goto disp_create_err; + +		if (dev->mode_config.num_crtc) { +			ret = drm_vblank_init(dev, dev->mode_config.num_crtc); +			if (ret) +				goto vblank_err; +		} + +		nouveau_backlight_init(dev);  	} -	nouveau_backlight_init(dev);  	return 0;  vblank_err: @@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)  	nouveau_backlight_exit(dev);  	drm_vblank_cleanup(dev); -	disp->dtor(dev); +	if (disp->dtor) +		disp->dtor(dev);  	drm_kms_helper_poll_fini(dev);  	drm_mode_config_cleanup(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index ccae8c26ae2..0910125cbbc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");  static int nouveau_noaccel = 0;  module_param_named(noaccel, nouveau_noaccel, int, 0400); -MODULE_PARM_DESC(modeset, "enable driver"); -static int nouveau_modeset = -1; +MODULE_PARM_DESC(modeset, "enable driver (default: auto, " +		          "0 = disabled, 1 = enabled, 2 = headless)"); +int nouveau_modeset = -1;  module_param_named(modeset, nouveau_modeset, int, 0400);  static struct drm_driver driver; @@ -363,7 +364,8 @@ nouveau_drm_unload(struct drm_device *dev)  	nouveau_pm_fini(dev); -	nouveau_display_fini(dev); +	if (dev->mode_config.num_crtc) +		nouveau_display_fini(dev);  	nouveau_display_destroy(dev);  	nouveau_irq_fini(dev); @@ -403,13 +405,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)  	    pm_state.event == PM_EVENT_PRETHAW)  		return 0; -	NV_INFO(drm, "suspending fbcon...\n"); -	nouveau_fbcon_set_suspend(dev, 1); +	if (dev->mode_config.num_crtc) { +		NV_INFO(drm, "suspending fbcon...\n"); +		nouveau_fbcon_set_suspend(dev, 1); -	NV_INFO(drm, "suspending display...\n"); -	ret = nouveau_display_suspend(dev); -	if (ret) -		return ret; +		NV_INFO(drm, "suspending display...\n"); +		ret = nouveau_display_suspend(dev); +		if (ret) +			return ret; +	}  	NV_INFO(drm, "evicting buffers...\n");  	ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM); @@ -445,8 +449,10 @@ fail_client:  		nouveau_client_init(&cli->base);  	} -	NV_INFO(drm, "resuming display...\n"); -	nouveau_display_resume(dev); +	if (dev->mode_config.num_crtc) { +		NV_INFO(drm, "resuming display...\n"); +		nouveau_display_resume(dev); +	}  	return ret;  } @@ -486,8 +492,10 @@ nouveau_drm_resume(struct pci_dev *pdev)  	nouveau_irq_postinstall(dev);  	nouveau_pm_resume(dev); -	NV_INFO(drm, "resuming display...\n"); -	nouveau_display_resume(dev); +	if (dev->mode_config.num_crtc) { +		NV_INFO(drm, "resuming display...\n"); +		nouveau_display_resume(dev); +	}  	return 0;  } @@ -662,9 +670,7 @@ nouveau_drm_init(void)  #ifdef CONFIG_VGA_CONSOLE  		if (vgacon_text_force())  			nouveau_modeset = 0; -		else  #endif -			nouveau_modeset = 1;  	}  	if (!nouveau_modeset) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index 81947121754..a1016992708 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);  		nv_info((cli), fmt, ##args);                                   \  } while (0) +extern int nouveau_modeset; +  #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 9ca8afdb554..1d8cb506a28 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)  	nv_subdev(pmc)->intr(nv_subdev(pmc)); -	if (device->card_type >= NV_D0) { -		if (nv_rd32(device, 0x000100) & 0x04000000) -			nvd0_display_intr(dev); -	} else -	if (device->card_type >= NV_50) { -		if (nv_rd32(device, 0x000100) & 0x04000000) -			nv50_display_intr(dev); +	if (dev->mode_config.num_crtc) { +		if (device->card_type >= NV_D0) { +			if (nv_rd32(device, 0x000100) & 0x04000000) +				nvd0_display_intr(dev); +		} else +		if (device->card_type >= NV_50) { +			if (nv_rd32(device, 0x000100) & 0x04000000) +				nv50_display_intr(dev); +		}  	}  	return IRQ_HANDLED; diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 347a3bd78d0..64f7020fb60 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -220,7 +220,7 @@ out:  	NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);  	if (blue == 0x18) { -		NV_INFO(drm, "Load detected on head A\n"); +		NV_DEBUG(drm, "Load detected on head A\n");  		return connector_status_connected;  	} @@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)  	if (nv17_dac_sample_load(encoder) &  	    NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { -		NV_INFO(drm, "Load detected on output %c\n", -			'@' + ffs(dcb->or)); +		NV_DEBUG(drm, "Load detected on output %c\n", +			 '@' + ffs(dcb->or));  		return connector_status_connected;  	} else {  		return connector_status_disconnected; @@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON); -	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", -		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), -		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); +	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", +		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), +		 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  }  void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) @@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)  		return;  	nv_encoder->last_dpms = mode; -	NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n", -		     mode, nv_encoder->dcb->index); +	NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n", +		 mode, nv_encoder->dcb->index);  	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);  } diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index da55d7642c8..184cdf80676 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON); -	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", -		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), -		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); +	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", +		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), +		 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  }  static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) @@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)  		return;  	nv_encoder->last_dpms = mode; -	NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", -		     mode, nv_encoder->dcb->index); +	NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", +		 mode, nv_encoder->dcb->index);  	if (was_powersaving && is_powersaving_dpms(mode))  		return; @@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)  		return;  	nv_encoder->last_dpms = mode; -	NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", -		     mode, nv_encoder->dcb->index); +	NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", +		 mode, nv_encoder->dcb->index);  	nv04_dfp_update_backlight(encoder, mode);  	nv04_dfp_update_fp_control(encoder, mode); diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 099fbeda6e2..62e826a139b 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c @@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)  	struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;  	uint8_t crtc1A; -	NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n", -		mode, nv_encoder->dcb->index); +	NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n", +		 mode, nv_encoder->dcb->index);  	state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); @@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON); -	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", -		      drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, -		      '@' + ffs(nv_encoder->dcb->or)); +	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", +		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  }  static void nv04_tv_destroy(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 2e566e123e9..3bce0299f64 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1696,35 +1696,43 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)  			return ATOM_PPLL2;  		DRM_ERROR("unable to allocate a PPLL\n");  		return ATOM_PPLL_INVALID; -	} else { -		if (ASIC_IS_AVIVO(rdev)) { -			/* in DP mode, the DP ref clock can come from either PPLL -			 * depending on the asic: -			 * DCE3: PPLL1 or PPLL2 -			 */ -			if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) { -				/* use the same PPLL for all DP monitors */ -				pll = radeon_get_shared_dp_ppll(crtc); -				if (pll != ATOM_PPLL_INVALID) -					return pll; -			} else { -				/* use the same PPLL for all monitors with the same clock */ -				pll = radeon_get_shared_nondp_ppll(crtc); -				if (pll != ATOM_PPLL_INVALID) -					return pll; -			} -			/* all other cases */ -			pll_in_use = radeon_get_pll_use_mask(crtc); +	} else if (ASIC_IS_AVIVO(rdev)) { +		/* in DP mode, the DP ref clock can come from either PPLL +		 * depending on the asic: +		 * DCE3: PPLL1 or PPLL2 +		 */ +		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) { +			/* use the same PPLL for all DP monitors */ +			pll = radeon_get_shared_dp_ppll(crtc); +			if (pll != ATOM_PPLL_INVALID) +				return pll; +		} else { +			/* use the same PPLL for all monitors with the same clock */ +			pll = radeon_get_shared_nondp_ppll(crtc); +			if (pll != ATOM_PPLL_INVALID) +				return pll; +		} +		/* all other cases */ +		pll_in_use = radeon_get_pll_use_mask(crtc); +		/* the order shouldn't matter here, but we probably +		 * need this until we have atomic modeset +		 */ +		if (rdev->flags & RADEON_IS_IGP) {  			if (!(pll_in_use & (1 << ATOM_PPLL1)))  				return ATOM_PPLL1;  			if (!(pll_in_use & (1 << ATOM_PPLL2)))  				return ATOM_PPLL2; -			DRM_ERROR("unable to allocate a PPLL\n"); -			return ATOM_PPLL_INVALID;  		} else { -			/* on pre-R5xx asics, the crtc to pll mapping is hardcoded */ -			return radeon_crtc->crtc_id; +			if (!(pll_in_use & (1 << ATOM_PPLL2))) +				return ATOM_PPLL2; +			if (!(pll_in_use & (1 << ATOM_PPLL1))) +				return ATOM_PPLL1;  		} +		DRM_ERROR("unable to allocate a PPLL\n"); +		return ATOM_PPLL_INVALID; +	} else { +		/* on pre-R5xx asics, the crtc to pll mapping is hardcoded */ +		return radeon_crtc->crtc_id;  	}  } diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 49cbb3795a1..ba498f8e47a 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -184,6 +184,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,  	struct radeon_backlight_privdata *pdata;  	struct radeon_encoder_atom_dig *dig;  	u8 backlight_level; +	char bl_name[16];  	if (!radeon_encoder->enc_priv)  		return; @@ -203,7 +204,9 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,  	memset(&props, 0, sizeof(props));  	props.max_brightness = RADEON_MAX_BL_LEVEL;  	props.type = BACKLIGHT_RAW; -	bd = backlight_device_register("radeon_bl", &drm_connector->kdev, +	snprintf(bl_name, sizeof(bl_name), +		 "radeon_bl%d", dev->primary->index); +	bd = backlight_device_register(bl_name, &drm_connector->kdev,  				       pdata, &radeon_atom_backlight_ops, &props);  	if (IS_ERR(bd)) {  		DRM_ERROR("Backlight registration failed\n"); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 14313ad43b7..af31f829f4a 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1372,7 +1372,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s  	WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN);  	for (i = 0; i < rdev->num_crtc; i++) { -		if (save->crtc_enabled) { +		if (save->crtc_enabled[i]) {  			if (ASIC_IS_DCE6(rdev)) {  				tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);  				tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 573ed1bc6cf..c042e497e45 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p,  	/* macro tile width & height */  	palign = (8 * surf->bankw * track->npipes) * surf->mtilea;  	halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; -	mtileb = (palign / 8) * (halign / 8) * tileb;; +	mtileb = (palign / 8) * (halign / 8) * tileb;  	mtile_pr = surf->nbx / palign;  	mtile_ps = (mtile_pr * surf->nby) / halign;  	surf->layer_size = mtile_ps * mtileb * slice_pt; @@ -2725,6 +2725,9 @@ static bool evergreen_vm_reg_valid(u32 reg)  	/* check config regs */  	switch (reg) {  	case GRBM_GFX_INDEX: +	case CP_STRMOUT_CNTL: +	case CP_COHER_CNTL: +	case CP_COHER_SIZE:  	case VGT_VTX_VECT_EJECT_REG:  	case VGT_CACHE_INVALIDATION:  	case VGT_GS_VERTEX_REUSE: @@ -2829,6 +2832,7 @@ static bool evergreen_vm_reg_valid(u32 reg)  	case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS:  		return true;  	default: +		DRM_ERROR("Invalid register 0x%x in CS\n", reg);  		return false;  	}  } diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index df542f1a5df..2bc0f6a1b42 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -91,6 +91,10 @@  #define		FB_READ_EN					(1 << 0)  #define		FB_WRITE_EN					(1 << 1) +#define	CP_STRMOUT_CNTL					0x84FC + +#define	CP_COHER_CNTL					0x85F0 +#define	CP_COHER_SIZE					0x85F4  #define	CP_COHER_BASE					0x85F8  #define	CP_STALLED_STAT1			0x8674  #define	CP_STALLED_STAT2			0x8678 diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 8c74c729586..81e6a568c29 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1538,26 +1538,31 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe,  {  	struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];  	uint32_t r600_flags = cayman_vm_page_flags(rdev, flags); -	int i; -	radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, 1 + count * 2)); -	radeon_ring_write(ring, pe); -	radeon_ring_write(ring, upper_32_bits(pe) & 0xff); -	for (i = 0; i < count; ++i) { -		uint64_t value = 0; -		if (flags & RADEON_VM_PAGE_SYSTEM) { -			value = radeon_vm_map_gart(rdev, addr); -			value &= 0xFFFFFFFFFFFFF000ULL; -			addr += incr; +	while (count) { +		unsigned ndw = 1 + count * 2; +		if (ndw > 0x3FFF) +			ndw = 0x3FFF; -		} else if (flags & RADEON_VM_PAGE_VALID) { -			value = addr; -			addr += incr; -		} +		radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, ndw)); +		radeon_ring_write(ring, pe); +		radeon_ring_write(ring, upper_32_bits(pe) & 0xff); +		for (; ndw > 1; ndw -= 2, --count, pe += 8) { +			uint64_t value = 0; +			if (flags & RADEON_VM_PAGE_SYSTEM) { +				value = radeon_vm_map_gart(rdev, addr); +				value &= 0xFFFFFFFFFFFFF000ULL; +				addr += incr; + +			} else if (flags & RADEON_VM_PAGE_VALID) { +				value = addr; +				addr += incr; +			} -		value |= r600_flags; -		radeon_ring_write(ring, value); -		radeon_ring_write(ring, upper_32_bits(value)); +			value |= r600_flags; +			radeon_ring_write(ring, value); +			radeon_ring_write(ring, upper_32_bits(value)); +		}  	}  } @@ -1586,4 +1591,8 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)  	/* bits 0-7 are the VM contexts0-7 */  	radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0));  	radeon_ring_write(ring, 1 << vm->id); + +	/* sync PFP to ME, otherwise we might get invalid PFP reads */ +	radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); +	radeon_ring_write(ring, 0x0);  } diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 2423d1b5d38..cbef6815907 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -502,6 +502,7 @@  #define	PACKET3_MPEG_INDEX				0x3A  #define	PACKET3_WAIT_REG_MEM				0x3C  #define	PACKET3_MEM_WRITE				0x3D +#define	PACKET3_PFP_SYNC_ME				0x42  #define	PACKET3_SURFACE_SYNC				0x43  #              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)  #              define PACKET3_CB1_DEST_BASE_ENA    (1 << 7) diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 1aa3f910b99..15f5ded65e0 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -87,7 +87,7 @@ static union acpi_object *radeon_atpx_call(acpi_handle handle, int function,  		atpx_arg_elements[1].integer.value = 0;  	} -	status = acpi_evaluate_object(handle, "ATPX", &atpx_arg, &buffer); +	status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);  	/* Fail only if calling the method fails and ATPX is supported */  	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { @@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)  }  /** - * radeon_atpx_switchto - switch to the requested GPU + * radeon_atpx_power_state - power down/up the requested GPU   * - * @id: GPU to switch to + * @id: GPU to power down/up   * @state: requested power state (0 = off, 1 = on)   *   * Execute the necessary ATPX function to power down/up the discrete GPU @@ -373,11 +373,11 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,  }  /** - * radeon_atpx_pci_probe_handle - look up the ATRM and ATPX handles + * radeon_atpx_pci_probe_handle - look up the ATPX handle   *   * @pdev: pci device   * - * Look up the ATPX and ATRM handles (all asics). + * Look up the ATPX handles (all asics).   * Returns true if the handles are found, false if not.   */  static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 67cfc1795ec..b884c362a8c 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)  	struct drm_mode_object *obj;  	int i;  	enum drm_connector_status ret = connector_status_disconnected; -	bool dret = false; +	bool dret = false, broken_edid = false;  	if (!force && radeon_check_hpd_status_unchanged(connector))  		return connector->status; @@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)  				ret = connector_status_disconnected;  				DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));  				radeon_connector->ddc_bus = NULL; +			} else { +				ret = connector_status_connected; +				broken_edid = true; /* defer use_digital to later */  			}  		} else {  			radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); @@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)  			encoder_funcs = encoder->helper_private;  			if (encoder_funcs->detect) { -				if (ret != connector_status_connected) { -					ret = encoder_funcs->detect(encoder, connector); -					if (ret == connector_status_connected) { -						radeon_connector->use_digital = false; +				if (!broken_edid) { +					if (ret != connector_status_connected) { +						/* deal with analog monitors without DDC */ +						ret = encoder_funcs->detect(encoder, connector); +						if (ret == connector_status_connected) { +							radeon_connector->use_digital = false; +						} +						if (ret != connector_status_disconnected) +							radeon_connector->detected_by_load = true;  					} -					if (ret != connector_status_disconnected) -						radeon_connector->detected_by_load = true; +				} else { +					enum drm_connector_status lret; +					/* assume digital unless load detected otherwise */ +					radeon_connector->use_digital = true; +					lret = encoder_funcs->detect(encoder, connector); +					DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret); +					if (lret == connector_status_connected) +						radeon_connector->use_digital = false;  				}  				break;  			} diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index bd13ca09eb6..e2f5f888c37 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -355,6 +355,8 @@ int radeon_wb_init(struct radeon_device *rdev)   */  void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base)  { +	uint64_t limit = (uint64_t)radeon_vram_limit << 20; +  	mc->vram_start = base;  	if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) {  		dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); @@ -368,8 +370,8 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64  		mc->mc_vram_size = mc->aper_size;  	}  	mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; -	if (radeon_vram_limit && radeon_vram_limit < mc->real_vram_size) -		mc->real_vram_size = radeon_vram_limit; +	if (limit && limit < mc->real_vram_size) +		mc->real_vram_size = limit;  	dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n",  			mc->mc_vram_size >> 20, mc->vram_start,  			mc->vram_end, mc->real_vram_size >> 20); @@ -835,6 +837,19 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)  }  /** + * radeon_check_pot_argument - check that argument is a power of two + * + * @arg: value to check + * + * Validates that a certain argument is a power of two (all asics). + * Returns true if argument is valid. + */ +static bool radeon_check_pot_argument(int arg) +{ +	return (arg & (arg - 1)) == 0; +} + +/**   * radeon_check_arguments - validate module params   *   * @rdev: radeon_device pointer @@ -845,52 +860,25 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)  static void radeon_check_arguments(struct radeon_device *rdev)  {  	/* vramlimit must be a power of two */ -	switch (radeon_vram_limit) { -	case 0: -	case 4: -	case 8: -	case 16: -	case 32: -	case 64: -	case 128: -	case 256: -	case 512: -	case 1024: -	case 2048: -	case 4096: -		break; -	default: +	if (!radeon_check_pot_argument(radeon_vram_limit)) {  		dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n",  				radeon_vram_limit);  		radeon_vram_limit = 0; -		break;  	} -	radeon_vram_limit = radeon_vram_limit << 20; +  	/* gtt size must be power of two and greater or equal to 32M */ -	switch (radeon_gart_size) { -	case 4: -	case 8: -	case 16: +	if (radeon_gart_size < 32) {  		dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n",  				radeon_gart_size);  		radeon_gart_size = 512; -		break; -	case 32: -	case 64: -	case 128: -	case 256: -	case 512: -	case 1024: -	case 2048: -	case 4096: -		break; -	default: + +	} else if (!radeon_check_pot_argument(radeon_gart_size)) {  		dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n",  				radeon_gart_size);  		radeon_gart_size = 512; -		break;  	} -	rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; +	rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20; +  	/* AGP mode can only be -1, 1, 2, 4, 8 */  	switch (radeon_agpmode) {  	case -1: diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index a7677dd1ce9..4debd60e5aa 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -355,14 +355,13 @@ int radeon_gart_init(struct radeon_device *rdev)  	DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",  		 rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);  	/* Allocate pages table */ -	rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages, -				   GFP_KERNEL); +	rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages);  	if (rdev->gart.pages == NULL) {  		radeon_gart_fini(rdev);  		return -ENOMEM;  	} -	rdev->gart.pages_addr = kzalloc(sizeof(dma_addr_t) * -					rdev->gart.num_cpu_pages, GFP_KERNEL); +	rdev->gart.pages_addr = vzalloc(sizeof(dma_addr_t) * +					rdev->gart.num_cpu_pages);  	if (rdev->gart.pages_addr == NULL) {  		radeon_gart_fini(rdev);  		return -ENOMEM; @@ -388,8 +387,8 @@ void radeon_gart_fini(struct radeon_device *rdev)  		radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages);  	}  	rdev->gart.ready = false; -	kfree(rdev->gart.pages); -	kfree(rdev->gart.pages_addr); +	vfree(rdev->gart.pages); +	vfree(rdev->gart.pages_addr);  	rdev->gart.pages = NULL;  	rdev->gart.pages_addr = NULL; @@ -577,7 +576,7 @@ void radeon_vm_manager_fini(struct radeon_device *rdev)   *   * Global and local mutex must be locked!   */ -int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm) +static int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm)  {  	struct radeon_vm *vm_evict; @@ -1036,8 +1035,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,  		pte = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]);  		pte += (addr & mask) * 8; -		if (((last_pte + 8 * count) != pte) || -		    ((count + nptes) > 1 << 11)) { +		if ((last_pte + 8 * count) != pte) {  			if (count) {  				radeon_asic_vm_set_page(rdev, last_pte, @@ -1148,17 +1146,17 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,  	if (RADEON_VM_BLOCK_SIZE > 11)  		/* reserve space for one header for every 2k dwords */ -		ndw += (nptes >> 11) * 3; +		ndw += (nptes >> 11) * 4;  	else  		/* reserve space for one header for  		    every (1 << BLOCK_SIZE) entries */ -		ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 3; +		ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 4;  	/* reserve space for pte addresses */  	ndw += nptes * 2;  	/* reserve space for one header for every 2k dwords */ -	ndw += (npdes >> 11) * 3; +	ndw += (npdes >> 11) * 4;  	/* reserve space for pde addresses */  	ndw += npdes * 2; diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index f38fbcc4693..fe5c1f6b795 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -53,6 +53,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,  				struct drm_gem_object **obj)  {  	struct radeon_bo *robj; +	unsigned long max_size;  	int r;  	*obj = NULL; @@ -60,11 +61,26 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,  	if (alignment < PAGE_SIZE) {  		alignment = PAGE_SIZE;  	} + +	/* maximun bo size is the minimun btw visible vram and gtt size */ +	max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size); +	if (size > max_size) { +		printk(KERN_WARNING "%s:%d alloc size %dMb bigger than %ldMb limit\n", +		       __func__, __LINE__, size >> 20, max_size >> 20); +		return -ENOMEM; +	} + +retry:  	r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj);  	if (r) { -		if (r != -ERESTARTSYS) +		if (r != -ERESTARTSYS) { +			if (initial_domain == RADEON_GEM_DOMAIN_VRAM) { +				initial_domain |= RADEON_GEM_DOMAIN_GTT; +				goto retry; +			}  			DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",  				  size, initial_domain, alignment, r); +		}  		return r;  	}  	*obj = &robj->gem_base; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 5677a424b58..6857cb4efb7 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)  	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);  	struct drm_device *dev = crtc->dev;  	struct radeon_device *rdev = dev->dev_private; +	uint32_t crtc_ext_cntl = 0;  	uint32_t mask;  	if (radeon_crtc->crtc_id) @@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)  			RADEON_CRTC_VSYNC_DIS |  			RADEON_CRTC_HSYNC_DIS); +	/* +	 * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC. +	 * Therefore it is set in the DAC DMPS function. +	 * This is different for GPU's with a single CRTC but a primary and a +	 * TV DAC: here it controls the single CRTC no matter where it is +	 * routed. Therefore we set it here. +	 */ +	if (rdev->flags & RADEON_SINGLE_CRTC) +		crtc_ext_cntl = RADEON_CRTC_CRT_ON; +	  	switch (mode) {  	case DRM_MODE_DPMS_ON:  		radeon_crtc->enabled = true; @@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)  		else {  			WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |  									 RADEON_CRTC_DISP_REQ_EN_B)); -			WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask); +			WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));  		}  		drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);  		radeon_crtc_load_lut(crtc); @@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)  		else {  			WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |  										    RADEON_CRTC_DISP_REQ_EN_B)); -			WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); +			WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl));  		}  		radeon_crtc->enabled = false;  		/* adjust pm to dpms changes AFTER disabling crtcs */ diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index a13ad9d707c..f5ba2241dac 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -370,6 +370,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,  	struct backlight_properties props;  	struct radeon_backlight_privdata *pdata;  	uint8_t backlight_level; +	char bl_name[16];  	if (!radeon_encoder->enc_priv)  		return; @@ -389,7 +390,9 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,  	memset(&props, 0, sizeof(props));  	props.max_brightness = RADEON_MAX_BL_LEVEL;  	props.type = BACKLIGHT_RAW; -	bd = backlight_device_register("radeon_bl", &drm_connector->kdev, +	snprintf(bl_name, sizeof(bl_name), +		 "radeon_bl%d", dev->primary->index); +	bd = backlight_device_register(bl_name, &drm_connector->kdev,  				       pdata, &radeon_backlight_ops, &props);  	if (IS_ERR(bd)) {  		DRM_ERROR("Backlight registration failed\n"); @@ -534,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode  		break;  	} -	WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); +	/* handled in radeon_crtc_dpms() */ +	if (!(rdev->flags & RADEON_SINGLE_CRTC)) +		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);  	WREG32(RADEON_DAC_CNTL, dac_cntl);  	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); @@ -659,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc  	if (ASIC_IS_R300(rdev))  		tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); +	else if (ASIC_IS_RV100(rdev)) +		tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);  	else  		tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); @@ -668,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc  	tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;  	WREG32(RADEON_DAC_CNTL, tmp); +	tmp = dac_macro_cntl;  	tmp &= ~(RADEON_DAC_PDWN_R |  		 RADEON_DAC_PDWN_G |  		 RADEON_DAC_PDWN_B); @@ -1089,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)  	} else {  		if (is_tv)  			WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); -		else +		/* handled in radeon_crtc_dpms() */ +		else if (!(rdev->flags & RADEON_SINGLE_CRTC))  			WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);  		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);  	} @@ -1413,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,  	return found;  } +static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder, +					 struct drm_connector *connector) +{ +	struct drm_device *dev = encoder->dev; +	struct radeon_device *rdev = dev->dev_private; +	uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; +	uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; +	uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; +	uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp; +	uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; +	bool found = false; +	int i; + +	/* save the regs we need */ +	gpio_monid = RREG32(RADEON_GPIO_MONID); +	fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); +	disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); +	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); +	disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A); +	disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B); +	disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C); +	disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D); +	disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E); +	disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F); +	crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP); +	crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP); +	crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID); +	crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID); + +	tmp = RREG32(RADEON_GPIO_MONID); +	tmp &= ~RADEON_GPIO_A_0; +	WREG32(RADEON_GPIO_MONID, tmp); + +	WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON | +				     RADEON_FP2_PANEL_FORMAT | +				     R200_FP2_SOURCE_SEL_TRANS_UNIT | +				     RADEON_FP2_DVO_EN | +				     R200_FP2_DVO_RATE_SEL_SDR)); + +	WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX | +					 RADEON_DISP_TRANS_MATRIX_GRAPHICS)); + +	WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN | +				       RADEON_CRTC2_DISP_REQ_EN_B)); + +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + +	WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); +	WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); +	WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); +	WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + +	for (i = 0; i < 200; i++) { +		tmp = RREG32(RADEON_GPIO_MONID); +		if (tmp & RADEON_GPIO_Y_0) +			found = true; + +		if (found) +			break; + +		if (!drm_can_sleep()) +			mdelay(1); +		else +			msleep(1); +	} + +	/* restore the regs we used */ +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); +	WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); +	WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); +	WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); +	WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); +	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); +	WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); +	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); +	WREG32(RADEON_GPIO_MONID, gpio_monid); + +	return found; +} +  static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,  							     struct drm_connector *connector)  {  	struct drm_device *dev = encoder->dev;  	struct radeon_device *rdev = dev->dev_private; -	uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; -	uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; +	uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl; +	uint32_t gpiopad_a = 0, pixclks_cntl, tmp; +	uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;  	enum drm_connector_status found = connector_status_disconnected;  	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);  	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; @@ -1456,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder  		return connector_status_disconnected;  	} +	/* R200 uses an external DAC for secondary DAC */ +	if (rdev->family == CHIP_R200) { +		if (radeon_legacy_ext_dac_detect(encoder, connector)) +			found = connector_status_connected; +		return found; +	} +  	/* save the regs we need */  	pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); -	gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0; -	disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0; -	disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG); -	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + +	if (rdev->flags & RADEON_SINGLE_CRTC) { +		crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); +	} else { +		if (ASIC_IS_R300(rdev)) { +			gpiopad_a = RREG32(RADEON_GPIOPAD_A); +			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); +		} else { +			disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); +		} +		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); +	}  	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);  	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);  	dac_cntl2 = RREG32(RADEON_DAC_CNTL2); @@ -1470,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder  			       | RADEON_PIX2CLK_DAC_ALWAYS_ONb);  	WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); -	if (ASIC_IS_R300(rdev)) -		WREG32_P(RADEON_GPIOPAD_A, 1, ~1); - -	tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; -	tmp |= RADEON_CRTC2_CRT2_ON | -		(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); - -	WREG32(RADEON_CRTC2_GEN_CNTL, tmp); - -	if (ASIC_IS_R300(rdev)) { -		tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; -		tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; -		WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); +	if (rdev->flags & RADEON_SINGLE_CRTC) { +		tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; +		WREG32(RADEON_CRTC_EXT_CNTL, tmp);  	} else { -		tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; -		WREG32(RADEON_DISP_HW_DEBUG, tmp); +		tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; +		tmp |= RADEON_CRTC2_CRT2_ON | +			(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); +		WREG32(RADEON_CRTC2_GEN_CNTL, tmp); + +		if (ASIC_IS_R300(rdev)) { +			WREG32_P(RADEON_GPIOPAD_A, 1, ~1); +			tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; +			tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; +			WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); +		} else { +			tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; +			WREG32(RADEON_DISP_HW_DEBUG, tmp); +		}  	}  	tmp = RADEON_TV_DAC_NBLANK | @@ -1527,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder  	WREG32(RADEON_DAC_CNTL2, dac_cntl2);  	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);  	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); -	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); -	if (ASIC_IS_R300(rdev)) { -		WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); -		WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); +	if (rdev->flags & RADEON_SINGLE_CRTC) { +		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);  	} else { -		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); +		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); +		if (ASIC_IS_R300(rdev)) { +			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); +			WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); +		} else { +			WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); +		}  	} +  	WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);  	return found; diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 8b27dd6e314..b91118ccef8 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -105,7 +105,6 @@ int radeon_bo_create(struct radeon_device *rdev,  	struct radeon_bo *bo;  	enum ttm_bo_type type;  	unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT; -	unsigned long max_size = 0;  	size_t acc_size;  	int r; @@ -121,18 +120,9 @@ int radeon_bo_create(struct radeon_device *rdev,  	}  	*bo_ptr = NULL; -	/* maximun bo size is the minimun btw visible vram and gtt size */ -	max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size); -	if ((page_align << PAGE_SHIFT) >= max_size) { -		printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n", -			__func__, __LINE__, page_align  >> (20 - PAGE_SHIFT), max_size >> 20); -		return -ENOMEM; -	} -  	acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size,  				       sizeof(struct radeon_bo)); -retry:  	bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);  	if (bo == NULL)  		return -ENOMEM; @@ -154,15 +144,6 @@ retry:  			acc_size, sg, &radeon_ttm_bo_destroy);  	up_read(&rdev->pm.mclk_lock);  	if (unlikely(r != 0)) { -		if (r != -ERESTARTSYS) { -			if (domain == RADEON_GEM_DOMAIN_VRAM) { -				domain |= RADEON_GEM_DOMAIN_GTT; -				goto retry; -			} -			dev_err(rdev->dev, -				"object_init failed for (%lu, 0x%08X)\n", -				size, domain); -		}  		return r;  	}  	*bo_ptr = bo; diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index df8dd770164..4422d630b33 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2474,6 +2474,7 @@ static bool si_vm_reg_valid(u32 reg)  	/* check config regs */  	switch (reg) {  	case GRBM_GFX_INDEX: +	case CP_STRMOUT_CNTL:  	case VGT_VTX_VECT_EJECT_REG:  	case VGT_CACHE_INVALIDATION:  	case VGT_ESGS_RING_SIZE: @@ -2808,26 +2809,31 @@ void si_vm_set_page(struct radeon_device *rdev, uint64_t pe,  {  	struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];  	uint32_t r600_flags = cayman_vm_page_flags(rdev, flags); -	int i; -	uint64_t value; -	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 2 + count * 2)); -	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | -				 WRITE_DATA_DST_SEL(1))); -	radeon_ring_write(ring, pe); -	radeon_ring_write(ring, upper_32_bits(pe)); -	for (i = 0; i < count; ++i) { -		if (flags & RADEON_VM_PAGE_SYSTEM) { -			value = radeon_vm_map_gart(rdev, addr); -			value &= 0xFFFFFFFFFFFFF000ULL; -		} else if (flags & RADEON_VM_PAGE_VALID) -			value = addr; -		else -			value = 0; -		addr += incr; -		value |= r600_flags; -		radeon_ring_write(ring, value); -		radeon_ring_write(ring, upper_32_bits(value)); +	while (count) { +		unsigned ndw = 2 + count * 2; +		if (ndw > 0x3FFE) +			ndw = 0x3FFE; + +		radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, ndw)); +		radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | +					 WRITE_DATA_DST_SEL(1))); +		radeon_ring_write(ring, pe); +		radeon_ring_write(ring, upper_32_bits(pe)); +		for (; ndw > 2; ndw -= 2, --count, pe += 8) { +			uint64_t value; +			if (flags & RADEON_VM_PAGE_SYSTEM) { +				value = radeon_vm_map_gart(rdev, addr); +				value &= 0xFFFFFFFFFFFFF000ULL; +			} else if (flags & RADEON_VM_PAGE_VALID) +				value = addr; +			else +				value = 0; +			addr += incr; +			value |= r600_flags; +			radeon_ring_write(ring, value); +			radeon_ring_write(ring, upper_32_bits(value)); +		}  	}  } @@ -2868,6 +2874,10 @@ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)  	radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);  	radeon_ring_write(ring, 0);  	radeon_ring_write(ring, 1 << vm->id); + +	/* sync PFP to ME, otherwise we might get invalid PFP reads */ +	radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); +	radeon_ring_write(ring, 0x0);  }  /* diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 7d2a20e5657..a8871afc5b4 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -424,6 +424,7 @@  #       define RDERR_INT_ENABLE                         (1 << 0)  #       define GUI_IDLE_INT_ENABLE                      (1 << 19) +#define	CP_STRMOUT_CNTL					0x84FC  #define	SCRATCH_REG0					0x8500  #define	SCRATCH_REG1					0x8504  #define	SCRATCH_REG2					0x8508 diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index fccd361f7b5..87aa5f5d3c8 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev,  int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,  		     const char *front, char **urb_buf_ptr, -		     u32 byte_offset, u32 byte_width, +		     u32 byte_offset, u32 device_byte_offset, u32 byte_width,  		     int *ident_ptr, int *sent_ptr);  int udl_dumb_create(struct drm_file *file_priv, diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 69a2b16f42a..d4ab3beaada 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info,  	list_for_each_entry(cur, &fbdefio->pagelist, lru) {  		if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), -				  &urb, (char *) info->fix.smem_start, -				  &cmd, cur->index << PAGE_SHIFT, -				  PAGE_SIZE, &bytes_identical, &bytes_sent)) +				     &urb, (char *) info->fix.smem_start, +				     &cmd, cur->index << PAGE_SHIFT, +				     cur->index << PAGE_SHIFT, +				     PAGE_SIZE, &bytes_identical, &bytes_sent))  			goto error;  		bytes_rendered += PAGE_SIZE;  	} @@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,  	for (i = y; i < y + height ; i++) {  		const int line_offset = fb->base.pitches[0] * i;  		const int byte_offset = line_offset + (x * bpp); - +		const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);  		if (udl_render_hline(dev, bpp, &urb,  				     (char *) fb->obj->vmapping, -				     &cmd, byte_offset, width * bpp, +				     &cmd, byte_offset, dev_byte_offset, +				     width * bpp,  				     &bytes_identical, &bytes_sent))  			goto error;  	} diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index dc095526ffb..142fee5f983 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -213,11 +213,12 @@ static void udl_compress_hline16(   */  int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,  		     const char *front, char **urb_buf_ptr, -		     u32 byte_offset, u32 byte_width, +		     u32 byte_offset, u32 device_byte_offset, +		     u32 byte_width,  		     int *ident_ptr, int *sent_ptr)  {  	const u8 *line_start, *line_end, *next_pixel; -	u32 base16 = 0 + (byte_offset / bpp) * 2; +	u32 base16 = 0 + (device_byte_offset / bpp) * 2;  	struct urb *urb = *urb_ptr;  	u8 *cmd = *urb_buf_ptr;  	u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c index 3ce68a2e312..d1498bfd787 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c @@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)  	BUG_ON(!atomic_read(&bo->reserved));  	BUG_ON(old_mem_type != TTM_PL_VRAM && -	       old_mem_type != VMW_PL_FLAG_GMR); +	       old_mem_type != VMW_PL_GMR);  	pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;  	if (pin) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index ed3c1e7ddde..2dd185e42f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1098,6 +1098,11 @@ static void vmw_pm_complete(struct device *kdev)  	struct drm_device *dev = pci_get_drvdata(pdev);  	struct vmw_private *dev_priv = vmw_priv(dev); +	mutex_lock(&dev_priv->hw_mutex); +	vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); +	(void) vmw_read(dev_priv, SVGA_REG_ID); +	mutex_unlock(&dev_priv->hw_mutex); +  	/**  	 * Reclaim 3d reference held by fbdev and potentially  	 * start fifo. diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 06ebdbb6ea0..fd7722aecf7 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -522,6 +522,12 @@ static const struct hid_device_id apple_devices[] = {  		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),  		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), +		.driver_data = APPLE_HAS_FN }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), +		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), +		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },  	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),  		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },  	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index bd3971bf31b..f4109fd657f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1532,6 +1532,9 @@ static const struct hid_device_id hid_have_special_driver[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },  	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },  	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },  	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, @@ -2139,6 +2142,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },  	{ } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 269b50912a4..9d7a42857ea 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -118,6 +118,9 @@  #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI	0x0252  #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO	0x0253  #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS	0x0254 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI	0x0259 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO	0x025a +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS	0x025b  #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI	0x0249  #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO	0x024a  #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS	0x024b diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 3acdcfcc17d..f676c01bb47 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -28,22 +28,30 @@  #define MS_RDESC		0x08  #define MS_NOGET		0x10  #define MS_DUPLICATE_USAGES	0x20 +#define MS_RDESC_3K		0x40 -/* - * Microsoft Wireless Desktop Receiver (Model 1028) has - * 'Usage Min/Max' where it ought to have 'Physical Min/Max' - */  static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,  		unsigned int *rsize)  {  	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); +	/* +	 * Microsoft Wireless Desktop Receiver (Model 1028) has +	 * 'Usage Min/Max' where it ought to have 'Physical Min/Max' +	 */  	if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&  			rdesc[559] == 0x29) {  		hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");  		rdesc[557] = 0x35;  		rdesc[559] = 0x45;  	} +	/* the same as above (s/usage/physical/) */ +	if ((quirks & MS_RDESC_3K) && *rsize == 106 && +			!memcmp((char []){ 0x19, 0x00, 0x29, 0xff }, +				&rdesc[94], 4)) { +		rdesc[94] = 0x35; +		rdesc[96] = 0x45; +	}  	return rdesc;  } @@ -192,7 +200,7 @@ static const struct hid_device_id ms_devices[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),  		.driver_data = MS_PRESENTER },  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), -		.driver_data = MS_ERGONOMY }, +		.driver_data = MS_ERGONOMY | MS_RDESC_3K },  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),  		.driver_data = MS_NOGET },  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 3eb02b94fc8..7867d69f0ef 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -210,8 +210,7 @@ static struct mt_class mt_classes[] = {  	},  	{ .name	= MT_CLS_GENERALTOUCH_PWT_TENFINGERS,  		.quirks	= MT_QUIRK_NOT_SEEN_MEANS_UP | -			MT_QUIRK_SLOT_IS_CONTACTNUMBER, -		.maxcontacts = 10 +			MT_QUIRK_SLOT_IS_CONTACTNUMBER  	},  	{ .name = MT_CLS_FLATFROG, @@ -421,11 +420,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,  			 * contact max are global to the report */  			td->last_field_index = field->index;  			return -1; -		}  		case HID_DG_TOUCH:  			/* Legacy devices use TIPSWITCH and not TOUCH.  			 * Let's just ignore this field. */  			return -1; +		}  		/* let hid-input decide for the others */  		return 0; diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 17d15bb610d..7c47fc3f7b2 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -42,7 +42,6 @@ static struct cdev hidraw_cdev;  static struct class *hidraw_class;  static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];  static DEFINE_MUTEX(minors_lock); -static void drop_ref(struct hidraw *hid, int exists_bit);  static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)  { @@ -114,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,  	__u8 *buf;  	int ret = 0; -	if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { +	if (!hidraw_table[minor]) {  		ret = -ENODEV;  		goto out;  	} @@ -262,7 +261,7 @@ static int hidraw_open(struct inode *inode, struct file *file)  	}  	mutex_lock(&minors_lock); -	if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { +	if (!hidraw_table[minor]) {  		err = -ENODEV;  		goto out_unlock;  	} @@ -299,12 +298,36 @@ out:  static int hidraw_release(struct inode * inode, struct file * file)  {  	unsigned int minor = iminor(inode); +	struct hidraw *dev;  	struct hidraw_list *list = file->private_data; +	int ret; +	int i; + +	mutex_lock(&minors_lock); +	if (!hidraw_table[minor]) { +		ret = -ENODEV; +		goto unlock; +	} -	drop_ref(hidraw_table[minor], 0);  	list_del(&list->node); +	dev = hidraw_table[minor]; +	if (!--dev->open) { +		if (list->hidraw->exist) { +			hid_hw_power(dev->hid, PM_HINT_NORMAL); +			hid_hw_close(dev->hid); +		} else { +			kfree(list->hidraw); +		} +	} + +	for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i) +		kfree(list->buffer[i].value);  	kfree(list); -	return 0; +	ret = 0; +unlock: +	mutex_unlock(&minors_lock); + +	return ret;  }  static long hidraw_ioctl(struct file *file, unsigned int cmd, @@ -506,7 +529,21 @@ EXPORT_SYMBOL_GPL(hidraw_connect);  void hidraw_disconnect(struct hid_device *hid)  {  	struct hidraw *hidraw = hid->hidraw; -	drop_ref(hidraw, 1); + +	mutex_lock(&minors_lock); +	hidraw->exist = 0; + +	device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); + +	hidraw_table[hidraw->minor] = NULL; + +	if (hidraw->open) { +		hid_hw_close(hid); +		wake_up_interruptible(&hidraw->wait); +	} else { +		kfree(hidraw); +	} +	mutex_unlock(&minors_lock);  }  EXPORT_SYMBOL_GPL(hidraw_disconnect); @@ -555,23 +592,3 @@ void hidraw_exit(void)  	unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);  } - -static void drop_ref(struct hidraw *hidraw, int exists_bit) -{ -	mutex_lock(&minors_lock); -	if (exists_bit) { -		hid_hw_close(hidraw->hid); -		hidraw->exist = 0; -		if (hidraw->open) -			wake_up_interruptible(&hidraw->wait); -	} else { -		--hidraw->open; -	} - -	if (!hidraw->open && !hidraw->exist) { -		device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); -		hidraw_table[hidraw->minor] = NULL; -		kfree(hidraw); -	} -	mutex_unlock(&minors_lock); -} diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 406537420ff..f4c3d28cd1f 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -146,14 +146,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,  	if (ret != 0) {  		err = ret; -		goto errorout; +		goto error0;  	}  	ret = hv_ringbuffer_init(  		&newchannel->inbound, in, recv_ringbuffer_size);  	if (ret != 0) {  		err = ret; -		goto errorout; +		goto error0;  	} @@ -168,7 +168,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,  	if (ret != 0) {  		err = ret; -		goto errorout; +		goto error0;  	}  	/* Create and init the channel open message */ @@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,  			   GFP_KERNEL);  	if (!open_info) {  		err = -ENOMEM; -		goto errorout; +		goto error0;  	}  	init_completion(&open_info->waitevent); @@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,  	if (userdatalen > MAX_USER_DEFINED_BYTES) {  		err = -EINVAL; -		goto errorout; +		goto error0;  	}  	if (userdatalen) @@ -208,19 +208,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,  			       sizeof(struct vmbus_channel_open_channel));  	if (ret != 0) -		goto cleanup; +		goto error1;  	t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);  	if (t == 0) {  		err = -ETIMEDOUT; -		goto errorout; +		goto error1;  	}  	if (open_info->response.open_result.status)  		err = open_info->response.open_result.status; -cleanup:  	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);  	list_del(&open_info->msglistentry);  	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); @@ -228,9 +227,12 @@ cleanup:  	kfree(open_info);  	return err; -errorout: -	hv_ringbuffer_cleanup(&newchannel->outbound); -	hv_ringbuffer_cleanup(&newchannel->inbound); +error1: +	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); +	list_del(&open_info->msglistentry); +	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); + +error0:  	free_pages((unsigned long)out,  		get_order(send_ringbuffer_size + recv_ringbuffer_size));  	kfree(open_info); diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index a227be47149..520e5bf4f76 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -32,7 +32,7 @@   * ASB100-A supports pwm1, while plain ASB100 does not.  There is no known   * way for the driver to tell which one is there.   * - * Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA + * Chip		#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA   * asb100	7	3	1	4	0x31	0x0694	yes	no   */ diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 68ad7d25551..4f411040738 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -2,7 +2,7 @@   * fam15h_power.c - AMD Family 15h processor power monitoring   *   * Copyright (c) 2011 Advanced Micro Devices, Inc. - * Author: Andreas Herrmann <andreas.herrmann3@amd.com> + * Author: Andreas Herrmann <herrmann.der.user@googlemail.com>   *   *   * This driver is free software; you can redistribute it and/or @@ -28,7 +28,7 @@  #include <asm/processor.h>  MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor"); -MODULE_AUTHOR("Andreas Herrmann <andreas.herrmann3@amd.com>"); +MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");  MODULE_LICENSE("GPL");  /* D18F3 */ diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 36509ae3208..1381a2e3bbd 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = {  	.driver	= {  		.name	= "gpio-fan",  		.pm	= GPIO_FAN_PM, +#ifdef CONFIG_OF_GPIO  		.of_match_table = of_match_ptr(of_gpio_fan_match), +#endif  	},  }; diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 1821b7423d5..de3c7e04c3b 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -2083,6 +2083,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)  	mutex_init(&data->lock);  	mutex_init(&data->update_lock);  	data->name = w83627ehf_device_names[sio_data->kind]; +	data->bank = 0xff;		/* Force initial bank selection */  	platform_set_drvdata(pdev, data);  	/* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 5b1a6a66644..af158990870 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -25,7 +25,7 @@  /*   * Supports following chips:   * - * Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA + * Chip		#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA   * w83627hf	9	3	2	3	0x20	0x5ca3	no	yes(LPC)   * w83627thf	7	3	3	3	0x90	0x5ca3	no	yes(LPC)   * w83637hf	7	3	3	3	0x80	0x5ca3	no	yes(LPC) diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 5a5046d94c3..20f11d31da4 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -24,7 +24,7 @@  /*   * Supports following chips:   * - * Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA + * Chip		#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA   * as99127f	7	3	0	3	0x31	0x12c3	yes	no   * as99127f rev.2 (type_name = as99127f)	0x31	0x5ca3	yes	no   * w83781d	7	3	0	3	0x10-1	0x5ca3	yes	yes diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 39ab7bcc616..ed397c64519 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -22,7 +22,7 @@  /*   * Supports following chips:   * - * Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA + * Chip		#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA   * w83791d	10	5	5	3	0x71	0x5ca3	yes	no   *   * The w83791d chip appears to be part way between the 83781d and the diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 053645279f3..301942d0845 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -31,7 +31,7 @@  /*   * Supports following chips:   * - * Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA + * Chip		#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA   * w83792d	9	7	7	3	0x7a	0x5ca3	yes	no   */ diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c index f0e8286c3c7..79710bcac2f 100644 --- a/drivers/hwmon/w83l786ng.c +++ b/drivers/hwmon/w83l786ng.c @@ -20,7 +20,7 @@  /*   * Supports following chips:   * - * Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA + * Chip		#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA   * w83l786ng	3	2	2	2	0x7b	0x5ca3	yes	no   */ diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index beee6b2d361..1722f50f247 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS)		+= i2c-smbus.o  obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o  obj-$(CONFIG_I2C_MUX)		+= i2c-mux.o  obj-y				+= algos/ busses/ muxes/ +obj-$(CONFIG_I2C_STUB)		+= i2c-stub.o  ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG  CFLAGS_i2c-core.o := -Wno-deprecated-declarations diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 65dd599a026..e9df4612b7e 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -81,7 +81,6 @@ config I2C_I801  	tristate "Intel 82801 (ICH/PCH)"  	depends on PCI  	select CHECK_SIGNATURE if X86 && DMI -	select GPIOLIB if I2C_MUX  	help  	  If you say yes to this option, support will be included for the Intel  	  801 family of mainboard I2C interfaces.  Specifically, the following diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 2d33d62952c..395b516ffa0 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN)		+= i2c-acorn.o  obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o  obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o  obj-$(CONFIG_I2C_SIBYTE)	+= i2c-sibyte.o -obj-$(CONFIG_I2C_STUB)		+= i2c-stub.o  obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o  obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 37793156bd9..6abc00d5988 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -82,7 +82,8 @@  #include <linux/wait.h>  #include <linux/err.h> -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ +		defined CONFIG_DMI  #include <linux/gpio.h>  #include <linux/i2c-mux-gpio.h>  #include <linux/platform_device.h> @@ -192,7 +193,8 @@ struct i801_priv {  	int len;  	u8 *data; -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ +		defined CONFIG_DMI  	const struct i801_mux_config *mux_drvdata;  	struct platform_device *mux_pdev;  #endif @@ -921,7 +923,8 @@ static void __init input_apanel_init(void) {}  static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}  #endif	/* CONFIG_X86 && CONFIG_DMI */ -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ +		defined CONFIG_DMI  static struct i801_mux_config i801_mux_config_asus_z8_d12 = {  	.gpio_chip = "gpio_ich",  	.values = { 0x02, 0x03 }, @@ -1059,7 +1062,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)  	id = dmi_first_match(mux_dmi_table);  	if (id) { -		/* Remove from branch classes from trunk */ +		/* Remove branch classes from trunk */  		mux_config = id->driver_data;  		for (i = 0; i < mux_config->n_values; i++)  			class &= ~mux_config->classes[i]; diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 1f58197062c..286ca191782 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -1,7 +1,7 @@  /*   * Freescale MXS I2C bus driver   * - * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. + * Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K.   *   * based on a (non-working) driver which was:   * @@ -35,10 +35,6 @@  #define DRIVER_NAME "mxs-i2c" -static bool use_pioqueue; -module_param(use_pioqueue, bool, 0); -MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA"); -  #define MXS_I2C_CTRL0		(0x00)  #define MXS_I2C_CTRL0_SET	(0x04) @@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");  				 MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \  				 MXS_I2C_CTRL1_SLAVE_IRQ) -#define MXS_I2C_QUEUECTRL	(0x60) -#define MXS_I2C_QUEUECTRL_SET	(0x64) -#define MXS_I2C_QUEUECTRL_CLR	(0x68) - -#define MXS_I2C_QUEUECTRL_QUEUE_RUN		0x20 -#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE	0x04 - -#define MXS_I2C_QUEUESTAT	(0x70) -#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY        0x00002000 -#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK	0x0000001F - -#define MXS_I2C_QUEUECMD	(0x80) - -#define MXS_I2C_QUEUEDATA	(0x90) - -#define MXS_I2C_DATA		(0xa0) -  #define MXS_CMD_I2C_SELECT	(MXS_I2C_CTRL0_RETAIN_CLOCK |	\  				 MXS_I2C_CTRL0_PRE_SEND_START |	\ @@ -153,7 +132,6 @@ struct mxs_i2c_dev {  	const struct mxs_i2c_speed_config *speed;  	/* DMA support components */ -	bool				dma_mode;  	int				dma_channel;  	struct dma_chan         	*dmach;  	struct mxs_dma_data		dma_data; @@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)  	writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);  	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); -	if (i2c->dma_mode) -		writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, -			i2c->regs + MXS_I2C_QUEUECTRL_CLR); -	else -		writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, -			i2c->regs + MXS_I2C_QUEUECTRL_SET); -} - -static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len, -					int flags) -{ -	u32 data; - -	writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD); - -	data = (addr << 1) | I2C_SMBUS_READ; -	writel(data, i2c->regs + MXS_I2C_DATA); - -	data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags; -	writel(data, i2c->regs + MXS_I2C_QUEUECMD); -} - -static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c, -				    u8 addr, u8 *buf, int len, int flags) -{ -	u32 data; -	int i, shifts_left; - -	data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags; -	writel(data, i2c->regs + MXS_I2C_QUEUECMD); - -	/* -	 * We have to copy the slave address (u8) and buffer (arbitrary number -	 * of u8) into the data register (u32). To achieve that, the u8 are put -	 * into the MSBs of 'data' which is then shifted for the next u8. When -	 * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32 -	 * looks like this: -	 * -	 *  3          2          1          0 -	 * 10987654|32109876|54321098|76543210 -	 * --------+--------+--------+-------- -	 * buffer+2|buffer+1|buffer+0|slave_addr -	 */ - -	data = ((addr << 1) | I2C_SMBUS_WRITE) << 24; - -	for (i = 0; i < len; i++) { -		data >>= 8; -		data |= buf[i] << 24; -		if ((i & 3) == 2) -			writel(data, i2c->regs + MXS_I2C_DATA); -	} - -	/* Write out the remaining bytes if any */ -	shifts_left = 24 - (i & 3) * 8; -	if (shifts_left) -		writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA); -} - -/* - * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the - * rd_threshold to 1). Couldn't get this to work, though. - */ -static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c) -{ -	unsigned long timeout = jiffies + msecs_to_jiffies(1000); - -	while (readl(i2c->regs + MXS_I2C_QUEUESTAT) -			& MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) { -			if (time_after(jiffies, timeout)) -				return -ETIMEDOUT; -			cond_resched(); -	} - -	return 0; -} - -static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len) -{ -	u32 uninitialized_var(data); -	int i; - -	for (i = 0; i < len; i++) { -		if ((i & 3) == 0) { -			if (mxs_i2c_wait_for_data(i2c)) -				return -ETIMEDOUT; -			data = readl(i2c->regs + MXS_I2C_QUEUEDATA); -		} -		buf[i] = data & 0xff; -		data >>= 8; -	} - -	return 0;  }  static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c) @@ -432,39 +317,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,  	init_completion(&i2c->cmd_complete);  	i2c->cmd_err = 0; -	if (i2c->dma_mode) { -		ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); -		if (ret) -			return ret; -	} else { -		if (msg->flags & I2C_M_RD) { -			mxs_i2c_pioq_setup_read(i2c, msg->addr, -						msg->len, flags); -		} else { -			mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, -						msg->len, flags); -		} - -		writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, -			i2c->regs + MXS_I2C_QUEUECTRL_SET); -	} +	ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); +	if (ret) +		return ret;  	ret = wait_for_completion_timeout(&i2c->cmd_complete,  						msecs_to_jiffies(1000));  	if (ret == 0)  		goto timeout; -	if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) { -		ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len); -		if (ret) -			goto timeout; -	} -  	if (i2c->cmd_err == -ENXIO)  		mxs_i2c_reset(i2c); -	else -		writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, -				i2c->regs + MXS_I2C_QUEUECTRL_CLR);  	dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err); @@ -472,8 +335,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,  timeout:  	dev_dbg(i2c->dev, "Timeout!\n"); -	if (i2c->dma_mode) -		mxs_i2c_dma_finish(i2c); +	mxs_i2c_dma_finish(i2c);  	mxs_i2c_reset(i2c);  	return -ETIMEDOUT;  } @@ -502,7 +364,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)  {  	struct mxs_i2c_dev *i2c = dev_id;  	u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK; -	bool is_last_cmd;  	if (!stat)  		return IRQ_NONE; @@ -515,14 +376,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)  		/* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */  		i2c->cmd_err = -EIO; -	if (!i2c->dma_mode) { -		is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) & -			MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0; - -		if (is_last_cmd || i2c->cmd_err) -			complete(&i2c->cmd_complete); -	} -  	writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);  	return IRQ_HANDLED; @@ -556,23 +409,14 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)  	int ret;  	/* -	 * The MXS I2C DMA mode is prefered and enabled by default. -	 * The PIO mode is still supported, but should be used only -	 * for debuging purposes etc. -	 */ -	i2c->dma_mode = !use_pioqueue; -	if (!i2c->dma_mode) -		dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n"); - -	/*  	 * TODO: This is a temporary solution and should be changed  	 * to use generic DMA binding later when the helpers get in.  	 */  	ret = of_property_read_u32(node, "fsl,i2c-dma-channel",  				   &i2c->dma_channel);  	if (ret) { -		dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n"); -		i2c->dma_mode = 0; +		dev_err(dev, "Failed to get DMA channel!\n"); +		return -ENODEV;  	}  	ret = of_property_read_u32(node, "clock-frequency", &speed); @@ -634,15 +478,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)  	}  	/* Setup the DMA */ -	if (i2c->dma_mode) { -		dma_cap_zero(mask); -		dma_cap_set(DMA_SLAVE, mask); -		i2c->dma_data.chan_irq = dmairq; -		i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c); -		if (!i2c->dmach) { -			dev_err(dev, "Failed to request dma\n"); -			return -ENODEV; -		} +	dma_cap_zero(mask); +	dma_cap_set(DMA_SLAVE, mask); +	i2c->dma_data.chan_irq = dmairq; +	i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c); +	if (!i2c->dmach) { +		dev_err(dev, "Failed to request dma\n"); +		return -ENODEV;  	}  	platform_set_drvdata(pdev, i2c); diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 698d7acb0f0..02c3115a2df 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,  	pm_runtime_get_sync(&dev->adev->dev); -	clk_enable(dev->clk); +	status = clk_prepare_enable(dev->clk); +	if (status) { +		dev_err(&dev->adev->dev, "can't prepare_enable clock\n"); +		goto out_clk; +	}  	status = init_hw(dev);  	if (status) @@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,  	}  out: -	clk_disable(dev->clk); +	clk_disable_unprepare(dev->clk); +out_clk:  	pm_runtime_put_sync(&dev->adev->dev);  	dev->busy = false; diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index f981ac4e678..dcea77bf6f5 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)  	}  	ret = devm_request_irq(&pdev->dev, i2c_dev->irq, -			tegra_i2c_isr, 0, pdev->name, i2c_dev); +			tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);  	if (ret) {  		dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);  		return ret; diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/i2c-stub.c index b1b3447942c..d0a9c590c3c 100644 --- a/drivers/i2c/busses/i2c-stub.c +++ b/drivers/i2c/i2c-stub.c @@ -2,7 +2,7 @@      i2c-stub.c - I2C/SMBus chip emulator      Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com> -    Copyright (C) 2007 Jean Delvare <khali@linux-fr.org> +    Copyright (C) 2007, 2012 Jean Delvare <khali@linux-fr.org>      This program is free software; you can redistribute it and/or modify      it under the terms of the GNU General Public License as published by @@ -51,8 +51,8 @@ struct stub_chip {  static struct stub_chip *stub_chips;  /* Return negative errno on error. */ -static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, -	char read_write, u8 command, int size, union i2c_smbus_data * data) +static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, +	char read_write, u8 command, int size, union i2c_smbus_data *data)  {  	s32 ret;  	int i, len; @@ -78,14 +78,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,  	case I2C_SMBUS_BYTE:  		if (read_write == I2C_SMBUS_WRITE) {  			chip->pointer = command; -			dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " -					"wrote 0x%02x.\n", -					addr, command); +			dev_dbg(&adap->dev, +				"smbus byte - addr 0x%02x, wrote 0x%02x.\n", +				addr, command);  		} else {  			data->byte = chip->words[chip->pointer++] & 0xff; -			dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " -					"read  0x%02x.\n", -					addr, data->byte); +			dev_dbg(&adap->dev, +				"smbus byte - addr 0x%02x, read  0x%02x.\n", +				addr, data->byte);  		}  		ret = 0; @@ -95,14 +95,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,  		if (read_write == I2C_SMBUS_WRITE) {  			chip->words[command] &= 0xff00;  			chip->words[command] |= data->byte; -			dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " -					"wrote 0x%02x at 0x%02x.\n", -					addr, data->byte, command); +			dev_dbg(&adap->dev, +				"smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n", +				addr, data->byte, command);  		} else {  			data->byte = chip->words[command] & 0xff; -			dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " -					"read  0x%02x at 0x%02x.\n", -					addr, data->byte, command); +			dev_dbg(&adap->dev, +				"smbus byte data - addr 0x%02x, read  0x%02x at 0x%02x.\n", +				addr, data->byte, command);  		}  		chip->pointer = command + 1; @@ -112,14 +112,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,  	case I2C_SMBUS_WORD_DATA:  		if (read_write == I2C_SMBUS_WRITE) {  			chip->words[command] = data->word; -			dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " -					"wrote 0x%04x at 0x%02x.\n", -					addr, data->word, command); +			dev_dbg(&adap->dev, +				"smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n", +				addr, data->word, command);  		} else {  			data->word = chip->words[command]; -			dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " -					"read  0x%04x at 0x%02x.\n", -					addr, data->word, command); +			dev_dbg(&adap->dev, +				"smbus word data - addr 0x%02x, read  0x%04x at 0x%02x.\n", +				addr, data->word, command);  		}  		ret = 0; @@ -132,17 +132,17 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,  				chip->words[command + i] &= 0xff00;  				chip->words[command + i] |= data->block[1 + i];  			} -			dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " -					"wrote %d bytes at 0x%02x.\n", -					addr, len, command); +			dev_dbg(&adap->dev, +				"i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n", +				addr, len, command);  		} else {  			for (i = 0; i < len; i++) {  				data->block[1 + i] =  					chip->words[command + i] & 0xff;  			} -			dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " -					"read  %d bytes at 0x%02x.\n", -					addr, len, command); +			dev_dbg(&adap->dev, +				"i2c block data - addr 0x%02x, read  %d bytes at 0x%02x.\n", +				addr, len, command);  		}  		ret = 0; @@ -179,25 +179,24 @@ static int __init i2c_stub_init(void)  	int i, ret;  	if (!chip_addr[0]) { -		printk(KERN_ERR "i2c-stub: Please specify a chip address\n"); +		pr_err("i2c-stub: Please specify a chip address\n");  		return -ENODEV;  	}  	for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {  		if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) { -			printk(KERN_ERR "i2c-stub: Invalid chip address " -			       "0x%02x\n", chip_addr[i]); +			pr_err("i2c-stub: Invalid chip address 0x%02x\n", +			       chip_addr[i]);  			return -EINVAL;  		} -		printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", -		       chip_addr[i]); +		pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]);  	}  	/* Allocate memory for all chips at once */  	stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);  	if (!stub_chips) { -		printk(KERN_ERR "i2c-stub: Out of memory\n"); +		pr_err("i2c-stub: Out of memory\n");  		return -ENOMEM;  	} @@ -219,4 +218,3 @@ MODULE_LICENSE("GPL");  module_init(i2c_stub_init);  module_exit(i2c_stub_exit); - diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 6e3f143fc71..fc937aca71f 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -62,7 +62,6 @@ source "drivers/iio/frequency/Kconfig"  source "drivers/iio/dac/Kconfig"  source "drivers/iio/common/Kconfig"  source "drivers/iio/gyro/Kconfig" -source "drivers/iio/light/Kconfig"  source "drivers/iio/magnetometer/Kconfig"  endif # IIO diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index f7fa3c0867b..761f2b65ac5 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -18,5 +18,4 @@ obj-y += frequency/  obj-y += dac/  obj-y += common/  obj-y += gyro/ -obj-y += light/  obj-y += magnetometer/ diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index 57e07c61ace..afd81790ab3 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -468,7 +468,7 @@ struct ib_mr *c4iw_register_phys_mem(struct ib_pd *pd,  	ret = alloc_pbl(mhp, npages);  	if (ret) {  		kfree(page_list); -		goto err_pbl; +		goto err;  	}  	ret = write_pbl(&mhp->rhp->rdev, page_list, mhp->attr.pbl_addr, diff --git a/drivers/infiniband/hw/mlx4/alias_GUID.c b/drivers/infiniband/hw/mlx4/alias_GUID.c index d2fb38d4357..2f215b93db6 100644 --- a/drivers/infiniband/hw/mlx4/alias_GUID.c +++ b/drivers/infiniband/hw/mlx4/alias_GUID.c @@ -107,7 +107,7 @@ static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index  {  	if (index >= NUM_ALIAS_GUID_PER_PORT) {  		pr_err("%s: ERROR: asked for index:%d\n", __func__, index); -		return  (__force __be64) ((u64) 0xFFFFFFFFFFFFFFFFUL); +		return (__force __be64) -1;  	}  	return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index];  } diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 21a794152d1..0a903c129f0 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -409,38 +409,45 @@ int mlx4_ib_find_real_gid(struct ib_device *ibdev, u8 port, __be64 guid)  } -static int get_pkey_phys_indices(struct mlx4_ib_dev *ibdev, u8 port, u8 ph_pkey_ix, -				 u8 *full_pk_ix, u8 *partial_pk_ix, -				 int *is_full_member) +static int find_slave_port_pkey_ix(struct mlx4_ib_dev *dev, int slave, +				   u8 port, u16 pkey, u16 *ix)  { -	u16 search_pkey; -	int fm; -	int err = 0; -	u16 pk; +	int i, ret; +	u8 unassigned_pkey_ix, pkey_ix, partial_ix = 0xFF; +	u16 slot_pkey; -	err = ib_get_cached_pkey(&ibdev->ib_dev, port, ph_pkey_ix, &search_pkey); -	if (err) -		return err; +	if (slave == mlx4_master_func_num(dev->dev)) +		return ib_find_cached_pkey(&dev->ib_dev, port, pkey, ix); -	fm = (search_pkey & 0x8000) ? 1 : 0; -	if (fm) { -		*full_pk_ix = ph_pkey_ix; -		search_pkey &= 0x7FFF; -	} else { -		*partial_pk_ix = ph_pkey_ix; -		search_pkey |= 0x8000; -	} +	unassigned_pkey_ix = dev->dev->phys_caps.pkey_phys_table_len[port] - 1; -	if (ib_find_exact_cached_pkey(&ibdev->ib_dev, port, search_pkey, &pk)) -		pk = 0xFFFF; +	for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) { +		if (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == unassigned_pkey_ix) +			continue; -	if (fm) -		*partial_pk_ix = (pk & 0xFF); -	else -		*full_pk_ix = (pk & 0xFF); +		pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][i]; -	*is_full_member = fm; -	return err; +		ret = ib_get_cached_pkey(&dev->ib_dev, port, pkey_ix, &slot_pkey); +		if (ret) +			continue; +		if ((slot_pkey & 0x7FFF) == (pkey & 0x7FFF)) { +			if (slot_pkey & 0x8000) { +				*ix = (u16) pkey_ix; +				return 0; +			} else { +				/* take first partial pkey index found */ +				if (partial_ix == 0xFF) +					partial_ix = pkey_ix; +			} +		} +	} + +	if (partial_ix < 0xFF) { +		*ix = (u16) partial_ix; +		return 0; +	} + +	return -EINVAL;  }  int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port, @@ -458,10 +465,8 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,  	unsigned tun_tx_ix = 0;  	int dqpn;  	int ret = 0; -	int i; -	int is_full_member = 0;  	u16 tun_pkey_ix; -	u8 ph_pkey_ix, full_pk_ix = 0, partial_pk_ix = 0; +	u16 cached_pkey;  	if (dest_qpt > IB_QPT_GSI)  		return -EINVAL; @@ -481,27 +486,17 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,  	else  		tun_qp = &tun_ctx->qp[1]; -	/* compute pkey index for slave */ -	/* get physical pkey -- virtualized Dom0 pkey to phys*/ +	/* compute P_Key index to put in tunnel header for slave */  	if (dest_qpt) { -		ph_pkey_ix = -			dev->pkeys.virt2phys_pkey[mlx4_master_func_num(dev->dev)][port - 1][wc->pkey_index]; - -		/* now, translate this to the slave pkey index */ -		ret = get_pkey_phys_indices(dev, port, ph_pkey_ix, &full_pk_ix, -					    &partial_pk_ix, &is_full_member); +		u16 pkey_ix; +		ret = ib_get_cached_pkey(&dev->ib_dev, port, wc->pkey_index, &cached_pkey);  		if (ret)  			return -EINVAL; -		for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) { -			if ((dev->pkeys.virt2phys_pkey[slave][port - 1][i] == full_pk_ix) || -			    (is_full_member && -			     (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == partial_pk_ix))) -				break; -		} -		if (i == dev->dev->caps.pkey_table_len[port]) +		ret = find_slave_port_pkey_ix(dev, slave, port, cached_pkey, &pkey_ix); +		if (ret)  			return -EINVAL; -		tun_pkey_ix = i; +		tun_pkey_ix = pkey_ix;  	} else  		tun_pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][0]; diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c index 3c3b54c3fdd..25b2cdff00f 100644 --- a/drivers/infiniband/hw/mlx4/mcg.c +++ b/drivers/infiniband/hw/mlx4/mcg.c @@ -233,7 +233,8 @@ static int send_mad_to_slave(int slave, struct mlx4_ib_demux_ctx *ctx,  	ib_query_ah(dev->sm_ah[ctx->port - 1], &ah_attr); -	wc.pkey_index = 0; +	if (ib_find_cached_pkey(&dev->ib_dev, ctx->port, IB_DEFAULT_PKEY_FULL, &wc.pkey_index)) +		return -EINVAL;  	wc.sl = 0;  	wc.dlid_path_bits = 0;  	wc.port_num = ctx->port; @@ -1074,10 +1075,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy  	unsigned long end;  	int count; -	if (ctx->flushing) -		return; - -	ctx->flushing = 1;  	for (i = 0; i < MAX_VFS; ++i)  		clean_vf_mcast(ctx, i); @@ -1107,9 +1104,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy  		force_clean_group(group);  	}  	mutex_unlock(&ctx->mcg_table_lock); - -	if (!destroy_wq) -		ctx->flushing = 0;  }  struct clean_work { @@ -1123,6 +1117,7 @@ static void mcg_clean_task(struct work_struct *work)  	struct clean_work *cw = container_of(work, struct clean_work, work);  	_mlx4_ib_mcg_port_cleanup(cw->ctx, cw->destroy_wq); +	cw->ctx->flushing = 0;  	kfree(cw);  } @@ -1130,13 +1125,20 @@ void mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy_wq)  {  	struct clean_work *work; +	if (ctx->flushing) +		return; + +	ctx->flushing = 1; +  	if (destroy_wq) {  		_mlx4_ib_mcg_port_cleanup(ctx, destroy_wq); +		ctx->flushing = 0;  		return;  	}  	work = kmalloc(sizeof *work, GFP_KERNEL);  	if (!work) { +		ctx->flushing = 0;  		mcg_warn("failed allocating work for cleanup\n");  		return;  	} diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index b4b65af8612..de0874054e9 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -335,6 +335,7 @@ config KEYBOARD_LOCOMO  config KEYBOARD_LPC32XX  	tristate "LPC32XX matrix key scanner support"  	depends on ARCH_LPC32XX && OF +	select INPUT_MATRIXKMAP  	help  	  Say Y here if you want to use NXP LPC32XX SoC key scanner interface,  	  connected to a key matrix. diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 803ff6fe021..cad9d5dd597 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -368,6 +368,9 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)  	unsigned int mask = 0, direct_key_num = 0;  	unsigned long kpc = 0; +	/* clear pending interrupt bit */ +	keypad_readl(KPC); +  	/* enable matrix keys with automatic scan */  	if (pdata->matrix_key_rows && pdata->matrix_key_cols) {  		kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL; diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 02ca8680ea5..6f7d9901303 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -311,7 +311,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,  	case XenbusStateReconfiguring:  	case XenbusStateReconfigured:  	case XenbusStateUnknown: -	case XenbusStateClosed:  		break;  	case XenbusStateInitWait: @@ -350,6 +349,10 @@ InitWait:  		break; +	case XenbusStateClosed: +		if (dev->state == XenbusStateClosed) +			break; +		/* Missed the backend's CLOSING state -- fallthrough */  	case XenbusStateClosing:  		xenbus_frontend_closed(dev);  		break; diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 3a78f235fa3..2baff1b79a5 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -84,6 +84,10 @@  #define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI	0x0262  #define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO	0x0263  #define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS	0x0264 +/* MacbookPro10,2 (unibody, October 2012) */ +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI	0x0259 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO	0x025a +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS	0x025b  #define BCM5974_DEVICE(prod) {					\  	.match_flags = (USB_DEVICE_ID_MATCH_DEVICE |		\ @@ -137,6 +141,10 @@ static const struct usb_device_id bcm5974_table[] = {  	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),  	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),  	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), +	/* MacbookPro10,2 */ +	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), +	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), +	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),  	/* Terminating entry */  	{}  }; @@ -379,6 +387,19 @@ static const struct bcm5974_config bcm5974_config_table[] = {  		{ SN_COORD, -150, 6730 },  		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }  	}, +	{ +		USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI, +		USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO, +		USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS, +		HAS_INTEGRATED_BUTTON, +		0x84, sizeof(struct bt_data), +		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, +		{ SN_PRESSURE, 0, 300 }, +		{ SN_WIDTH, 0, 2048 }, +		{ SN_COORD, -4750, 5280 }, +		{ SN_COORD, -150, 6730 }, +		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } +	},  	{}  }; diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 9edf9806cff..858ad446de9 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf,  							features->pktlen = WACOM_PKGLEN_TPC2FG;  						} -						if (features->type == MTSCREEN) +						if (features->type == MTSCREEN || features->type == WACOM_24HDT)  							features->pktlen = WACOM_PKGLEN_MTOUCH;  						if (features->type == BAMBOO_PT) { @@ -402,6 +402,14 @@ static int wacom_parse_hid(struct usb_interface *intf,  							features->x_max =  								get_unaligned_le16(&report[i + 8]);  							i += 15; +						} else if (features->type == WACOM_24HDT) { +							features->x_max = +								get_unaligned_le16(&report[i + 3]); +							features->x_phy = +								get_unaligned_le16(&report[i + 8]); +							features->unit = report[i - 1]; +							features->unitExpo = report[i - 3]; +							i += 12;  						} else {  							features->x_max =  								get_unaligned_le16(&report[i + 3]); @@ -434,6 +442,12 @@ static int wacom_parse_hid(struct usb_interface *intf,  							features->y_phy =  								get_unaligned_le16(&report[i + 6]);  							i += 7; +						} else if (type == WACOM_24HDT) { +							features->y_max = +								get_unaligned_le16(&report[i + 3]); +							features->y_phy = +								get_unaligned_le16(&report[i - 2]); +							i += 7;  						} else if (type == BAMBOO_PT) {  							features->y_phy =  								get_unaligned_le16(&report[i + 3]); @@ -541,6 +555,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat  			/* MT Tablet PC touch */  			return wacom_set_device_mode(intf, 3, 4, 4);  		} +		else if (features->type == WACOM_24HDT) { +			return wacom_set_device_mode(intf, 18, 3, 2); +		}  	} else if (features->device_type == BTN_TOOL_PEN) {  		if (features->type <= BAMBOO_PT && features->type != WIRELESS) {  			return wacom_set_device_mode(intf, 2, 2, 2); @@ -613,6 +630,30 @@ struct wacom_usbdev_data {  static LIST_HEAD(wacom_udev_list);  static DEFINE_MUTEX(wacom_udev_list_lock); +static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product) +{ +	int port1; +	struct usb_device *sibling; + +	if (vendor == 0 && product == 0) +		return dev; + +	if (dev->parent == NULL) +		return NULL; + +	usb_hub_for_each_child(dev->parent, port1, sibling) { +		struct usb_device_descriptor *d; +		if (sibling == NULL) +			continue; + +		d = &sibling->descriptor; +		if (d->idVendor == vendor && d->idProduct == product) +			return sibling; +	} + +	return NULL; +} +  static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)  {  	struct wacom_usbdev_data *data; @@ -1257,13 +1298,19 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i  	strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));  	if (features->quirks & WACOM_QUIRK_MULTI_INPUT) { +		struct usb_device *other_dev; +  		/* Append the device type to the name */  		strlcat(wacom_wac->name,  			features->device_type == BTN_TOOL_PEN ?  				" Pen" : " Finger",  			sizeof(wacom_wac->name)); -		error = wacom_add_shared_data(wacom_wac, dev); + +		other_dev = wacom_get_sibling(dev, features->oVid, features->oPid); +		if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL) +			other_dev = dev; +		error = wacom_add_shared_data(wacom_wac, other_dev);  		if (error)  			goto fail3;  	} diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index c3468c8dbd8..0a67031ffc1 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -806,6 +806,70 @@ static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid)  	return -1;  } +static int int_dist(int x1, int y1, int x2, int y2) +{ +	int x = x2 - x1; +	int y = y2 - y1; + +	return int_sqrt(x*x + y*y); +} + +static int wacom_24hdt_irq(struct wacom_wac *wacom) +{ +	struct input_dev *input = wacom->input; +	char *data = wacom->data; +	int i; +	int current_num_contacts = data[61]; +	int contacts_to_send = 0; + +	/* +	 * First packet resets the counter since only the first +	 * packet in series will have non-zero current_num_contacts. +	 */ +	if (current_num_contacts) +		wacom->num_contacts_left = current_num_contacts; + +	/* There are at most 4 contacts per packet */ +	contacts_to_send = min(4, wacom->num_contacts_left); + +	for (i = 0; i < contacts_to_send; i++) { +		int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1; +		bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity; +		int id = data[offset + 1]; +		int slot = find_slot_from_contactid(wacom, id); + +		if (slot < 0) +			continue; +		input_mt_slot(input, slot); +		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); + +		if (touch) { +			int t_x = le16_to_cpup((__le16 *)&data[offset + 2]); +			int c_x = le16_to_cpup((__le16 *)&data[offset + 4]); +			int t_y = le16_to_cpup((__le16 *)&data[offset + 6]); +			int c_y = le16_to_cpup((__le16 *)&data[offset + 8]); +			int w = le16_to_cpup((__le16 *)&data[offset + 10]); +			int h = le16_to_cpup((__le16 *)&data[offset + 12]); + +			input_report_abs(input, ABS_MT_POSITION_X, t_x); +			input_report_abs(input, ABS_MT_POSITION_Y, t_y); +			input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h)); +			input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y)); +			input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h)); +			input_report_abs(input, ABS_MT_ORIENTATION, w > h); +		} +		wacom->slots[slot] = touch ? id : -1; +	} + +	input_mt_report_pointer_emulation(input, true); + +	wacom->num_contacts_left -= contacts_to_send; +	if (wacom->num_contacts_left <= 0) +		wacom->num_contacts_left = 0; + +	return 1; +} +  static int wacom_mt_touch(struct wacom_wac *wacom)  {  	struct input_dev *input = wacom->input; @@ -1255,6 +1319,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)  		sync = wacom_intuos_irq(wacom_wac);  		break; +	case WACOM_24HDT: +		sync = wacom_24hdt_irq(wacom_wac); +		break; +  	case INTUOS5S:  	case INTUOS5:  	case INTUOS5L: @@ -1340,7 +1408,8 @@ void wacom_setup_device_quirks(struct wacom_features *features)  	/* these device have multiple inputs */  	if (features->type >= WIRELESS || -	    (features->type >= INTUOS5S && features->type <= INTUOS5L)) +	    (features->type >= INTUOS5S && features->type <= INTUOS5L) || +	    (features->oVid && features->oPid))  		features->quirks |= WACOM_QUIRK_MULTI_INPUT;  	/* quirk for bamboo touch with 2 low res touches */ @@ -1449,6 +1518,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,  		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);  		input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); + +		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit); +  		wacom_setup_cintiq(wacom_wac);  		break; @@ -1575,6 +1647,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,  		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);  		break; +	case WACOM_24HDT: +		if (features->device_type == BTN_TOOL_FINGER) { +			input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); +			input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0); +			input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0); +			input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); +		} +		/* fall through */ +  	case MTSCREEN:  		if (features->device_type == BTN_TOOL_FINGER) {  			wacom_wac->slots = kmalloc(features->touch_max * @@ -1869,8 +1950,11 @@ static const struct wacom_features wacom_features_0xF4 =  	{ "Wacom Cintiq 24HD",       WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,  	  63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };  static const struct wacom_features wacom_features_0xF8 = -	{ "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104480, 65600, 2047, -	  63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; +	{ "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104480, 65600, 2047, /* Pen */ +	  63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; +static const struct wacom_features wacom_features_0xF6 = +	{ "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ +	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 };  static const struct wacom_features wacom_features_0x3F =  	{ "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023,  	  63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; @@ -2113,6 +2197,7 @@ const struct usb_device_id wacom_ids[] = {  	{ USB_DEVICE_WACOM(0x47) },  	{ USB_DEVICE_WACOM(0xF4) },  	{ USB_DEVICE_WACOM(0xF8) }, +	{ USB_DEVICE_WACOM(0xF6) },  	{ USB_DEVICE_WACOM(0xFA) },  	{ USB_DEVICE_LENOVO(0x6004) },  	{ } diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 96c185cc301..345f1e76975 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -29,6 +29,7 @@  /* wacom data size per MT contact */  #define WACOM_BYTES_PER_MT_PACKET	11 +#define WACOM_BYTES_PER_24HDT_PACKET	14  /* device IDs */  #define STYLUS_DEVICE_ID	0x02 @@ -49,6 +50,7 @@  #define WACOM_REPORT_TPCHID		15  #define WACOM_REPORT_TPCST		16  #define WACOM_REPORT_TPC1FGE		18 +#define WACOM_REPORT_24HDT		1  /* device quirks */  #define WACOM_QUIRK_MULTI_INPUT		0x0001 @@ -81,6 +83,7 @@ enum {  	WACOM_MO,  	WIRELESS,  	BAMBOO_PT, +	WACOM_24HDT,  	TABLETPC,   /* add new TPC below */  	TABLETPCE,  	TABLETPC2FG, @@ -109,6 +112,8 @@ struct wacom_features {  	int distance_fuzz;  	unsigned quirks;  	unsigned touch_max; +	int oVid; +	int oPid;  };  struct wacom_shared { diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 1ba232cbc09..f7668b24c37 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -239,7 +239,7 @@ config TOUCHSCREEN_EETI  config TOUCHSCREEN_EGALAX  	tristate "EETI eGalax multi-touch panel support" -	depends on I2C +	depends on I2C && OF  	help  	  Say Y here to enable support for I2C connected EETI  	  eGalax multi-touch panels. diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index c1e3460f119..13fa62fdfb0 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -28,6 +28,7 @@  #include <linux/slab.h>  #include <linux/bitops.h>  #include <linux/input/mt.h> +#include <linux/of_gpio.h>  /*   * Mouse Mode: some panel may configure the controller to mouse mode, @@ -122,9 +123,17 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)  /* wake up controller by an falling edge of interrupt gpio.  */  static int egalax_wake_up_device(struct i2c_client *client)  { -	int gpio = irq_to_gpio(client->irq); +	struct device_node *np = client->dev.of_node; +	int gpio;  	int ret; +	if (!np) +		return -ENODEV; + +	gpio = of_get_named_gpio(np, "wakeup-gpios", 0); +	if (!gpio_is_valid(gpio)) +		return -ENODEV; +  	ret = gpio_request(gpio, "egalax_irq");  	if (ret < 0) {  		dev_err(&client->dev, @@ -181,7 +190,11 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,  	ts->input_dev = input_dev;  	/* controller may be in sleep, wake it up. */ -	egalax_wake_up_device(client); +	error = egalax_wake_up_device(client); +	if (error) { +		dev_err(&client->dev, "Failed to wake up the controller\n"); +		goto err_free_dev; +	}  	ret = egalax_firmware_version(client);  	if (ret < 0) { @@ -274,11 +287,17 @@ static int egalax_ts_resume(struct device *dev)  static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume); +static struct of_device_id egalax_ts_dt_ids[] = { +	{ .compatible = "eeti,egalax_ts" }, +	{ /* sentinel */ } +}; +  static struct i2c_driver egalax_ts_driver = {  	.driver = {  		.name	= "egalax_ts",  		.owner	= THIS_MODULE,  		.pm	= &egalax_ts_pm_ops, +		.of_match_table	= of_match_ptr(egalax_ts_dt_ids),  	},  	.id_table	= egalax_ts_id,  	.probe		= egalax_ts_probe, diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index 63209aaa55f..eb96f168fb9 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c @@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)  	__set_bit(BTN_TOUCH, input_dev->keybit);  	input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);  	input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0); -	input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0);  	serio_set_drvdata(serio, ptsc); diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 18b0d99bd4d..81837b0710a 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1599,21 +1599,46 @@ static void __init free_on_init_error(void)  #endif  } +/* SB IOAPIC is always on this device in AMD systems */ +#define IOAPIC_SB_DEVID		((0x00 << 8) | PCI_DEVFN(0x14, 0)) +  static bool __init check_ioapic_information(void)  { +	bool ret, has_sb_ioapic;  	int idx; +	has_sb_ioapic = false; +	ret           = false; +  	for (idx = 0; idx < nr_ioapics; idx++) { -		int id = mpc_ioapic_id(idx); +		int devid, id = mpc_ioapic_id(idx); -		if (get_ioapic_devid(id) < 0) { -			pr_err(FW_BUG "AMD-Vi: IO-APIC[%d] not in IVRS table\n", id); -			pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug\n"); -			return false; +		devid = get_ioapic_devid(id); +		if (devid < 0) { +			pr_err(FW_BUG "AMD-Vi: IOAPIC[%d] not in IVRS table\n", id); +			ret = false; +		} else if (devid == IOAPIC_SB_DEVID) { +			has_sb_ioapic = true; +			ret           = true;  		}  	} -	return true; +	if (!has_sb_ioapic) { +		/* +		 * We expect the SB IOAPIC to be listed in the IVRS +		 * table. The system timer is connected to the SB IOAPIC +		 * and if we don't have it in the list the system will +		 * panic at boot time.  This situation usually happens +		 * when the BIOS is buggy and provides us the wrong +		 * device id for the IOAPIC in the system. +		 */ +		pr_err(FW_BUG "AMD-Vi: No southbridge IOAPIC found in IVRS table\n"); +	} + +	if (!ret) +		pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug(s)\n"); + +	return ret;  }  static void __init free_dma_resources(void) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 0b4d62e0c64..a649f146d17 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -200,7 +200,7 @@ enum {  #define SMMU_ADDR_TO_PFN(addr)	((addr) >> 12)  #define SMMU_ADDR_TO_PDN(addr)	((addr) >> 22) -#define SMMU_PDN_TO_ADDR(addr)	((pdn) << 22) +#define SMMU_PDN_TO_ADDR(pdn)	((pdn) << 22)  #define _READABLE	(1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT)  #define _WRITABLE	(1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT) diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig index a233ed53913..86cd75a0e84 100644 --- a/drivers/isdn/Kconfig +++ b/drivers/isdn/Kconfig @@ -4,7 +4,7 @@  menuconfig ISDN  	bool "ISDN support" -	depends on NET +	depends on NET && NETDEVICES  	depends on !S390 && !UML  	---help---  	  ISDN ("Integrated Services Digital Network", called RNIS in France) diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 52758870894..c44950d3eb7 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -617,7 +617,13 @@ static void int_in_work(struct work_struct *work)  	if (rc == 0)  		/* success, resubmit interrupt read URB */  		rc = usb_submit_urb(urb, GFP_ATOMIC); -	if (rc != 0 && rc != -ENODEV) { + +	switch (rc) { +	case 0:		/* success */ +	case -ENODEV:	/* device gone */ +	case -EINVAL:	/* URB already resubmitted, or terminal badness */ +		break; +	default:	/* failure: try to recover by resetting the device */  		dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc));  		rc = usb_lock_device_for_reset(ucs->udev, ucs->interface);  		if (rc == 0) { @@ -2442,7 +2448,9 @@ static void gigaset_disconnect(struct usb_interface *interface)  }  /* gigaset_suspend - * This function is called before the USB connection is suspended. + * This function is called before the USB connection is suspended + * or before the USB device is reset. + * In the latter case, message == PMSG_ON.   */  static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)  { @@ -2498,7 +2506,12 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)  	del_timer_sync(&ucs->timer_atrdy);  	del_timer_sync(&ucs->timer_cmd_in);  	del_timer_sync(&ucs->timer_int_in); -	cancel_work_sync(&ucs->int_in_wq); + +	/* don't try to cancel int_in_wq from within reset as it +	 * might be the one requesting the reset +	 */ +	if (message.event != PM_EVENT_ON) +		cancel_work_sync(&ucs->int_in_wq);  	gig_dbg(DEBUG_SUSPEND, "suspend complete");  	return 0; diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index 2302fbe70ac..9c6650ea848 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig @@ -6,7 +6,7 @@ if ISDN_I4L  config ISDN_PPP  	bool "Support synchronous PPP" -	depends on INET && NETDEVICES +	depends on INET  	select SLHC  	help  	  Over digital connections such as ISDN, there is no need to diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 8c610fa6782..e2a945ee9f0 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1312,7 +1312,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)  			} else  				return -EINVAL;  			break; -#ifdef CONFIG_NETDEVICES  		case IIOCNETGPN:  			/* Get peer phone number of a connected  			 * isdn network interface */ @@ -1322,7 +1321,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)  				return isdn_net_getpeer(&phone, argp);  			} else  				return -EINVAL; -#endif  		default:  			return -EINVAL;  		} @@ -1352,7 +1350,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)  		case IIOCNETLCR:  			printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");  			return -ENODEV; -#ifdef CONFIG_NETDEVICES  		case IIOCNETAIF:  			/* Add a network-interface */  			if (arg) { @@ -1491,7 +1488,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)  				return -EFAULT;  			return isdn_net_force_hangup(name);  			break; -#endif                          /* CONFIG_NETDEVICES */  		case IIOCSETVER:  			dev->net_verbose = arg;  			printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose); diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index 45135f69509..5e7dc772f5d 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -315,8 +315,11 @@ static int run(struct mddev *mddev)  	}  	conf->nfaults = 0; -	rdev_for_each(rdev, mddev) +	rdev_for_each(rdev, mddev) {  		conf->rdev = rdev; +		disk_stack_limits(mddev->gendisk, rdev->bdev, +				  rdev->data_offset << 9); +	}  	md_set_array_sectors(mddev, faulty_size(mddev, 0, 0));  	mddev->private = conf; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 8034fbd6190..636bae0405e 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2710,7 +2710,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)  		    || disk_idx < 0)  			continue;  		if (test_bit(Replacement, &rdev->flags)) -			disk = conf->mirrors + conf->raid_disks + disk_idx; +			disk = conf->mirrors + mddev->raid_disks + disk_idx;  		else  			disk = conf->mirrors + disk_idx; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 906ccbd0f7d..d1295aff417 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1783,7 +1783,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)  		clear_bit(Unmerged, &rdev->flags);  	}  	md_integrity_add_rdev(rdev, mddev); -	if (blk_queue_discard(bdev_get_queue(rdev->bdev))) +	if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))  		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);  	print_conf(conf); @@ -3613,11 +3613,14 @@ static int run(struct mddev *mddev)  			discard_supported = true;  	} -	if (discard_supported) -		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); -	else -		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); - +	if (mddev->queue) { +		if (discard_supported) +			queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, +						mddev->queue); +		else +			queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, +						  mddev->queue); +	}  	/* need to check that every block has at least one working mirror */  	if (!enough(conf, -1)) {  		printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n", diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 660bbc52886..4d50da61816 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -208,7 +208,7 @@ static unsigned long exynos5250_dwmmc_caps[4] = {  	MMC_CAP_CMD23,  }; -static struct dw_mci_drv_data exynos5250_drv_data = { +static const struct dw_mci_drv_data exynos5250_drv_data = {  	.caps			= exynos5250_dwmmc_caps,  	.init			= dw_mci_exynos_priv_init,  	.setup_clock		= dw_mci_exynos_setup_clock, @@ -220,14 +220,14 @@ static struct dw_mci_drv_data exynos5250_drv_data = {  static const struct of_device_id dw_mci_exynos_match[] = {  	{ .compatible = "samsung,exynos5250-dw-mshc", -			.data = (void *)&exynos5250_drv_data, }, +			.data = &exynos5250_drv_data, },  	{},  }; -MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); +MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);  int dw_mci_exynos_probe(struct platform_device *pdev)  { -	struct dw_mci_drv_data *drv_data; +	const struct dw_mci_drv_data *drv_data;  	const struct of_device_id *match;  	match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node); diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index c960ca7ffbe..917936bee5d 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -24,7 +24,7 @@  #include "dw_mmc.h"  int dw_mci_pltfm_register(struct platform_device *pdev, -				struct dw_mci_drv_data *drv_data) +				const struct dw_mci_drv_data *drv_data)  {  	struct dw_mci *host;  	struct resource	*regs; @@ -50,8 +50,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev,  	if (!host->regs)  		return -ENOMEM; -	if (host->drv_data->init) { -		ret = host->drv_data->init(host); +	if (drv_data && drv_data->init) { +		ret = drv_data->init(host);  		if (ret)  			return ret;  	} diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h index 301f24541fc..2ac37b81de4 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.h +++ b/drivers/mmc/host/dw_mmc-pltfm.h @@ -13,7 +13,7 @@  #define _DW_MMC_PLTFM_H_  extern int dw_mci_pltfm_register(struct platform_device *pdev, -				struct dw_mci_drv_data *drv_data); +				const struct dw_mci_drv_data *drv_data);  extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev);  extern const struct dev_pm_ops dw_mci_pltfm_pmops; diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index c2828f35c3b..c0667c8af2b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -232,6 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)  {  	struct mmc_data	*data;  	struct dw_mci_slot *slot = mmc_priv(mmc); +	struct dw_mci_drv_data *drv_data = slot->host->drv_data;  	u32 cmdr;  	cmd->error = -EINPROGRESS; @@ -261,8 +262,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)  			cmdr |= SDMMC_CMD_DAT_WR;  	} -	if (slot->host->drv_data->prepare_command) -		slot->host->drv_data->prepare_command(slot->host, &cmdr); +	if (drv_data && drv_data->prepare_command) +		drv_data->prepare_command(slot->host, &cmdr);  	return cmdr;  } @@ -434,7 +435,7 @@ static int dw_mci_idmac_init(struct dw_mci *host)  	return 0;  } -static struct dw_mci_dma_ops dw_mci_idmac_ops = { +static const struct dw_mci_dma_ops dw_mci_idmac_ops = {  	.init = dw_mci_idmac_init,  	.start = dw_mci_idmac_start_dma,  	.stop = dw_mci_idmac_stop_dma, @@ -772,6 +773,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)  static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  {  	struct dw_mci_slot *slot = mmc_priv(mmc); +	struct dw_mci_drv_data *drv_data = slot->host->drv_data;  	u32 regs;  	/* set default 1 bit mode */ @@ -807,8 +809,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  		slot->clock = ios->clock;  	} -	if (slot->host->drv_data->set_ios) -		slot->host->drv_data->set_ios(slot->host, ios); +	if (drv_data && drv_data->set_ios) +		drv_data->set_ios(slot->host, ios);  	switch (ios->power_mode) {  	case MMC_POWER_UP: @@ -1815,6 +1817,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)  {  	struct mmc_host *mmc;  	struct dw_mci_slot *slot; +	struct dw_mci_drv_data *drv_data = host->drv_data;  	int ctrl_id, ret;  	u8 bus_width; @@ -1854,8 +1857,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)  	} else {  		ctrl_id = to_platform_device(host->dev)->id;  	} -	if (host->drv_data && host->drv_data->caps) -		mmc->caps |= host->drv_data->caps[ctrl_id]; +	if (drv_data && drv_data->caps) +		mmc->caps |= drv_data->caps[ctrl_id];  	if (host->pdata->caps2)  		mmc->caps2 = host->pdata->caps2; @@ -1867,10 +1870,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)  	else  		bus_width = 1; -	if (host->drv_data->setup_bus) { +	if (drv_data && drv_data->setup_bus) {  		struct device_node *slot_np;  		slot_np = dw_mci_of_find_slot_node(host->dev, slot->id); -		ret = host->drv_data->setup_bus(host, slot_np, bus_width); +		ret = drv_data->setup_bus(host, slot_np, bus_width);  		if (ret)  			goto err_setup_bus;  	} @@ -1968,7 +1971,7 @@ static void dw_mci_init_dma(struct dw_mci *host)  	/* Determine which DMA interface to use */  #ifdef CONFIG_MMC_DW_IDMAC  	host->dma_ops = &dw_mci_idmac_ops; -	dev_info(&host->dev, "Using internal DMA controller.\n"); +	dev_info(host->dev, "Using internal DMA controller.\n");  #endif  	if (!host->dma_ops) @@ -2035,6 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)  	struct dw_mci_board *pdata;  	struct device *dev = host->dev;  	struct device_node *np = dev->of_node; +	struct dw_mci_drv_data *drv_data = host->drv_data;  	int idx, ret;  	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); @@ -2062,8 +2066,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)  	of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); -	if (host->drv_data->parse_dt) { -		ret = host->drv_data->parse_dt(host); +	if (drv_data && drv_data->parse_dt) { +		ret = drv_data->parse_dt(host);  		if (ret)  			return ERR_PTR(ret);  	} @@ -2080,6 +2084,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)  int dw_mci_probe(struct dw_mci *host)  { +	struct dw_mci_drv_data *drv_data = host->drv_data;  	int width, i, ret = 0;  	u32 fifo_size;  	int init_slots = 0; @@ -2127,8 +2132,8 @@ int dw_mci_probe(struct dw_mci *host)  	else  		host->bus_hz = clk_get_rate(host->ciu_clk); -	if (host->drv_data->setup_clock) { -		ret = host->drv_data->setup_clock(host); +	if (drv_data && drv_data->setup_clock) { +		ret = drv_data->setup_clock(host);  		if (ret) {  			dev_err(host->dev,  				"implementation specific clock setup failed\n"); @@ -2228,6 +2233,21 @@ int dw_mci_probe(struct dw_mci *host)  	else  		host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; +	/* +	 * Enable interrupts for command done, data over, data empty, card det, +	 * receive ready and error such as transmit, receive timeout, crc error +	 */ +	mci_writel(host, RINTSTS, 0xFFFFFFFF); +	mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | +		   SDMMC_INT_TXDR | SDMMC_INT_RXDR | +		   DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); +	mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ + +	dev_info(host->dev, "DW MMC controller at irq %d, " +		 "%d bit host data width, " +		 "%u deep fifo\n", +		 host->irq, width, fifo_size); +  	/* We need at least one slot to succeed */  	for (i = 0; i < host->num_slots; i++) {  		ret = dw_mci_init_slot(host, i); @@ -2257,20 +2277,6 @@ int dw_mci_probe(struct dw_mci *host)  	else  		host->data_offset = DATA_240A_OFFSET; -	/* -	 * Enable interrupts for command done, data over, data empty, card det, -	 * receive ready and error such as transmit, receive timeout, crc error -	 */ -	mci_writel(host, RINTSTS, 0xFFFFFFFF); -	mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | -		   SDMMC_INT_TXDR | SDMMC_INT_RXDR | -		   DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); -	mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ - -	dev_info(host->dev, "DW MMC controller at irq %d, " -		 "%d bit host data width, " -		 "%u deep fifo\n", -		 host->irq, width, fifo_size);  	if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)  		dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 565c2e4fac7..6290b7f1ccf 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -1134,4 +1134,4 @@ module_platform_driver(mxcmci_driver);  MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");  MODULE_AUTHOR("Sascha Hauer, Pengutronix");  MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-mmc"); +MODULE_ALIAS("platform:mxc-mmc"); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 54bfd0cc106..fedd258cc4e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -178,7 +178,8 @@ struct omap_hsmmc_host {  static int omap_hsmmc_card_detect(struct device *dev, int slot)  { -	struct omap_mmc_platform_data *mmc = dev->platform_data; +	struct omap_hsmmc_host *host = dev_get_drvdata(dev); +	struct omap_mmc_platform_data *mmc = host->pdata;  	/* NOTE: assumes card detect signal is active-low */  	return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); @@ -186,7 +187,8 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot)  static int omap_hsmmc_get_wp(struct device *dev, int slot)  { -	struct omap_mmc_platform_data *mmc = dev->platform_data; +	struct omap_hsmmc_host *host = dev_get_drvdata(dev); +	struct omap_mmc_platform_data *mmc = host->pdata;  	/* NOTE: assumes write protect signal is active-high */  	return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); @@ -194,7 +196,8 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot)  static int omap_hsmmc_get_cover_state(struct device *dev, int slot)  { -	struct omap_mmc_platform_data *mmc = dev->platform_data; +	struct omap_hsmmc_host *host = dev_get_drvdata(dev); +	struct omap_mmc_platform_data *mmc = host->pdata;  	/* NOTE: assumes card detect signal is active-low */  	return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); @@ -204,7 +207,8 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot)  static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)  { -	struct omap_mmc_platform_data *mmc = dev->platform_data; +	struct omap_hsmmc_host *host = dev_get_drvdata(dev); +	struct omap_mmc_platform_data *mmc = host->pdata;  	disable_irq(mmc->slots[0].card_detect_irq);  	return 0; @@ -212,7 +216,8 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)  static int omap_hsmmc_resume_cdirq(struct device *dev, int slot)  { -	struct omap_mmc_platform_data *mmc = dev->platform_data; +	struct omap_hsmmc_host *host = dev_get_drvdata(dev); +	struct omap_mmc_platform_data *mmc = host->pdata;  	enable_irq(mmc->slots[0].card_detect_irq);  	return 0; @@ -2009,9 +2014,9 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)  		clk_put(host->dbclk);  	} -	mmc_free_host(host->mmc); +	omap_hsmmc_gpio_free(host->pdata);  	iounmap(host->base); -	omap_hsmmc_gpio_free(pdev->dev.platform_data); +	mmc_free_host(host->mmc);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (res) diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 90140eb03e3..8fd50a21103 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -19,6 +19,7 @@   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */ +#include <linux/err.h>  #include <linux/io.h>  #include <linux/clk.h>  #include <linux/err.h> @@ -84,30 +85,32 @@ static int __devinit sdhci_dove_probe(struct platform_device *pdev)  	struct sdhci_dove_priv *priv;  	int ret; -	ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata); -	if (ret) -		goto sdhci_dove_register_fail; -  	priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv),  			    GFP_KERNEL);  	if (!priv) {  		dev_err(&pdev->dev, "unable to allocate private data"); -		ret = -ENOMEM; -		goto sdhci_dove_allocate_fail; +		return -ENOMEM;  	} +	priv->clk = clk_get(&pdev->dev, NULL); +	if (!IS_ERR(priv->clk)) +		clk_prepare_enable(priv->clk); + +	ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata); +	if (ret) +		goto sdhci_dove_register_fail; +  	host = platform_get_drvdata(pdev);  	pltfm_host = sdhci_priv(host);  	pltfm_host->priv = priv; -	priv->clk = clk_get(&pdev->dev, NULL); -	if (!IS_ERR(priv->clk)) -		clk_prepare_enable(priv->clk);  	return 0; -sdhci_dove_allocate_fail: -	sdhci_pltfm_unregister(pdev);  sdhci_dove_register_fail: +	if (!IS_ERR(priv->clk)) { +		clk_disable_unprepare(priv->clk); +		clk_put(priv->clk); +	}  	return ret;  } @@ -117,14 +120,13 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev)  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct sdhci_dove_priv *priv = pltfm_host->priv; -	if (priv->clk) { -		if (!IS_ERR(priv->clk)) { -			clk_disable_unprepare(priv->clk); -			clk_put(priv->clk); -		} -		devm_kfree(&pdev->dev, priv->clk); +	sdhci_pltfm_unregister(pdev); + +	if (!IS_ERR(priv->clk)) { +		clk_disable_unprepare(priv->clk); +		clk_put(priv->clk);  	} -	return sdhci_pltfm_unregister(pdev); +	return 0;  }  static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = { diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index ae5fcbfa1ee..63d219f57ca 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -169,6 +169,16 @@ static void esdhc_of_resume(struct sdhci_host *host)  }  #endif +static void esdhc_of_platform_init(struct sdhci_host *host) +{ +	u32 vvn; + +	vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); +	vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; +	if (vvn == VENDOR_V_22) +		host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; +} +  static struct sdhci_ops sdhci_esdhc_ops = {  	.read_l = esdhc_readl,  	.read_w = esdhc_readw, @@ -180,6 +190,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {  	.enable_dma = esdhc_of_enable_dma,  	.get_max_clock = esdhc_of_get_max_clock,  	.get_min_clock = esdhc_of_get_min_clock, +	.platform_init = esdhc_of_platform_init,  #ifdef CONFIG_PM  	.platform_suspend = esdhc_of_suspend,  	.platform_resume = esdhc_of_resume, diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 4bb74b042a0..04936f353ce 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -1196,7 +1196,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(  		return ERR_PTR(-ENODEV);  	} -	if (pci_resource_len(pdev, bar) != 0x100) { +	if (pci_resource_len(pdev, bar) < 0x100) {  		dev_err(&pdev->dev, "Invalid iomem size. You may "  			"experience problems.\n");  	} diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 65551a9709c..27164457f86 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -150,6 +150,13 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,  		goto err_remap;  	} +	/* +	 * Some platforms need to probe the controller to be able to +	 * determine which caps should be used. +	 */ +	if (host->ops && host->ops->platform_init) +		host->ops->platform_init(host); +  	platform_set_drvdata(pdev, host);  	return host; diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 2903949594c..a54dd5d7a5f 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -211,8 +211,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)  	if (ourhost->cur_clk != best_src) {  		struct clk *clk = ourhost->clk_bus[best_src]; -		clk_enable(clk); -		clk_disable(ourhost->clk_bus[ourhost->cur_clk]); +		clk_prepare_enable(clk); +		clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);  		/* turn clock off to card before changing clock source */  		writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); @@ -607,7 +607,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)  	}  	/* enable the local io clock and keep it running for the moment. */ -	clk_enable(sc->clk_io); +	clk_prepare_enable(sc->clk_io);  	for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {  		struct clk *clk; @@ -638,7 +638,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)  	}  #ifndef CONFIG_PM_RUNTIME -	clk_enable(sc->clk_bus[sc->cur_clk]); +	clk_prepare_enable(sc->clk_bus[sc->cur_clk]);  #endif  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -747,13 +747,14 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)  		sdhci_s3c_setup_card_detect_gpio(sc);  #ifdef CONFIG_PM_RUNTIME -	clk_disable(sc->clk_io); +	if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) +		clk_disable_unprepare(sc->clk_io);  #endif  	return 0;   err_req_regs:  #ifndef CONFIG_PM_RUNTIME -	clk_disable(sc->clk_bus[sc->cur_clk]); +	clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);  #endif  	for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {  		if (sc->clk_bus[ptr]) { @@ -762,7 +763,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)  	}   err_no_busclks: -	clk_disable(sc->clk_io); +	clk_disable_unprepare(sc->clk_io);  	clk_put(sc->clk_io);   err_io_clk: @@ -794,7 +795,8 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)  		gpio_free(sc->ext_cd_gpio);  #ifdef CONFIG_PM_RUNTIME -	clk_enable(sc->clk_io); +	if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) +		clk_prepare_enable(sc->clk_io);  #endif  	sdhci_remove_host(host, 1); @@ -802,14 +804,14 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)  	pm_runtime_disable(&pdev->dev);  #ifndef CONFIG_PM_RUNTIME -	clk_disable(sc->clk_bus[sc->cur_clk]); +	clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);  #endif  	for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {  		if (sc->clk_bus[ptr]) {  			clk_put(sc->clk_bus[ptr]);  		}  	} -	clk_disable(sc->clk_io); +	clk_disable_unprepare(sc->clk_io);  	clk_put(sc->clk_io);  	if (pdev->dev.of_node) { @@ -849,8 +851,8 @@ static int sdhci_s3c_runtime_suspend(struct device *dev)  	ret = sdhci_runtime_suspend_host(host); -	clk_disable(ourhost->clk_bus[ourhost->cur_clk]); -	clk_disable(busclk); +	clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]); +	clk_disable_unprepare(busclk);  	return ret;  } @@ -861,8 +863,8 @@ static int sdhci_s3c_runtime_resume(struct device *dev)  	struct clk *busclk = ourhost->clk_io;  	int ret; -	clk_enable(busclk); -	clk_enable(ourhost->clk_bus[ourhost->cur_clk]); +	clk_prepare_enable(busclk); +	clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);  	ret = sdhci_runtime_resume_host(host);  	return ret;  } diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 7922adb4238..c7851c0aabc 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1315,16 +1315,19 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)  		 */  		if ((host->flags & SDHCI_NEEDS_RETUNING) &&  		    !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { -			/* eMMC uses cmd21 while sd and sdio use cmd19 */ -			tuning_opcode = mmc->card->type == MMC_TYPE_MMC ? -				MMC_SEND_TUNING_BLOCK_HS200 : -				MMC_SEND_TUNING_BLOCK; -			spin_unlock_irqrestore(&host->lock, flags); -			sdhci_execute_tuning(mmc, tuning_opcode); -			spin_lock_irqsave(&host->lock, flags); +			if (mmc->card) { +				/* eMMC uses cmd21 but sd and sdio use cmd19 */ +				tuning_opcode = +					mmc->card->type == MMC_TYPE_MMC ? +					MMC_SEND_TUNING_BLOCK_HS200 : +					MMC_SEND_TUNING_BLOCK; +				spin_unlock_irqrestore(&host->lock, flags); +				sdhci_execute_tuning(mmc, tuning_opcode); +				spin_lock_irqsave(&host->lock, flags); -			/* Restore original mmc_request structure */ -			host->mrq = mrq; +				/* Restore original mmc_request structure */ +				host->mrq = mrq; +			}  		}  		if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) @@ -2837,6 +2840,9 @@ int sdhci_add_host(struct sdhci_host *host)  	if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))  		mmc->caps |= MMC_CAP_4_BIT_DATA; +	if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) +		mmc->caps &= ~MMC_CAP_CMD23; +  	if (caps[0] & SDHCI_CAN_DO_HISPD)  		mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; @@ -2846,9 +2852,12 @@ int sdhci_add_host(struct sdhci_host *host)  	/* If vqmmc regulator and no 1.8V signalling, then there's no UHS */  	host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc"); -	if (IS_ERR(host->vqmmc)) { -		pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc)); -		host->vqmmc = NULL; +	if (IS_ERR_OR_NULL(host->vqmmc)) { +		if (PTR_ERR(host->vqmmc) < 0) { +			pr_info("%s: no vqmmc regulator found\n", +				mmc_hostname(mmc)); +			host->vqmmc = NULL; +		}  	}  	else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000))  		regulator_enable(host->vqmmc); @@ -2904,9 +2913,12 @@ int sdhci_add_host(struct sdhci_host *host)  	ocr_avail = 0;  	host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); -	if (IS_ERR(host->vmmc)) { -		pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); -		host->vmmc = NULL; +	if (IS_ERR_OR_NULL(host->vmmc)) { +		if (PTR_ERR(host->vmmc) < 0) { +			pr_info("%s: no vmmc regulator found\n", +				mmc_hostname(mmc)); +			host->vmmc = NULL; +		}  	} else  		regulator_enable(host->vmmc); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 97653ea8942..71a4a7ed46c 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -278,6 +278,7 @@ struct sdhci_ops {  	void	(*hw_reset)(struct sdhci_host *host);  	void	(*platform_suspend)(struct sdhci_host *host);  	void	(*platform_resume)(struct sdhci_host *host); +	void	(*platform_init)(struct sdhci_host *host);  };  #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 11d2bc3b51d..d25bc97dc5c 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1466,9 +1466,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)  	platform_set_drvdata(pdev, NULL); +	clk_disable(host->hclk);  	mmc_free_host(host->mmc);  	pm_runtime_put_sync(&pdev->dev); -	clk_disable(host->hclk);  	pm_runtime_disable(&pdev->dev);  	return 0; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index dc15d248443..ef8d2a080d1 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1060,7 +1060,7 @@ static ssize_t bonding_store_primary(struct device *d,  		goto out;  	} -	sscanf(buf, "%16s", ifname); /* IFNAMSIZ */ +	sscanf(buf, "%15s", ifname); /* IFNAMSIZ */  	/* check to see if we are clearing primary */  	if (!strlen(ifname) || buf[0] == '\n') { @@ -1237,7 +1237,7 @@ static ssize_t bonding_store_active_slave(struct device *d,  		goto out;  	} -	sscanf(buf, "%16s", ifname); /* IFNAMSIZ */ +	sscanf(buf, "%15s", ifname); /* IFNAMSIZ */  	/* check to see if we are clearing active */  	if (!strlen(ifname) || buf[0] == '\n') { diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index c78ecfca1e4..a412bf6d73e 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -144,9 +144,22 @@  #define FLEXCAN_MB_CODE_MASK		(0xf0ffffff) -/* FLEXCAN hardware feature flags */ +/* + * FLEXCAN hardware feature flags + * + * Below is some version info we got: + *    SOC   Version   IP-Version  Glitch-  [TR]WRN_INT + *                                Filter?   connected? + *   MX25  FlexCAN2  03.00.00.00     no         no + *   MX28  FlexCAN2  03.00.04.00    yes        yes + *   MX35  FlexCAN2  03.00.00.00     no         no + *   MX53  FlexCAN2  03.00.00.00    yes         no + *   MX6s  FlexCAN3  10.00.12.00    yes        yes + * + * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. + */  #define FLEXCAN_HAS_V10_FEATURES	BIT(1) /* For core version >= 10 */ -#define FLEXCAN_HAS_BROKEN_ERR_STATE	BIT(2) /* Broken error state handling */ +#define FLEXCAN_HAS_BROKEN_ERR_STATE	BIT(2) /* [TR]WRN_INT not connected */  /* Structure of the message buffer */  struct flexcan_mb { @@ -205,7 +218,7 @@ static struct flexcan_devtype_data fsl_p1010_devtype_data = {  };  static struct flexcan_devtype_data fsl_imx28_devtype_data;  static struct flexcan_devtype_data fsl_imx6q_devtype_data = { -	.features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_BROKEN_ERR_STATE, +	.features = FLEXCAN_HAS_V10_FEATURES,  };  static const struct can_bittiming_const flexcan_bittiming_const = { diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index f5b82aeb254..6525dbcca4e 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -30,9 +30,10 @@  #include "sja1000.h" -MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>"); +MODULE_AUTHOR("Stephane Grosjean <s.grosjean@peak-system.com>");  MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI family cards");  MODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe/PCIeC miniPCI CAN cards"); +MODULE_SUPPORTED_DEVICE("PEAK PCAN miniPCIe/cPCI PC/104+ PCI/104e CAN Cards");  MODULE_LICENSE("GPL v2");  #define DRV_NAME  "peak_pci" @@ -64,7 +65,11 @@ struct peak_pci_chan {  #define PEAK_PCI_DEVICE_ID	0x0001	/* for PCI/PCIe slot cards */  #define PEAK_PCIEC_DEVICE_ID	0x0002	/* for ExpressCard slot cards */  #define PEAK_PCIE_DEVICE_ID	0x0003	/* for nextgen PCIe slot cards */ -#define PEAK_MPCI_DEVICE_ID	0x0008	/* The miniPCI slot cards */ +#define PEAK_CPCI_DEVICE_ID	0x0004	/* for nextgen cPCI slot cards */ +#define PEAK_MPCI_DEVICE_ID	0x0005	/* for nextgen miniPCI slot cards */ +#define PEAK_PC_104P_DEVICE_ID	0x0006	/* PCAN-PC/104+ cards */ +#define PEAK_PCI_104E_DEVICE_ID	0x0007	/* PCAN-PCI/104 Express cards */ +#define PEAK_MPCIE_DEVICE_ID	0x0008	/* The miniPCIe slot cards */  #define PEAK_PCI_CHAN_MAX	4 @@ -76,6 +81,10 @@ static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = {  	{PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},  	{PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},  	{PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, +	{PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, +	{PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, +	{PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, +	{PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},  #ifdef CONFIG_CAN_PEAK_PCIEC  	{PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},  #endif diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index c65295dded3..6e5bdd1a31d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1702,7 +1702,7 @@ static int bnx2x_set_eee(struct net_device *dev, struct ethtool_eee *edata)  				      SHMEM_EEE_ADV_STATUS_SHIFT);  	if ((advertised != (eee_cfg & SHMEM_EEE_ADV_STATUS_MASK))) {  		DP(BNX2X_MSG_ETHTOOL, -		   "Direct manipulation of EEE advertisment is not supported\n"); +		   "Direct manipulation of EEE advertisement is not supported\n");  		return -EINVAL;  	} diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index e2e45ee5df3..f6cfdc6cf20 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -137,7 +137,16 @@  #define LINK_20GTFD		LINK_STATUS_SPEED_AND_DUPLEX_20GTFD  #define LINK_20GXFD		LINK_STATUS_SPEED_AND_DUPLEX_20GXFD - +#define LINK_UPDATE_MASK \ +			(LINK_STATUS_SPEED_AND_DUPLEX_MASK | \ +			 LINK_STATUS_LINK_UP | \ +			 LINK_STATUS_PHYSICAL_LINK_FLAG | \ +			 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \ +			 LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \ +			 LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \ +			 LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \ +			 LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \ +			 LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)  #define SFP_EEPROM_CON_TYPE_ADDR		0x2  	#define SFP_EEPROM_CON_TYPE_VAL_LC	0x7 @@ -3295,6 +3304,21 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)  	       DEFAULT_PHY_DEV_ADDR);  } +static void bnx2x_xgxs_specific_func(struct bnx2x_phy *phy, +				     struct link_params *params, +				     u32 action) +{ +	struct bnx2x *bp = params->bp; +	switch (action) { +	case PHY_INIT: +		/* Set correct devad */ +		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0); +		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18, +		       phy->def_md_devad); +		break; +	} +} +  static void bnx2x_xgxs_deassert(struct link_params *params)  {  	struct bnx2x *bp = params->bp; @@ -3309,10 +3333,8 @@ static void bnx2x_xgxs_deassert(struct link_params *params)  	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);  	udelay(500);  	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val); - -	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0); -	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, -	       params->phy[INT_PHY].def_md_devad); +	bnx2x_xgxs_specific_func(¶ms->phy[INT_PHY], params, +				 PHY_INIT);  }  static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy, @@ -3545,14 +3567,11 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,  static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,  					struct link_params *params,  					struct link_vars *vars) { -	u16 val16 = 0, lane, i; +	u16 lane, i, cl72_ctrl, an_adv = 0; +	u16 ucode_ver;  	struct bnx2x *bp = params->bp;  	static struct bnx2x_reg_set reg_set[] = {  		{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, -		{MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0}, -		{MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0}, -		{MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff}, -		{MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555},  		{MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0},  		{MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},  		{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190}, @@ -3565,12 +3584,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,  		bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,  				 reg_set[i].val); +	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, +		MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl); +	cl72_ctrl &= 0xf8ff; +	cl72_ctrl |= 0x3800; +	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, +		MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl); +  	/* Check adding advertisement for 1G KX */  	if (((vars->line_speed == SPEED_AUTO_NEG) &&  	     (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||  	    (vars->line_speed == SPEED_1000)) {  		u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2; -		val16 |= (1<<5); +		an_adv |= (1<<5);  		/* Enable CL37 1G Parallel Detect */  		bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1); @@ -3580,11 +3606,14 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,  	     (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||  	    (vars->line_speed ==  SPEED_10000)) {  		/* Check adding advertisement for 10G KR */ -		val16 |= (1<<7); +		an_adv |= (1<<7);  		/* Enable 10G Parallel Detect */ +		CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, +				  MDIO_AER_BLOCK_AER_REG, 0); +  		bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,  				 MDIO_WC_REG_PAR_DET_10G_CTRL, 1); - +		bnx2x_set_aer_mmd(params, phy);  		DP(NETIF_MSG_LINK, "Advertize 10G\n");  	} @@ -3604,7 +3633,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,  	/* Advertised speeds */  	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, -			 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16); +			 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv);  	/* Advertised and set FEC (Forward Error Correction) */  	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, @@ -3628,9 +3657,10 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,  	/* Set KR Autoneg Work-Around flag for Warpcore version older than D108  	 */  	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, -			MDIO_WC_REG_UC_INFO_B1_VERSION, &val16); -	if (val16 < 0xd108) { -		DP(NETIF_MSG_LINK, "Enable AN KR work-around\n"); +			MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver); +	if (ucode_ver < 0xd108) { +		DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n", +			       ucode_ver);  		vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;  	}  	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, @@ -3651,21 +3681,16 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,  				      struct link_vars *vars)  {  	struct bnx2x *bp = params->bp; -	u16 i; +	u16 val16, i, lane;  	static struct bnx2x_reg_set reg_set[] = {  		/* Disable Autoneg */  		{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, -		{MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},  		{MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,  			0x3f00},  		{MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0},  		{MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0},  		{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},  		{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa}, -		/* Disable CL36 PCS Tx */ -		{MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0}, -		/* Double Wide Single Data Rate @ pll rate */ -		{MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF},  		/* Leave cl72 training enable, needed for KR */  		{MDIO_PMA_DEVAD,  		MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150, @@ -3676,11 +3701,24 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,  		bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,  				 reg_set[i].val); -	/* Leave CL72 enabled */ -	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, -				 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, -				 0x3800); +	lane = bnx2x_get_warpcore_lane(phy, params); +	/* Global registers */ +	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, +			  MDIO_AER_BLOCK_AER_REG, 0); +	/* Disable CL36 PCS Tx */ +	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, +			MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16); +	val16 &= ~(0x0011 << lane); +	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, +			 MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16); +	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, +			MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16); +	val16 |= (0x0303 << (lane << 1)); +	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, +			 MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16); +	/* Restore AER */ +	bnx2x_set_aer_mmd(params, phy);  	/* Set speed via PMA/PMD register */  	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,  			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040); @@ -4303,7 +4341,7 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,  				      struct link_params *params)  {  	struct bnx2x *bp = params->bp; -	u16 val16; +	u16 val16, lane;  	bnx2x_sfp_e3_set_transmitter(params, phy, 0);  	bnx2x_set_mdio_clk(bp, params->chip_id, params->port);  	bnx2x_set_aer_mmd(params, phy); @@ -4340,6 +4378,30 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,  			 MDIO_WC_REG_XGXSBLK1_LANECTRL2,  			 val16 & 0xff00); +	lane = bnx2x_get_warpcore_lane(phy, params); +	/* Disable CL36 PCS Tx */ +	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, +			MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16); +	val16 |= (0x11 << lane); +	if (phy->flags & FLAGS_WC_DUAL_MODE) +		val16 |= (0x22 << lane); +	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, +			 MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16); + +	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, +			MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16); +	val16 &= ~(0x0303 << (lane << 1)); +	val16 |= (0x0101 << (lane << 1)); +	if (phy->flags & FLAGS_WC_DUAL_MODE) { +		val16 &= ~(0x0c0c << (lane << 1)); +		val16 |= (0x0404 << (lane << 1)); +	} + +	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, +			 MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16); +	/* Restore AER */ +	bnx2x_set_aer_mmd(params, phy); +  }  static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy, @@ -6296,15 +6358,7 @@ static int bnx2x_update_link_down(struct link_params *params,  	vars->mac_type = MAC_TYPE_NONE;  	/* Update shared memory */ -	vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK | -			       LINK_STATUS_LINK_UP | -			       LINK_STATUS_PHYSICAL_LINK_FLAG | -			       LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | -			       LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | -			       LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | -			       LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | -			       LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | -			       LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE); +	vars->link_status &= ~LINK_UPDATE_MASK;  	vars->line_speed = 0;  	bnx2x_update_mng(params, vars->link_status); @@ -6452,6 +6506,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)  	u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;  	u8 active_external_phy = INT_PHY;  	vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; +	vars->link_status &= ~LINK_UPDATE_MASK;  	for (phy_index = INT_PHY; phy_index < params->num_phys;  	      phy_index++) {  		phy_vars[phy_index].flow_ctrl = 0; @@ -7579,7 +7634,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params,  static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,  						 struct link_params *params,  						 u16 addr, u8 byte_cnt, -						 u8 *o_buf) +						 u8 *o_buf, u8 is_init)  {  	int rc = 0;  	u8 i, j = 0, cnt = 0; @@ -7596,10 +7651,10 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,  	/* 4 byte aligned address */  	addr32 = addr & (~0x3);  	do { -		if (cnt == I2C_WA_PWR_ITER) { +		if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {  			bnx2x_warpcore_power_module(params, phy, 0);  			/* Note that 100us are not enough here */ -			usleep_range(1000,1000); +			usleep_range(1000, 2000);  			bnx2x_warpcore_power_module(params, phy, 1);  		}  		rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt, @@ -7719,7 +7774,7 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,  	break;  	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:  		rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr, -							   byte_cnt, o_buf); +							   byte_cnt, o_buf, 0);  	break;  	}  	return rc; @@ -7923,6 +7978,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,  {  	u8 val; +	int rc;  	struct bnx2x *bp = params->bp;  	u16 timeout;  	/* Initialization time after hot-plug may take up to 300ms for @@ -7930,8 +7986,14 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,  	 */  	for (timeout = 0; timeout < 60; timeout++) { -		if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val) -		    == 0) { +		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) +			rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, +								   params, 1, +								   1, &val, 1); +		else +			rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, +							  &val); +		if (rc == 0) {  			DP(NETIF_MSG_LINK,  			   "SFP+ module initialization took %d ms\n",  			   timeout * 5); @@ -7939,7 +8001,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,  		}  		usleep_range(5000, 10000);  	} -	return -EINVAL; +	rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val); +	return rc;  }  static void bnx2x_8727_power_module(struct bnx2x *bp, @@ -9878,7 +9941,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,  		else  			rc = bnx2x_8483x_disable_eee(phy, params, vars);  		if (rc) { -			DP(NETIF_MSG_LINK, "Failed to set EEE advertisment\n"); +			DP(NETIF_MSG_LINK, "Failed to set EEE advertisement\n");  			return rc;  		}  	} else { @@ -10993,7 +11056,7 @@ static struct bnx2x_phy phy_xgxs = {  	.format_fw_ver	= (format_fw_ver_t)NULL,  	.hw_reset	= (hw_reset_t)NULL,  	.set_link_led	= (set_link_led_t)NULL, -	.phy_specific_func = (phy_specific_func_t)NULL +	.phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func  };  static struct bnx2x_phy phy_warpcore = {  	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, @@ -11465,6 +11528,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,  			phy->media_type = ETH_PHY_BASE_T;  			break;  		case PORT_HW_CFG_NET_SERDES_IF_XFI: +			phy->supported &= (SUPPORTED_1000baseT_Full | +					   SUPPORTED_10000baseT_Full | +					   SUPPORTED_FIBRE | +					   SUPPORTED_Pause | +					   SUPPORTED_Asym_Pause);  			phy->media_type = ETH_PHY_XFP_FIBER;  			break;  		case PORT_HW_CFG_NET_SERDES_IF_SFI: @@ -12919,7 +12987,7 @@ static u8 bnx2x_analyze_link_error(struct link_params *params,  		DP(NETIF_MSG_LINK, "Analyze TX Fault\n");  		break;  	default: -		DP(NETIF_MSG_LINK, "Analyze UNKOWN\n"); +		DP(NETIF_MSG_LINK, "Analyze UNKNOWN\n");  	}  	DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up,  	   old_status, status); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index d5648fc666b..bd1fd3d87c2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -6794,8 +6794,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)  	bnx2x_init_block(bp, BLOCK_DORQ, init_phase); +	bnx2x_init_block(bp, BLOCK_BRB1, init_phase); +  	if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) { -		bnx2x_init_block(bp, BLOCK_BRB1, init_phase);  		if (IS_MF(bp))  			low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246); @@ -11902,7 +11903,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,  	/* disable FCOE L2 queue for E1x */  	if (CHIP_IS_E1x(bp))  		bp->flags |= NO_FCOE_FLAG; - +	/* disable FCOE for 57840 device, until FW supports it */ +	switch (ent->driver_data) { +	case BCM57840_O: +	case BCM57840_4_10: +	case BCM57840_2_20: +	case BCM57840_MFO: +	case BCM57840_MF: +		bp->flags |= NO_FCOE_FLAG; +	}  #endif diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index a4da893ac1e..378988b5709 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -251,6 +251,8 @@ struct adapter_params {  	unsigned char rev;                /* chip revision */  	unsigned char offload; +	unsigned char bypass; +  	unsigned int ofldq_wr_cred;  }; @@ -642,6 +644,23 @@ extern int dbfifo_int_thresh;  #define for_each_port(adapter, iter) \  	for (iter = 0; iter < (adapter)->params.nports; ++iter) +static inline int is_bypass(struct adapter *adap) +{ +	return adap->params.bypass; +} + +static inline int is_bypass_device(int device) +{ +	/* this should be set based upon device capabilities */ +	switch (device) { +	case 0x440b: +	case 0x440c: +		return 1; +	default: +		return 0; +	} +} +  static inline unsigned int core_ticks_per_usec(const struct adapter *adap)  {  	return adap->params.vpd.cclk / 1000; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 604f4f87f55..0df1284df49 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -3416,16 +3416,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)  			 finicsum, cfcsum);  	/* -	 * If we're a pure NIC driver then disable all offloading facilities. -	 * This will allow the firmware to optimize aspects of the hardware -	 * configuration which will result in improved performance. -	 */ -	caps_cmd.ofldcaps = 0; -	caps_cmd.iscsicaps = 0; -	caps_cmd.rdmacaps = 0; -	caps_cmd.fcoecaps = 0; - -	/*  	 * And now tell the firmware to use the configuration we just loaded.  	 */  	caps_cmd.op_to_write = @@ -3513,18 +3503,6 @@ static int adap_init0_no_config(struct adapter *adapter, int reset)  	if (ret < 0)  		goto bye; -#ifndef CONFIG_CHELSIO_T4_OFFLOAD -	/* -	 * If we're a pure NIC driver then disable all offloading facilities. -	 * This will allow the firmware to optimize aspects of the hardware -	 * configuration which will result in improved performance. -	 */ -	caps_cmd.ofldcaps = 0; -	caps_cmd.iscsicaps = 0; -	caps_cmd.rdmacaps = 0; -	caps_cmd.fcoecaps = 0; -#endif -  	if (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) {  		if (!vf_acls)  			caps_cmd.niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM); @@ -3745,6 +3723,7 @@ static int adap_init0(struct adapter *adap)  	u32 v, port_vec;  	enum dev_state state;  	u32 params[7], val[7]; +	struct fw_caps_config_cmd caps_cmd;  	int reset = 1, j;  	/* @@ -3898,6 +3877,9 @@ static int adap_init0(struct adapter *adap)  			goto bye;  	} +	if (is_bypass_device(adap->pdev->device)) +		adap->params.bypass = 1; +  	/*  	 * Grab some of our basic fundamental operating parameters.  	 */ @@ -3940,13 +3922,12 @@ static int adap_init0(struct adapter *adap)  		adap->tids.aftid_end = val[1];  	} -#ifdef CONFIG_CHELSIO_T4_OFFLOAD  	/*  	 * Get device capabilities so we can determine what resources we need  	 * to manage.  	 */  	memset(&caps_cmd, 0, sizeof(caps_cmd)); -	caps_cmd.op_to_write = htonl(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | +	caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |  				     FW_CMD_REQUEST | FW_CMD_READ);  	caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));  	ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd), @@ -3991,15 +3972,6 @@ static int adap_init0(struct adapter *adap)  		adap->vres.ddp.size = val[4] - val[3] + 1;  		adap->params.ofldq_wr_cred = val[5]; -		params[0] = FW_PARAM_PFVF(ETHOFLD_START); -		params[1] = FW_PARAM_PFVF(ETHOFLD_END); -		ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, -				      params, val); -		if ((val[0] != val[1]) && (ret >= 0)) { -			adap->tids.uotid_base = val[0]; -			adap->tids.nuotids = val[1] - val[0] + 1; -		} -  		adap->params.offload = 1;  	}  	if (caps_cmd.rdmacaps) { @@ -4048,7 +4020,6 @@ static int adap_init0(struct adapter *adap)  	}  #undef FW_PARAM_PFVF  #undef FW_PARAM_DEV -#endif /* CONFIG_CHELSIO_T4_OFFLOAD */  	/*  	 * These are finalized by FW initialization, load their values now. diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 1b899fea1a9..39bec73ff87 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -102,6 +102,9 @@ struct tid_info {  	unsigned int ftid_base;  	unsigned int aftid_base;  	unsigned int aftid_end; +	/* Server filter region */ +	unsigned int sftid_base; +	unsigned int nsftids;  	spinlock_t atid_lock ____cacheline_aligned_in_smp;  	union aopen_entry *afree; diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 32eec15fe4c..730ae2cfa49 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -2519,6 +2519,7 @@ int t4_fw_bye(struct adapter *adap, unsigned int mbox)  {  	struct fw_bye_cmd c; +	memset(&c, 0, sizeof(c));  	INIT_CMD(c, BYE, WRITE);  	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);  } @@ -2535,6 +2536,7 @@ int t4_early_init(struct adapter *adap, unsigned int mbox)  {  	struct fw_initialize_cmd c; +	memset(&c, 0, sizeof(c));  	INIT_CMD(c, INITIALIZE, WRITE);  	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);  } @@ -2551,6 +2553,7 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset)  {  	struct fw_reset_cmd c; +	memset(&c, 0, sizeof(c));  	INIT_CMD(c, RESET, WRITE);  	c.val = htonl(reset);  	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); @@ -2828,7 +2831,7 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,  		     HOSTPAGESIZEPF7(sge_hps));  	t4_set_reg_field(adap, SGE_CONTROL, -			 INGPADBOUNDARY(INGPADBOUNDARY_MASK) | +			 INGPADBOUNDARY_MASK |  			 EGRSTATUSPAGESIZE_MASK,  			 INGPADBOUNDARY(fl_align_log - 5) |  			 EGRSTATUSPAGESIZE(stat_len != 64)); @@ -3278,6 +3281,7 @@ int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,  {  	struct fw_vi_enable_cmd c; +	memset(&c, 0, sizeof(c));  	c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |  			     FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));  	c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED | FW_LEN16(c)); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 1d03dcdd5e5..19ac096cb07 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1353,8 +1353,11 @@ static int gfar_restore(struct device *dev)  	struct gfar_private *priv = dev_get_drvdata(dev);  	struct net_device *ndev = priv->ndev; -	if (!netif_running(ndev)) +	if (!netif_running(ndev)) { +		netif_device_attach(ndev); +  		return 0; +	}  	gfar_init_bds(ndev);  	init_registers(ndev); diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c index b9db0e04056..2e5daee0438 100644 --- a/drivers/net/ethernet/freescale/gianfar_ptp.c +++ b/drivers/net/ethernet/freescale/gianfar_ptp.c @@ -478,7 +478,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)  		pr_err("no resource\n");  		goto no_resource;  	} -	if (request_resource(&ioport_resource, etsects->rsrc)) { +	if (request_resource(&iomem_resource, etsects->rsrc)) {  		pr_err("resource busy\n");  		goto no_resource;  	} diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 56b20d17d0e..116f0e901be 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2673,6 +2673,9 @@ static int ixgbe_get_ts_info(struct net_device *dev,  	case ixgbe_mac_X540:  	case ixgbe_mac_82599EB:  		info->so_timestamping = +			SOF_TIMESTAMPING_TX_SOFTWARE | +			SOF_TIMESTAMPING_RX_SOFTWARE | +			SOF_TIMESTAMPING_SOFTWARE |  			SOF_TIMESTAMPING_TX_HARDWARE |  			SOF_TIMESTAMPING_RX_HARDWARE |  			SOF_TIMESTAMPING_RAW_HARDWARE; diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index f8064df10cc..92317e9c0f7 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -1948,10 +1948,10 @@ jme_close(struct net_device *netdev)  	JME_NAPI_DISABLE(jme); -	tasklet_disable(&jme->linkch_task); -	tasklet_disable(&jme->txclean_task); -	tasklet_disable(&jme->rxclean_task); -	tasklet_disable(&jme->rxempty_task); +	tasklet_kill(&jme->linkch_task); +	tasklet_kill(&jme->txclean_task); +	tasklet_kill(&jme->rxclean_task); +	tasklet_kill(&jme->rxempty_task);  	jme_disable_rx_engine(jme);  	jme_disable_tx_engine(jme); diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 9b9c2ac5c4c..d19a143aa5a 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -4026,7 +4026,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)  	dev0 = hw->dev[0];  	unregister_netdev(dev0); -	tasklet_disable(&hw->phy_task); +	tasklet_kill(&hw->phy_task);  	spin_lock_irq(&hw->hw_lock);  	hw->intr_mask = 0; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index c10e3a6de09..b35094c590b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -143,7 +143,6 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,  		mlx4_bf_free(mdev->dev, &ring->bf);  	mlx4_qp_remove(mdev->dev, &ring->qp);  	mlx4_qp_free(mdev->dev, &ring->qp); -	mlx4_qp_release_range(mdev->dev, ring->qpn, 1);  	mlx4_en_unmap_buffer(&ring->wqres.buf);  	mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);  	kfree(ring->bounce_buf); @@ -712,7 +711,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)  	if (bounce)  		tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size); -	if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) { +	if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tx_tag_present(skb)) {  		*(__be32 *) (&tx_desc->ctrl.vlan_tag) |= cpu_to_be32(ring->doorbell_qpn);  		op_own |= htonl((bf_index & 0xffff) << 8);  		/* Ensure new descirptor hits memory diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 51c764901ad..b84a88bc44d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -329,9 +329,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave,  	ctx = &priv->mfunc.master.slave_state[slave];  	spin_lock_irqsave(&ctx->lock, flags); -	mlx4_dbg(dev, "%s: slave: %d, current state: %d new event :%d\n", -		 __func__, slave, cur_state, event); -  	switch (cur_state) {  	case SLAVE_PORT_DOWN:  		if (MLX4_PORT_STATE_DEV_EVENT_PORT_UP == event) @@ -366,9 +363,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave,  			goto out;  	}  	ret = mlx4_get_slave_port_state(dev, slave, port); -	mlx4_dbg(dev, "%s: slave: %d, current state: %d new event" -		 " :%d gen_event: %d\n", -		 __func__, slave, cur_state, event, *gen_event);  out:  	spin_unlock_irqrestore(&ctx->lock, flags); @@ -843,6 +837,18 @@ static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq)  	return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4);  } +static void mlx4_unmap_uar(struct mlx4_dev *dev) +{ +	struct mlx4_priv *priv = mlx4_priv(dev); +	int i; + +	for (i = 0; i < mlx4_num_eq_uar(dev); ++i) +		if (priv->eq_table.uar_map[i]) { +			iounmap(priv->eq_table.uar_map[i]); +			priv->eq_table.uar_map[i] = NULL; +		} +} +  static int mlx4_create_eq(struct mlx4_dev *dev, int nent,  			  u8 intr, struct mlx4_eq *eq)  { @@ -1207,6 +1213,7 @@ err_out_unmap:  	mlx4_free_irqs(dev);  err_out_bitmap: +	mlx4_unmap_uar(dev);  	mlx4_bitmap_cleanup(&priv->eq_table.bitmap);  err_out_free: @@ -1231,10 +1238,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)  	if (!mlx4_is_slave(dev))  		mlx4_unmap_clr_int(dev); -	for (i = 0; i < mlx4_num_eq_uar(dev); ++i) -		if (priv->eq_table.uar_map[i]) -			iounmap(priv->eq_table.uar_map[i]); - +	mlx4_unmap_uar(dev);  	mlx4_bitmap_cleanup(&priv->eq_table.bitmap);  	kfree(priv->eq_table.uar_map); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 80df2ab0177..2aa80afd98d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1405,7 +1405,10 @@ unmap_bf:  	unmap_bf_area(dev);  err_close: -	mlx4_close_hca(dev); +	if (mlx4_is_slave(dev)) +		mlx4_slave_exit(dev); +	else +		mlx4_CLOSE_HCA(dev, 0);  err_free_icm:  	if (!mlx4_is_slave(dev)) diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 926c911c0ac..b05705f50f0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -330,9 +330,6 @@ static void update_pkey_index(struct mlx4_dev *dev, int slave,  	new_index = priv->virt2phys_pkey[slave][port - 1][orig_index];  	*(u8 *)(inbox->buf + 35) = new_index; - -	mlx4_dbg(dev, "port = %d, orig pkey index = %d, " -		 "new pkey index = %d\n", port, orig_index, new_index);  }  static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox, @@ -351,9 +348,6 @@ static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,  		if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH)  			qp_ctx->alt_path.mgid_index = slave & 0x7F;  	} - -	mlx4_dbg(dev, "slave %d, new gid index: 0x%x ", -		slave, qp_ctx->pri_path.mgid_index);  }  static int mpt_mask(struct mlx4_dev *dev) diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index 318fee91c79..e558edd1cb6 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -5407,8 +5407,8 @@ static int netdev_close(struct net_device *dev)  		/* Delay for receive task to stop scheduling itself. */  		msleep(2000 / HZ); -		tasklet_disable(&hw_priv->rx_tasklet); -		tasklet_disable(&hw_priv->tx_tasklet); +		tasklet_kill(&hw_priv->rx_tasklet); +		tasklet_kill(&hw_priv->tx_tasklet);  		free_irq(dev->irq, hw_priv->dev);  		transmit_cleanup(hw_priv, 0); diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 53743f7a2ca..af8b4142088 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1524,6 +1524,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)  				  pldat->dma_buff_base_p);  	free_irq(ndev->irq, ndev);  	iounmap(pldat->net_base); +	mdiobus_unregister(pldat->mii_bus);  	mdiobus_free(pldat->mii_bus);  	clk_disable(pldat->clk);  	clk_put(pldat->clk); diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index b2a94d02a52..4c4fe5b1a29 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -339,26 +339,6 @@ static void pch_gbe_wait_clr_bit(void *reg, u32 bit)  }  /** - * pch_gbe_wait_clr_bit_irq - Wait to clear a bit for interrupt context - * @reg:	Pointer of register - * @busy:	Busy bit - */ -static int pch_gbe_wait_clr_bit_irq(void *reg, u32 bit) -{ -	u32 tmp; -	int ret = -1; -	/* wait busy */ -	tmp = 20; -	while ((ioread32(reg) & bit) && --tmp) -		udelay(5); -	if (!tmp) -		pr_err("Error: busy bit is not cleared\n"); -	else -		ret = 0; -	return ret; -} - -/**   * pch_gbe_mac_mar_set - Set MAC address register   * @hw:	    Pointer to the HW structure   * @addr:   Pointer to the MAC address @@ -409,15 +389,20 @@ static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw)  	return;  } -static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw) +static void pch_gbe_disable_mac_rx(struct pch_gbe_hw *hw)  { -	/* Read the MAC addresses. and store to the private data */ -	pch_gbe_mac_read_mac_addr(hw); -	iowrite32(PCH_GBE_RX_RST, &hw->reg->RESET); -	pch_gbe_wait_clr_bit_irq(&hw->reg->RESET, PCH_GBE_RX_RST); -	/* Setup the MAC addresses */ -	pch_gbe_mac_mar_set(hw, hw->mac.addr, 0); -	return; +	u32 rctl; +	/* Disables Receive MAC */ +	rctl = ioread32(&hw->reg->MAC_RX_EN); +	iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN); +} + +static void pch_gbe_enable_mac_rx(struct pch_gbe_hw *hw) +{ +	u32 rctl; +	/* Enables Receive MAC */ +	rctl = ioread32(&hw->reg->MAC_RX_EN); +	iowrite32((rctl | PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);  }  /** @@ -913,7 +898,7 @@ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter)  static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)  {  	struct pch_gbe_hw *hw = &adapter->hw; -	u32 rdba, rdlen, rctl, rxdma; +	u32 rdba, rdlen, rxdma;  	pr_debug("dma adr = 0x%08llx  size = 0x%08x\n",  		 (unsigned long long)adapter->rx_ring->dma, @@ -921,9 +906,7 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)  	pch_gbe_mac_force_mac_fc(hw); -	/* Disables Receive MAC */ -	rctl = ioread32(&hw->reg->MAC_RX_EN); -	iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN); +	pch_gbe_disable_mac_rx(hw);  	/* Disables Receive DMA */  	rxdma = ioread32(&hw->reg->DMA_CTRL); @@ -1316,38 +1299,17 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter)  	spin_unlock_irqrestore(&adapter->stats_lock, flags);  } -static void pch_gbe_stop_receive(struct pch_gbe_adapter *adapter) +static void pch_gbe_disable_dma_rx(struct pch_gbe_hw *hw)  { -	struct pch_gbe_hw *hw = &adapter->hw;  	u32 rxdma; -	u16 value; -	int ret;  	/* Disable Receive DMA */  	rxdma = ioread32(&hw->reg->DMA_CTRL);  	rxdma &= ~PCH_GBE_RX_DMA_EN;  	iowrite32(rxdma, &hw->reg->DMA_CTRL); -	/* Wait Rx DMA BUS is IDLE */ -	ret = pch_gbe_wait_clr_bit_irq(&hw->reg->RX_DMA_ST, PCH_GBE_IDLE_CHECK); -	if (ret) { -		/* Disable Bus master */ -		pci_read_config_word(adapter->pdev, PCI_COMMAND, &value); -		value &= ~PCI_COMMAND_MASTER; -		pci_write_config_word(adapter->pdev, PCI_COMMAND, value); -		/* Stop Receive */ -		pch_gbe_mac_reset_rx(hw); -		/* Enable Bus master */ -		value |= PCI_COMMAND_MASTER; -		pci_write_config_word(adapter->pdev, PCI_COMMAND, value); -	} else { -		/* Stop Receive */ -		pch_gbe_mac_reset_rx(hw); -	} -	/* reprogram multicast address register after reset */ -	pch_gbe_set_multi(adapter->netdev);  } -static void pch_gbe_start_receive(struct pch_gbe_hw *hw) +static void pch_gbe_enable_dma_rx(struct pch_gbe_hw *hw)  {  	u32 rxdma; @@ -1355,9 +1317,6 @@ static void pch_gbe_start_receive(struct pch_gbe_hw *hw)  	rxdma = ioread32(&hw->reg->DMA_CTRL);  	rxdma |= PCH_GBE_RX_DMA_EN;  	iowrite32(rxdma, &hw->reg->DMA_CTRL); -	/* Enables Receive */ -	iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN); -	return;  }  /** @@ -1393,7 +1352,7 @@ static irqreturn_t pch_gbe_intr(int irq, void *data)  			int_en = ioread32(&hw->reg->INT_EN);  			iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR),  				  &hw->reg->INT_EN); -			pch_gbe_stop_receive(adapter); +			pch_gbe_disable_dma_rx(&adapter->hw);  			int_st |= ioread32(&hw->reg->INT_ST);  			int_st = int_st & ioread32(&hw->reg->INT_EN);  		} @@ -1971,12 +1930,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)  	struct net_device *netdev = adapter->netdev;  	struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;  	struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring; -	int err; +	int err = -EINVAL;  	/* Ensure we have a valid MAC */  	if (!is_valid_ether_addr(adapter->hw.mac.addr)) {  		pr_err("Error: Invalid MAC address\n"); -		return -EINVAL; +		goto out;  	}  	/* hardware has been reset, we need to reload some things */ @@ -1989,18 +1948,19 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)  	err = pch_gbe_request_irq(adapter);  	if (err) { -		pr_err("Error: can't bring device up\n"); -		return err; +		pr_err("Error: can't bring device up - irq request failed\n"); +		goto out;  	}  	err = pch_gbe_alloc_rx_buffers_pool(adapter, rx_ring, rx_ring->count);  	if (err) { -		pr_err("Error: can't bring device up\n"); -		return err; +		pr_err("Error: can't bring device up - alloc rx buffers pool failed\n"); +		goto freeirq;  	}  	pch_gbe_alloc_tx_buffers(adapter, tx_ring);  	pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count);  	adapter->tx_queue_len = netdev->tx_queue_len; -	pch_gbe_start_receive(&adapter->hw); +	pch_gbe_enable_dma_rx(&adapter->hw); +	pch_gbe_enable_mac_rx(&adapter->hw);  	mod_timer(&adapter->watchdog_timer, jiffies); @@ -2009,6 +1969,11 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)  	netif_start_queue(adapter->netdev);  	return 0; + +freeirq: +	pch_gbe_free_irq(adapter); +out: +	return err;  }  /** @@ -2405,7 +2370,6 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)  	int work_done = 0;  	bool poll_end_flag = false;  	bool cleaned = false; -	u32 int_en;  	pr_debug("budget : %d\n", budget); @@ -2422,19 +2386,13 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)  	if (poll_end_flag) {  		napi_complete(napi); -		if (adapter->rx_stop_flag) { -			adapter->rx_stop_flag = false; -			pch_gbe_start_receive(&adapter->hw); -		}  		pch_gbe_irq_enable(adapter); -	} else -		if (adapter->rx_stop_flag) { -			adapter->rx_stop_flag = false; -			pch_gbe_start_receive(&adapter->hw); -			int_en = ioread32(&adapter->hw.reg->INT_EN); -			iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR), -				&adapter->hw.reg->INT_EN); -		} +	} + +	if (adapter->rx_stop_flag) { +		adapter->rx_stop_flag = false; +		pch_gbe_enable_dma_rx(&adapter->hw); +	}  	pr_debug("poll_end_flag : %d  work_done : %d  budget : %d\n",  		 poll_end_flag, work_done, budget); diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index df09b1cb742..6407d0d77e8 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -2525,6 +2525,13 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)  	qdev->req_q_size =  	    (u32) (NUM_REQ_Q_ENTRIES * sizeof(struct ob_mac_iocb_req)); +	qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb); + +	/* The barrier is required to ensure request and response queue +	 * addr writes to the registers. +	 */ +	wmb(); +  	qdev->req_q_virt_addr =  	    pci_alloc_consistent(qdev->pdev,  				 (size_t) qdev->req_q_size, @@ -2536,8 +2543,6 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)  		return -ENOMEM;  	} -	qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb); -  	qdev->rsp_q_virt_addr =  	    pci_alloc_consistent(qdev->pdev,  				 (size_t) qdev->rsp_q_size, diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index e7ff886e804..927aa33d434 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -3827,6 +3827,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)  	void __iomem *ioaddr = tp->mmio_addr;  	switch (tp->mac_version) { +	case RTL_GIGA_MAC_VER_25: +	case RTL_GIGA_MAC_VER_26:  	case RTL_GIGA_MAC_VER_29:  	case RTL_GIGA_MAC_VER_30:  	case RTL_GIGA_MAC_VER_32: @@ -4519,6 +4521,9 @@ static void rtl_set_rx_mode(struct net_device *dev)  		mc_filter[1] = swab32(data);  	} +	if (tp->mac_version == RTL_GIGA_MAC_VER_35) +		mc_filter[1] = mc_filter[0] = 0xffffffff; +  	RTL_W32(MAR0 + 4, mc_filter[1]);  	RTL_W32(MAR0 + 0, mc_filter[0]); diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig index b26cbda5efa..2c41894d547 100644 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig @@ -5,7 +5,7 @@  config NET_VENDOR_TI  	bool "Texas Instruments (TI) devices"  	default y -	depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3)) +	depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX))  	---help---  	  If you have a network (Ethernet) card belonging to this class, say Y  	  and read the Ethernet-HOWTO, available from diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 4e2a1628484..4e981001385 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c @@ -1334,11 +1334,11 @@ static int tso_count_edescs(struct sk_buff *skb)  {  	struct skb_shared_info *sh = skb_shinfo(skb);  	unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); -	unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; +	unsigned int data_len = skb->len - sh_len;  	unsigned int p_len = sh->gso_size;  	long f_id = -1;    /* id of the current fragment */ -	long f_size = skb->hdr_len;  /* size of the current fragment */ -	long f_used = sh_len;  /* bytes used from the current fragment */ +	long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */ +	long f_used = 0;  /* bytes used from the current fragment */  	long n;            /* size of the current piece of payload */  	int num_edescs = 0;  	int segment; @@ -1353,7 +1353,7 @@ static int tso_count_edescs(struct sk_buff *skb)  			/* Advance as needed. */  			while (f_used >= f_size) {  				f_id++; -				f_size = sh->frags[f_id].size; +				f_size = skb_frag_size(&sh->frags[f_id]);  				f_used = 0;  			} @@ -1384,13 +1384,13 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,  	struct iphdr *ih;  	struct tcphdr *th;  	unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); -	unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; +	unsigned int data_len = skb->len - sh_len;  	unsigned char *data = skb->data;  	unsigned int ih_off, th_off, p_len;  	unsigned int isum_seed, tsum_seed, id, seq;  	long f_id = -1;    /* id of the current fragment */ -	long f_size = skb->hdr_len;  /* size of the current fragment */ -	long f_used = sh_len;  /* bytes used from the current fragment */ +	long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */ +	long f_used = 0;  /* bytes used from the current fragment */  	long n;            /* size of the current piece of payload */  	int segment; @@ -1405,7 +1405,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,  	isum_seed = ((0xFFFF - ih->check) +  		     (0xFFFF - ih->tot_len) +  		     (0xFFFF - ih->id)); -	tsum_seed = th->check + (0xFFFF ^ htons(sh_len + data_len)); +	tsum_seed = th->check + (0xFFFF ^ htons(skb->len));  	id = ntohs(ih->id);  	seq = ntohl(th->seq); @@ -1444,7 +1444,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,  			/* Advance as needed. */  			while (f_used >= f_size) {  				f_id++; -				f_size = sh->frags[f_id].size; +				f_size = skb_frag_size(&sh->frags[f_id]);  				f_used = 0;  			} @@ -1478,14 +1478,14 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,  	struct tile_net_priv *priv = netdev_priv(dev);  	struct skb_shared_info *sh = skb_shinfo(skb);  	unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); -	unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; +	unsigned int data_len = skb->len - sh_len;  	unsigned int p_len = sh->gso_size;  	gxio_mpipe_edesc_t edesc_head = { { 0 } };  	gxio_mpipe_edesc_t edesc_body = { { 0 } };  	long f_id = -1;    /* id of the current fragment */ -	long f_size = skb->hdr_len;  /* size of the current fragment */ -	long f_used = sh_len;  /* bytes used from the current fragment */ -	void *f_data = skb->data; +	long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */ +	long f_used = 0;  /* bytes used from the current fragment */ +	void *f_data = skb->data + sh_len;  	long n;            /* size of the current piece of payload */  	unsigned long tx_packets = 0, tx_bytes = 0;  	unsigned int csum_start; @@ -1516,15 +1516,18 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,  		/* Egress the payload. */  		while (p_used < p_len) { +			void *va;  			/* Advance as needed. */  			while (f_used >= f_size) {  				f_id++; -				f_size = sh->frags[f_id].size; -				f_used = 0; +				f_size = skb_frag_size(&sh->frags[f_id]);  				f_data = tile_net_frag_buf(&sh->frags[f_id]); +				f_used = 0;  			} +			va = f_data + f_used; +  			/* Use bytes from the current fragment. */  			n = p_len - p_used;  			if (n > f_size - f_used) @@ -1533,7 +1536,7 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,  			p_used += n;  			/* Egress a piece of the payload. */ -			edesc_body.va = va_to_tile_io_addr(f_data) + f_used; +			edesc_body.va = va_to_tile_io_addr(va);  			edesc_body.xfer_size = n;  			edesc_body.bound = !(p_used < p_len);  			gxio_mpipe_equeue_put_at(equeue, edesc_body, slot); diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 0793299bd39..1d04754a663 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -990,7 +990,7 @@ static int axienet_stop(struct net_device *ndev)  	axienet_setoptions(ndev, lp->options &  			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); -	tasklet_disable(&lp->dma_err_tasklet); +	tasklet_kill(&lp->dma_err_tasklet);  	free_irq(lp->tx_irq, ndev);  	free_irq(lp->rx_irq, ndev); diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 983bbf4d5ef..961f0b29391 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -15,6 +15,11 @@ if PHYLIB  comment "MII PHY device drivers" +config AT803X_PHY +	tristate "Drivers for Atheros AT803X PHYs" +	---help--- +	  Currently supports the AT8030 and AT8035 model +  config AMD_PHY  	tristate "Drivers for the AMD PHYs"  	---help--- diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 426674debae..9645e389a58 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_STE10XP)		+= ste10Xp.o  obj-$(CONFIG_MICREL_PHY)	+= micrel.o  obj-$(CONFIG_MDIO_OCTEON)	+= mdio-octeon.o  obj-$(CONFIG_MICREL_KS8995MA)	+= spi_ks8995.o +obj-$(CONFIG_AT803X_PHY)	+= at803x.o  obj-$(CONFIG_AMD_PHY)		+= amd.o  obj-$(CONFIG_MDIO_BUS_MUX)	+= mdio-mux.o  obj-$(CONFIG_MDIO_BUS_MUX_GPIO)	+= mdio-mux-gpio.o diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c new file mode 100644 index 00000000000..45cbc10de01 --- /dev/null +++ b/drivers/net/phy/at803x.c @@ -0,0 +1,176 @@ +/* + * drivers/net/phy/at803x.c + * + * Driver for Atheros 803x PHY + * + * Author: Matus Ujhelyi <ujhelyi.m@gmail.com> + * + * This program is free software; you can redistribute  it and/or modify it + * under  the terms of  the GNU General  Public License as published by the + * Free Software Foundation;  either version 2 of the  License, or (at your + * option) any later version. + */ + +#include <linux/phy.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> + +#define AT803X_INTR_ENABLE			0x12 +#define AT803X_INTR_STATUS			0x13 +#define AT803X_WOL_ENABLE			0x01 +#define AT803X_DEVICE_ADDR			0x03 +#define AT803X_LOC_MAC_ADDR_0_15_OFFSET		0x804C +#define AT803X_LOC_MAC_ADDR_16_31_OFFSET	0x804B +#define AT803X_LOC_MAC_ADDR_32_47_OFFSET	0x804A +#define AT803X_MMD_ACCESS_CONTROL		0x0D +#define AT803X_MMD_ACCESS_CONTROL_DATA		0x0E +#define AT803X_FUNC_DATA			0x4003 + +MODULE_DESCRIPTION("Atheros 803x PHY driver"); +MODULE_AUTHOR("Matus Ujhelyi"); +MODULE_LICENSE("GPL"); + +static void at803x_set_wol_mac_addr(struct phy_device *phydev) +{ +	struct net_device *ndev = phydev->attached_dev; +	const u8 *mac; +	unsigned int i, offsets[] = { +		AT803X_LOC_MAC_ADDR_32_47_OFFSET, +		AT803X_LOC_MAC_ADDR_16_31_OFFSET, +		AT803X_LOC_MAC_ADDR_0_15_OFFSET, +	}; + +	if (!ndev) +		return; + +	mac = (const u8 *) ndev->dev_addr; + +	if (!is_valid_ether_addr(mac)) +		return; + +	for (i = 0; i < 3; i++) { +		phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, +				  AT803X_DEVICE_ADDR); +		phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, +				  offsets[i]); +		phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, +				  AT803X_FUNC_DATA); +		phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, +				  mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); +	} +} + +static int at803x_config_init(struct phy_device *phydev) +{ +	int val; +	u32 features; +	int status; + +	features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI | +		   SUPPORTED_FIBRE | SUPPORTED_BNC; + +	val = phy_read(phydev, MII_BMSR); +	if (val < 0) +		return val; + +	if (val & BMSR_ANEGCAPABLE) +		features |= SUPPORTED_Autoneg; +	if (val & BMSR_100FULL) +		features |= SUPPORTED_100baseT_Full; +	if (val & BMSR_100HALF) +		features |= SUPPORTED_100baseT_Half; +	if (val & BMSR_10FULL) +		features |= SUPPORTED_10baseT_Full; +	if (val & BMSR_10HALF) +		features |= SUPPORTED_10baseT_Half; + +	if (val & BMSR_ESTATEN) { +		val = phy_read(phydev, MII_ESTATUS); +		if (val < 0) +			return val; + +		if (val & ESTATUS_1000_TFULL) +			features |= SUPPORTED_1000baseT_Full; +		if (val & ESTATUS_1000_THALF) +			features |= SUPPORTED_1000baseT_Half; +	} + +	phydev->supported = features; +	phydev->advertising = features; + +	/* enable WOL */ +	at803x_set_wol_mac_addr(phydev); +	status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE); +	status = phy_read(phydev, AT803X_INTR_STATUS); + +	return 0; +} + +/* ATHEROS 8035 */ +static struct phy_driver at8035_driver = { +	.phy_id		= 0x004dd072, +	.name		= "Atheros 8035 ethernet", +	.phy_id_mask	= 0xffffffef, +	.config_init	= at803x_config_init, +	.features	= PHY_GBIT_FEATURES, +	.flags		= PHY_HAS_INTERRUPT, +	.config_aneg	= &genphy_config_aneg, +	.read_status	= &genphy_read_status, +	.driver		= { +		.owner = THIS_MODULE, +	}, +}; + +/* ATHEROS 8030 */ +static struct phy_driver at8030_driver = { +	.phy_id		= 0x004dd076, +	.name		= "Atheros 8030 ethernet", +	.phy_id_mask	= 0xffffffef, +	.config_init	= at803x_config_init, +	.features	= PHY_GBIT_FEATURES, +	.flags		= PHY_HAS_INTERRUPT, +	.config_aneg	= &genphy_config_aneg, +	.read_status	= &genphy_read_status, +	.driver		= { +		.owner = THIS_MODULE, +	}, +}; + +static int __init atheros_init(void) +{ +	int ret; + +	ret = phy_driver_register(&at8035_driver); +	if (ret) +		goto err1; + +	ret = phy_driver_register(&at8030_driver); +	if (ret) +		goto err2; + +	return 0; + +err2: +	phy_driver_unregister(&at8035_driver); +err1: +	return ret; +} + +static void __exit atheros_exit(void) +{ +	phy_driver_unregister(&at8035_driver); +	phy_driver_unregister(&at8030_driver); +} + +module_init(atheros_init); +module_exit(atheros_exit); + +static struct mdio_device_id __maybe_unused atheros_tbl[] = { +	{ 0x004dd076, 0xffffffef }, +	{ 0x004dd072, 0xffffffef }, +	{ } +}; + +MODULE_DEVICE_TABLE(mdio, atheros_tbl); diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c index daec9b05d16..6428fcbbdd4 100644 --- a/drivers/net/phy/mdio-bitbang.c +++ b/drivers/net/phy/mdio-bitbang.c @@ -234,6 +234,7 @@ void free_mdio_bitbang(struct mii_bus *bus)  	struct mdiobb_ctrl *ctrl = bus->priv;  	module_put(ctrl->ops->owner); +	mdiobus_unregister(bus);  	mdiobus_free(bus);  }  EXPORT_SYMBOL(free_mdio_bitbang); diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c index c81e278629f..08d55b6bf27 100644 --- a/drivers/net/usb/cdc_eem.c +++ b/drivers/net/usb/cdc_eem.c @@ -31,6 +31,7 @@  #include <linux/usb/cdc.h>  #include <linux/usb/usbnet.h>  #include <linux/gfp.h> +#include <linux/if_vlan.h>  /* @@ -92,7 +93,7 @@ static int eem_bind(struct usbnet *dev, struct usb_interface *intf)  	/* no jumbogram (16K) support for now */ -	dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN; +	dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN + VLAN_HLEN;  	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;  	return 0; diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index a03de719704..d0129827602 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -592,6 +592,32 @@ static const struct usb_device_id	products [] = {  	.driver_info		= 0,  }, +/* Novatel USB551L and MC551 - handled by qmi_wwan */ +{ +	.match_flags    =   USB_DEVICE_ID_MATCH_VENDOR +		 | USB_DEVICE_ID_MATCH_PRODUCT +		 | USB_DEVICE_ID_MATCH_INT_INFO, +	.idVendor               = NOVATEL_VENDOR_ID, +	.idProduct		= 0xB001, +	.bInterfaceClass	= USB_CLASS_COMM, +	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET, +	.bInterfaceProtocol	= USB_CDC_PROTO_NONE, +	.driver_info = 0, +}, + +/* Novatel E362 - handled by qmi_wwan */ +{ +	.match_flags    =   USB_DEVICE_ID_MATCH_VENDOR +		 | USB_DEVICE_ID_MATCH_PRODUCT +		 | USB_DEVICE_ID_MATCH_INT_INFO, +	.idVendor               = NOVATEL_VENDOR_ID, +	.idProduct		= 0x9010, +	.bInterfaceClass	= USB_CLASS_COMM, +	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET, +	.bInterfaceProtocol	= USB_CDC_PROTO_NONE, +	.driver_info = 0, +}, +  /*   * WHITELIST!!!   * @@ -604,21 +630,6 @@ static const struct usb_device_id	products [] = {   * because of bugs/quirks in a given product (like Zaurus, above).   */  { -	/* Novatel USB551L */ -	/* This match must come *before* the generic CDC-ETHER match so that -	 * we get FLAG_WWAN set on the device, since it's descriptors are -	 * generic CDC-ETHER. -	 */ -	.match_flags    =   USB_DEVICE_ID_MATCH_VENDOR -		 | USB_DEVICE_ID_MATCH_PRODUCT -		 | USB_DEVICE_ID_MATCH_INT_INFO, -	.idVendor               = NOVATEL_VENDOR_ID, -	.idProduct		= 0xB001, -	.bInterfaceClass	= USB_CLASS_COMM, -	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET, -	.bInterfaceProtocol	= USB_CDC_PROTO_NONE, -	.driver_info = (unsigned long)&wwan_info, -}, {  	/* ZTE (Vodafone) K3805-Z */  	.match_flags    =   USB_DEVICE_ID_MATCH_VENDOR  		 | USB_DEVICE_ID_MATCH_PRODUCT diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index a28a983d465..534d8becbbd 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -62,6 +62,7 @@  #define USB_PRODUCT_IPAD 0x129a  #define USB_PRODUCT_IPHONE_4_VZW 0x129c  #define USB_PRODUCT_IPHONE_4S	0x12a0 +#define USB_PRODUCT_IPHONE_5	0x12a8  #define IPHETH_USBINTF_CLASS    255  #define IPHETH_USBINTF_SUBCLASS 253 @@ -113,6 +114,10 @@ static struct usb_device_id ipheth_table[] = {  		USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S,  		IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,  		IPHETH_USBINTF_PROTO) }, +	{ USB_DEVICE_AND_INTERFACE_INFO( +		USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5, +		IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, +		IPHETH_USBINTF_PROTO) },  	{ }  };  MODULE_DEVICE_TABLE(usb, ipheth_table); diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 6883c371c59..3b566fa0f8e 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -369,18 +369,73 @@ static const struct usb_device_id products[] = {  		USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),  		.driver_info        = (unsigned long)&qmi_wwan_info,  	}, +	{	/* Novatel USB551L and MC551 */ +		USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0xb001, +		                              USB_CLASS_COMM, +		                              USB_CDC_SUBCLASS_ETHERNET, +		                              USB_CDC_PROTO_NONE), +		.driver_info        = (unsigned long)&qmi_wwan_info, +	}, +	{	/* Novatel E362 */ +		USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0x9010, +		                              USB_CLASS_COMM, +		                              USB_CDC_SUBCLASS_ETHERNET, +		                              USB_CDC_PROTO_NONE), +		.driver_info        = (unsigned long)&qmi_wwan_info, +	},  	/* 3. Combined interface devices matching on interface number */ +	{QMI_FIXED_INTF(0x19d2, 0x0002, 1)}, +	{QMI_FIXED_INTF(0x19d2, 0x0012, 1)}, +	{QMI_FIXED_INTF(0x19d2, 0x0017, 3)}, +	{QMI_FIXED_INTF(0x19d2, 0x0021, 4)}, +	{QMI_FIXED_INTF(0x19d2, 0x0025, 1)}, +	{QMI_FIXED_INTF(0x19d2, 0x0031, 4)}, +	{QMI_FIXED_INTF(0x19d2, 0x0042, 4)}, +	{QMI_FIXED_INTF(0x19d2, 0x0049, 5)}, +	{QMI_FIXED_INTF(0x19d2, 0x0052, 4)},  	{QMI_FIXED_INTF(0x19d2, 0x0055, 1)},	/* ZTE (Vodafone) K3520-Z */ +	{QMI_FIXED_INTF(0x19d2, 0x0058, 4)},  	{QMI_FIXED_INTF(0x19d2, 0x0063, 4)},	/* ZTE (Vodafone) K3565-Z */  	{QMI_FIXED_INTF(0x19d2, 0x0104, 4)},	/* ZTE (Vodafone) K4505-Z */ +	{QMI_FIXED_INTF(0x19d2, 0x0113, 5)}, +	{QMI_FIXED_INTF(0x19d2, 0x0118, 5)}, +	{QMI_FIXED_INTF(0x19d2, 0x0121, 5)}, +	{QMI_FIXED_INTF(0x19d2, 0x0123, 4)}, +	{QMI_FIXED_INTF(0x19d2, 0x0124, 5)}, +	{QMI_FIXED_INTF(0x19d2, 0x0125, 6)}, +	{QMI_FIXED_INTF(0x19d2, 0x0126, 5)}, +	{QMI_FIXED_INTF(0x19d2, 0x0130, 1)}, +	{QMI_FIXED_INTF(0x19d2, 0x0133, 3)}, +	{QMI_FIXED_INTF(0x19d2, 0x0141, 5)},  	{QMI_FIXED_INTF(0x19d2, 0x0157, 5)},	/* ZTE MF683 */ +	{QMI_FIXED_INTF(0x19d2, 0x0158, 3)},  	{QMI_FIXED_INTF(0x19d2, 0x0167, 4)},	/* ZTE MF820D */ +	{QMI_FIXED_INTF(0x19d2, 0x0168, 4)}, +	{QMI_FIXED_INTF(0x19d2, 0x0176, 3)}, +	{QMI_FIXED_INTF(0x19d2, 0x0178, 3)}, +	{QMI_FIXED_INTF(0x19d2, 0x0191, 4)},	/* ZTE EuFi890 */ +	{QMI_FIXED_INTF(0x19d2, 0x0199, 1)},	/* ZTE MF820S */ +	{QMI_FIXED_INTF(0x19d2, 0x0200, 1)}, +	{QMI_FIXED_INTF(0x19d2, 0x0257, 3)},	/* ZTE MF821 */  	{QMI_FIXED_INTF(0x19d2, 0x0326, 4)},	/* ZTE MF821D */  	{QMI_FIXED_INTF(0x19d2, 0x1008, 4)},	/* ZTE (Vodafone) K3570-Z */  	{QMI_FIXED_INTF(0x19d2, 0x1010, 4)},	/* ZTE (Vodafone) K3571-Z */ +	{QMI_FIXED_INTF(0x19d2, 0x1012, 4)},  	{QMI_FIXED_INTF(0x19d2, 0x1018, 3)},	/* ZTE (Vodafone) K5006-Z */ +	{QMI_FIXED_INTF(0x19d2, 0x1021, 2)}, +	{QMI_FIXED_INTF(0x19d2, 0x1245, 4)}, +	{QMI_FIXED_INTF(0x19d2, 0x1247, 4)}, +	{QMI_FIXED_INTF(0x19d2, 0x1252, 4)}, +	{QMI_FIXED_INTF(0x19d2, 0x1254, 4)}, +	{QMI_FIXED_INTF(0x19d2, 0x1255, 3)}, +	{QMI_FIXED_INTF(0x19d2, 0x1255, 4)}, +	{QMI_FIXED_INTF(0x19d2, 0x1256, 4)}, +	{QMI_FIXED_INTF(0x19d2, 0x1401, 2)},  	{QMI_FIXED_INTF(0x19d2, 0x1402, 2)},	/* ZTE MF60 */ +	{QMI_FIXED_INTF(0x19d2, 0x1424, 2)}, +	{QMI_FIXED_INTF(0x19d2, 0x1425, 2)}, +	{QMI_FIXED_INTF(0x19d2, 0x1426, 2)},	/* ZTE MF91 */  	{QMI_FIXED_INTF(0x19d2, 0x2002, 4)},	/* ZTE (Vodafone) K3765-Z */  	{QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)},    /* Sierra Wireless MC7700 */  	{QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */ diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 7479a5761d0..3286166415b 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1344,6 +1344,7 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,  		} else {  			u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);  			skb_push(skb, 4); +			cpu_to_le32s(&csum_preamble);  			memcpy(skb->data, &csum_preamble, 4);  		}  	} diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index f9819d10b1f..edb81ed0695 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -359,10 +359,12 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,  void usbnet_defer_kevent (struct usbnet *dev, int work)  {  	set_bit (work, &dev->flags); -	if (!schedule_work (&dev->kevent)) -		netdev_err(dev->net, "kevent %d may have been dropped\n", work); -	else +	if (!schedule_work (&dev->kevent)) { +		if (net_ratelimit()) +			netdev_err(dev->net, "kevent %d may have been dropped\n", work); +	} else {  		netdev_dbg(dev->net, "kevent %d scheduled\n", work); +	}  }  EXPORT_SYMBOL_GPL(usbnet_defer_kevent); @@ -1158,6 +1160,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,  		usb_anchor_urb(urb, &dev->deferred);  		/* no use to process more packets */  		netif_stop_queue(net); +		usb_put_urb(urb);  		spin_unlock_irqrestore(&dev->txq.lock, flags);  		netdev_dbg(dev->net, "Delaying transmission for resumption\n");  		goto deferred; @@ -1310,6 +1313,8 @@ void usbnet_disconnect (struct usb_interface *intf)  	cancel_work_sync(&dev->kevent); +	usb_scuttle_anchored_urbs(&dev->deferred); +  	if (dev->driver_info->unbind)  		dev->driver_info->unbind (dev, intf); diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index ce9d4f2c977..0ae1bcc6da7 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,  	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {  		const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; +		u32 buf_size; -		tbi = tq->buf_info + tq->tx_ring.next2fill; -		tbi->map_type = VMXNET3_MAP_PAGE; -		tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag, -						 0, skb_frag_size(frag), -						 DMA_TO_DEVICE); +		buf_offset = 0; +		len = skb_frag_size(frag); +		while (len) { +			tbi = tq->buf_info + tq->tx_ring.next2fill; +			if (len < VMXNET3_MAX_TX_BUF_SIZE) { +				buf_size = len; +				dw2 |= len; +			} else { +				buf_size = VMXNET3_MAX_TX_BUF_SIZE; +				/* spec says that for TxDesc.len, 0 == 2^14 */ +			} +			tbi->map_type = VMXNET3_MAP_PAGE; +			tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag, +							 buf_offset, buf_size, +							 DMA_TO_DEVICE); -		tbi->len = skb_frag_size(frag); +			tbi->len = buf_size; -		gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; -		BUG_ON(gdesc->txd.gen == tq->tx_ring.gen); +			gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; +			BUG_ON(gdesc->txd.gen == tq->tx_ring.gen); -		gdesc->txd.addr = cpu_to_le64(tbi->dma_addr); -		gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag)); -		gdesc->dword[3] = 0; +			gdesc->txd.addr = cpu_to_le64(tbi->dma_addr); +			gdesc->dword[2] = cpu_to_le32(dw2); +			gdesc->dword[3] = 0; -		dev_dbg(&adapter->netdev->dev, -			"txd[%u]: 0x%llu %u %u\n", -			tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr), -			le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]); -		vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); -		dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT; +			dev_dbg(&adapter->netdev->dev, +				"txd[%u]: 0x%llu %u %u\n", +				tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr), +				le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]); +			vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); +			dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT; + +			len -= buf_size; +			buf_offset += buf_size; +		}  	}  	ctx->eop_txd = gdesc; @@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb,  	}  } +static int txd_estimate(const struct sk_buff *skb) +{ +	int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1; +	int i; + +	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { +		const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + +		count += VMXNET3_TXD_NEEDED(skb_frag_size(frag)); +	} +	return count; +}  /*   * Transmits a pkt thru a given tq @@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,  	union Vmxnet3_GenericDesc tempTxDesc;  #endif -	/* conservatively estimate # of descriptors to use */ -	count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + -		skb_shinfo(skb)->nr_frags + 1; +	count = txd_estimate(skb);  	ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP)); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 607976c0016..7b4adde93c0 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -816,7 +816,7 @@ static void vxlan_cleanup(unsigned long arg)  				= container_of(p, struct vxlan_fdb, hlist);  			unsigned long timeout; -			if (f->state == NUD_PERMANENT) +			if (f->state & NUD_PERMANENT)  				continue;  			timeout = f->used + vxlan->age_interval * HZ; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 89bf94d4d8a..6f7cf49eff4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = {  static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {  	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ -	{0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, -	{0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, -	{0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, +	{0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +	{0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +	{0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},  	{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},  	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},  	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},  	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},  	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},  	{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, -	{0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, -	{0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, -	{0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, -	{0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, -	{0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, -	{0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, -	{0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, -	{0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, -	{0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, -	{0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, -	{0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, -	{0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, -	{0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, -	{0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, -	{0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, -	{0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83}, -	{0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84}, -	{0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, -	{0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, -	{0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, -	{0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, -	{0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, -	{0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, -	{0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, -	{0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, -	{0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, -	{0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, -	{0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, +	{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, +	{0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, +	{0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, +	{0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, +	{0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, +	{0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, +	{0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, +	{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, +	{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, +	{0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, +	{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, +	{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, +	{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, +	{0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, +	{0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, +	{0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, +	{0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, +	{0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, +	{0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, +	{0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, +	{0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, +	{0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +	{0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +	{0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +	{0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +	{0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +	{0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +	{0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},  	{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},  	{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},  	{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},  	{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, -	{0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202}, -	{0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400}, -	{0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402}, -	{0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404}, -	{0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603}, -	{0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02}, -	{0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04}, -	{0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20}, -	{0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20}, -	{0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22}, -	{0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24}, -	{0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640}, -	{0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660}, -	{0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861}, -	{0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81}, -	{0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83}, -	{0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84}, -	{0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3}, -	{0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5}, -	{0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9}, -	{0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb}, -	{0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, -	{0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, -	{0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, -	{0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, -	{0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, -	{0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, -	{0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, +	{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, +	{0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, +	{0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, +	{0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, +	{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, +	{0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, +	{0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, +	{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, +	{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, +	{0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, +	{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, +	{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, +	{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, +	{0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, +	{0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, +	{0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, +	{0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, +	{0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, +	{0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, +	{0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, +	{0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, +	{0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +	{0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +	{0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +	{0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},  	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},  	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -	{0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, -	{0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, -	{0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, -	{0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, -	{0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, -	{0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, -	{0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, -	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, -	{0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, -	{0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, -	{0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, -	{0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, -	{0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, -	{0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, -	{0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, -	{0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, -	{0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, +	{0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, +	{0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, +	{0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, +	{0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, +	{0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +	{0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +	{0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +	{0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +	{0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +	{0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +	{0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +	{0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},  	{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, -	{0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, -	{0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, -	{0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, +	{0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +	{0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +	{0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},  	{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},  	{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, -	{0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, +	{0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},  	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},  	{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, -	{0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, +	{0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},  	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},  	{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, -	{0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, +	{0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},  	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},  }; diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 924c4616c3d..f5dda84176c 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {  	{ USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */  	{ USB_DEVICE(0x040D, 0x3801) }, /* VIA */  	{ USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ +	{ USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */  	{ USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */  	{ USB_DEVICE(0x0cf3, 0x7015), diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 378bd70256b..741918a2027 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)  	}  	bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); +	bf->bf_next = NULL;  	list_del(&bf->list);  	spin_unlock_bh(&sc->tx.txbuflock); @@ -393,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  	u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;  	u32 ba[WME_BA_BMP_SIZE >> 5];  	int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; -	bool rc_update = true; +	bool rc_update = true, isba;  	struct ieee80211_tx_rate rates[4];  	struct ath_frame_info *fi;  	int nframes; @@ -437,13 +438,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  	tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;  	tid = ATH_AN_2_TID(an, tidno);  	seq_first = tid->seq_start; +	isba = ts->ts_flags & ATH9K_TX_BA;  	/*  	 * The hardware occasionally sends a tx status for the wrong TID.  	 * In this case, the BA status cannot be considered valid and all  	 * subframes need to be retransmitted +	 * +	 * Only BlockAcks have a TID and therefore normal Acks cannot be +	 * checked  	 */ -	if (tidno != ts->tid) +	if (isba && tidno != ts->tid)  		txok = false;  	isaggr = bf_isaggr(bf); @@ -1774,6 +1779,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,  	list_add_tail(&bf->list, &bf_head);  	bf->bf_state.bf_type = 0; +	bf->bf_next = NULL;  	bf->bf_lastbf = bf;  	ath_tx_fill_desc(sc, bf, txq, fi->framelen);  	ath_tx_txqaddbuf(sc, txq, &bf_head, false); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 73730e94e0a..c5a99c8c816 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -5404,6 +5404,8 @@ static void b43_bcma_remove(struct bcma_device *core)  	cancel_work_sync(&wldev->restart_work);  	B43_WARN_ON(!wl); +	if (!wldev->fw.ucode.data) +		return;			/* NULL if firmware never loaded */  	if (wl->current_dev == wldev && wl->hw_registred) {  		b43_leds_stop(wldev);  		ieee80211_unregister_hw(wl->hw); @@ -5478,6 +5480,8 @@ static void b43_ssb_remove(struct ssb_device *sdev)  	cancel_work_sync(&wldev->restart_work);  	B43_WARN_ON(!wl); +	if (!wldev->fw.ucode.data) +		return;			/* NULL if firmware never loaded */  	if (wl->current_dev == wldev && wl->hw_registred) {  		b43_leds_stop(wldev);  		ieee80211_unregister_hw(wl->hw); diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c index 192251adf98..282eedec675 100644 --- a/drivers/net/wireless/b43legacy/pio.c +++ b/drivers/net/wireless/b43legacy/pio.c @@ -382,7 +382,7 @@ static void cancel_transfers(struct b43legacy_pioqueue *queue)  {  	struct b43legacy_pio_txpacket *packet, *tmp_packet; -	tasklet_disable(&queue->txtask); +	tasklet_kill(&queue->txtask);  	list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)  		free_txpacket(packet, 0); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index a2b4b1e7101..7a6dfdc67b6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -1339,7 +1339,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,  	}  	ret = brcmf_bus_start(dev); -	if (ret == -ENOLINK) { +	if (ret) {  		brcmf_dbg(ERROR, "dongle is not responding\n");  		brcmf_detach(dev);  		goto fail; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index c1abaa6db59..a6f1e816600 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -3569,7 +3569,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,  	if (!request || !request->n_ssids || !request->n_match_sets) {  		WL_ERR("Invalid sched scan req!! n_ssids:%d\n", -		       request->n_ssids); +		       request ? request->n_ssids : 0);  		return -EINVAL;  	} @@ -3972,7 +3972,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,  	u8  *iovar_ie_buf;  	u8  *curr_ie_buf;  	u8  *mgmt_ie_buf = NULL; -	u32 mgmt_ie_buf_len = 0; +	int mgmt_ie_buf_len;  	u32 *mgmt_ie_len = 0;  	u32 del_add_ie_buf_len = 0;  	u32 total_ie_buf_len = 0; @@ -3982,7 +3982,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,  	struct parsed_vndr_ie_info *vndrie_info;  	s32 i;  	u8 *ptr; -	u32 remained_buf_len; +	int remained_buf_len;  	WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag);  	iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); @@ -4606,12 +4606,13 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,  	struct brcmf_cfg80211_profile *profile = cfg->profile;  	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);  	struct wiphy *wiphy = cfg_to_wiphy(cfg); -	struct brcmf_channel_info_le channel_le; -	struct ieee80211_channel *notify_channel; +	struct ieee80211_channel *notify_channel = NULL;  	struct ieee80211_supported_band *band; +	struct brcmf_bss_info_le *bi;  	u32 freq;  	s32 err = 0;  	u32 target_channel; +	u8 *buf;  	WL_TRACE("Enter\n"); @@ -4619,11 +4620,22 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,  	memcpy(profile->bssid, e->addr, ETH_ALEN);  	brcmf_update_bss_info(cfg); -	brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le, -			sizeof(channel_le)); +	buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); +	if (buf == NULL) { +		err = -ENOMEM; +		goto done; +	} + +	/* data sent to dongle has to be little endian */ +	*(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); +	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); + +	if (err) +		goto done; -	target_channel = le32_to_cpu(channel_le.target_channel); -	WL_CONN("Roamed to channel %d\n", target_channel); +	bi = (struct brcmf_bss_info_le *)(buf + 4); +	target_channel = bi->ctl_ch ? bi->ctl_ch : +				      CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));  	if (target_channel <= CH_MAX_2G_CHANNEL)  		band = wiphy->bands[IEEE80211_BAND_2GHZ]; @@ -4633,6 +4645,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,  	freq = ieee80211_channel_to_frequency(target_channel, band->band);  	notify_channel = ieee80211_get_channel(wiphy, freq); +done: +	kfree(buf);  	cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid,  			conn_info->req_ie, conn_info->req_ie_len,  			conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); @@ -5186,41 +5200,6 @@ brcmf_cfg80211_event(struct net_device *ndev,  		schedule_work(&cfg->event_work);  } -static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype) -{ -	s32 infra = 0; -	s32 err = 0; - -	switch (iftype) { -	case NL80211_IFTYPE_MONITOR: -	case NL80211_IFTYPE_WDS: -		WL_ERR("type (%d) : currently we do not support this mode\n", -		       iftype); -		err = -EINVAL; -		return err; -	case NL80211_IFTYPE_ADHOC: -		infra = 0; -		break; -	case NL80211_IFTYPE_STATION: -		infra = 1; -		break; -	case NL80211_IFTYPE_AP: -		infra = 1; -		break; -	default: -		err = -EINVAL; -		WL_ERR("invalid type (%d)\n", iftype); -		return err; -	} -	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); -	if (err) { -		WL_ERR("WLC_SET_INFRA error (%d)\n", err); -		return err; -	} - -	return 0; -} -  static s32 brcmf_dongle_eventmsg(struct net_device *ndev)  {  	/* Room for "event_msgs" + '\0' + bitvec */ @@ -5439,7 +5418,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)  				WL_BEACON_TIMEOUT);  	if (err)  		goto default_conf_out; -	err = brcmf_dongle_mode(ndev, wdev->iftype); +	err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, +					  NULL, NULL);  	if (err && err != -EINPROGRESS)  		goto default_conf_out;  	err = brcmf_dongle_probecap(cfg); diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 935120fc8c9..768bf612533 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -10472,7 +10472,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,  		} else  			len = src->len; -		dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC); +		dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC);  		if (!dst)  			continue; diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index 349c205d5f6..da586206419 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c @@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,  	 * See iwlagn_mac_channel_switch.  	 */  	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; -	struct iwl6000_channel_switch_cmd cmd; +	struct iwl6000_channel_switch_cmd *cmd;  	u32 switch_time_in_usec, ucode_switch_time;  	u16 ch;  	u32 tsf_low; @@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,  	struct ieee80211_vif *vif = ctx->vif;  	struct iwl_host_cmd hcmd = {  		.id = REPLY_CHANNEL_SWITCH, -		.len = { sizeof(cmd), }, +		.len = { sizeof(*cmd), },  		.flags = CMD_SYNC, -		.data = { &cmd, }, +		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,  	}; +	int err; -	cmd.band = priv->band == IEEE80211_BAND_2GHZ; +	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); +	if (!cmd) +		return -ENOMEM; + +	hcmd.data[0] = cmd; + +	cmd->band = priv->band == IEEE80211_BAND_2GHZ;  	ch = ch_switch->channel->hw_value;  	IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",  		      ctx->active.channel, ch); -	cmd.channel = cpu_to_le16(ch); -	cmd.rxon_flags = ctx->staging.flags; -	cmd.rxon_filter_flags = ctx->staging.filter_flags; +	cmd->channel = cpu_to_le16(ch); +	cmd->rxon_flags = ctx->staging.flags; +	cmd->rxon_filter_flags = ctx->staging.filter_flags;  	switch_count = ch_switch->count;  	tsf_low = ch_switch->timestamp & 0x0ffffffff;  	/* @@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,  			switch_count = 0;  	}  	if (switch_count <= 1) -		cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); +		cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time);  	else {  		switch_time_in_usec =  			vif->bss_conf.beacon_int * switch_count * TIME_UNIT;  		ucode_switch_time = iwl_usecs_to_beacons(priv,  							 switch_time_in_usec,  							 beacon_interval); -		cmd.switch_time = iwl_add_beacon_time(priv, -						      priv->ucode_beacon_time, -						      ucode_switch_time, -						      beacon_interval); +		cmd->switch_time = iwl_add_beacon_time(priv, +						       priv->ucode_beacon_time, +						       ucode_switch_time, +						       beacon_interval);  	}  	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", -		      cmd.switch_time); -	cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; +		      cmd->switch_time); +	cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; -	return iwl_dvm_send_cmd(priv, &hcmd); +	err = iwl_dvm_send_cmd(priv, &hcmd); +	kfree(cmd); +	return err;  }  struct iwl_lib_ops iwl6000_lib = { diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 0679458a1ba..780d3e16829 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1825,8 +1825,6 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,  		return -EBUSY;  	} -	priv->scan_request = request; -  	priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),  				      GFP_KERNEL);  	if (!priv->user_scan_cfg) { @@ -1834,6 +1832,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,  		return -ENOMEM;  	} +	priv->scan_request = request; +  	priv->user_scan_cfg->num_ssids = request->n_ssids;  	priv->user_scan_cfg->ssid_list = request->ssids; @@ -1870,6 +1870,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,  	ret = mwifiex_scan_networks(priv, priv->user_scan_cfg);  	if (ret) {  		dev_err(priv->adapter->dev, "scan failed: %d\n", ret); +		priv->scan_request = NULL; +		kfree(priv->user_scan_cfg); +		priv->user_scan_cfg = NULL;  		return ret;  	} diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 00b658d3b6e..9171aaedbcc 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1843,21 +1843,18 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,  				      struct cfg80211_ssid *req_ssid)  {  	struct mwifiex_adapter *adapter = priv->adapter; -	int ret = 0; +	int ret;  	struct mwifiex_user_scan_cfg *scan_cfg; -	if (!req_ssid) -		return -1; -  	if (adapter->scan_processing) { -		dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); -		return ret; +		dev_err(adapter->dev, "cmd: Scan already in process...\n"); +		return -EBUSY;  	}  	if (priv->scan_block) { -		dev_dbg(adapter->dev, +		dev_err(adapter->dev,  			"cmd: Scan is blocked during association...\n"); -		return ret; +		return -EBUSY;  	}  	scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index a12e84f892b..6b2e1e431dd 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = {  	.disconnect	= rt2x00usb_disconnect,  	.suspend	= rt2x00usb_suspend,  	.resume		= rt2x00usb_resume, +	.reset_resume	= rt2x00usb_resume,  	.disable_hub_initiated_lpm = 1,  }; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 01dc8891070..59474ae0aec 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2449,7 +2449,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)  	/*  	 * Check if temperature compensation is supported.  	 */ -	if (tssi_bounds[4] == 0xff) +	if (tssi_bounds[4] == 0xff || step == 0xff)  		return 0;  	/* diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index c9e9370eb78..3b8fb5a603f 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = {  	.disconnect	= rt2x00usb_disconnect,  	.suspend	= rt2x00usb_suspend,  	.resume		= rt2x00usb_resume, +	.reset_resume	= rt2x00usb_resume,  	.disable_hub_initiated_lpm = 1,  }; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index e5eb43b3eee..24eec66e9fd 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = {  	.disconnect	= rt2x00usb_disconnect,  	.suspend	= rt2x00usb_suspend,  	.resume		= rt2x00usb_resume, +	.reset_resume	= rt2x00usb_resume,  	.disable_hub_initiated_lpm = 1,  }; diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 030beb45d8b..e3ea4b34688 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -673,7 +673,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw)  		set_hal_start(rtlhal);  		/* Start bulk IN */ -		_rtl_usb_receive(hw); +		err = _rtl_usb_receive(hw);  	}  	return err; diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 6241fd05bd4..a543746fb35 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -320,10 +320,7 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),  		} else  			next = dev->bus_list.next; -		/* Run device routines with the device locked */ -		device_lock(&dev->dev);  		retval = cb(dev, userdata); -		device_unlock(&dev->dev);  		if (retval)  			break;  	} diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 94c6e2aa03d..6c94fc9489e 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -398,6 +398,8 @@ static void pci_device_shutdown(struct device *dev)  	struct pci_dev *pci_dev = to_pci_dev(dev);  	struct pci_driver *drv = pci_dev->driver; +	pm_runtime_resume(dev); +  	if (drv && drv->shutdown)  		drv->shutdown(pci_dev);  	pci_msi_shutdown(pci_dev); @@ -408,16 +410,6 @@ static void pci_device_shutdown(struct device *dev)  	 * continue to do DMA  	 */  	pci_disable_device(pci_dev); - -	/* -	 * Devices may be enabled to wake up by runtime PM, but they need not -	 * be supposed to wake up the system from its "power off" state (e.g. -	 * ACPI S5).  Therefore disable wakeup for all devices that aren't -	 * supposed to wake up the system at this point.  The state argument -	 * will be ignored by pci_enable_wake(). -	 */ -	if (!device_may_wakeup(dev)) -		pci_enable_wake(pci_dev, PCI_UNKNOWN, false);  }  #ifdef CONFIG_PM diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 02d107b1528..f39378d9da1 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -458,40 +458,6 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)  }  struct device_attribute vga_attr = __ATTR_RO(boot_vga); -static void -pci_config_pm_runtime_get(struct pci_dev *pdev) -{ -	struct device *dev = &pdev->dev; -	struct device *parent = dev->parent; - -	if (parent) -		pm_runtime_get_sync(parent); -	pm_runtime_get_noresume(dev); -	/* -	 * pdev->current_state is set to PCI_D3cold during suspending, -	 * so wait until suspending completes -	 */ -	pm_runtime_barrier(dev); -	/* -	 * Only need to resume devices in D3cold, because config -	 * registers are still accessible for devices suspended but -	 * not in D3cold. -	 */ -	if (pdev->current_state == PCI_D3cold) -		pm_runtime_resume(dev); -} - -static void -pci_config_pm_runtime_put(struct pci_dev *pdev) -{ -	struct device *dev = &pdev->dev; -	struct device *parent = dev->parent; - -	pm_runtime_put(dev); -	if (parent) -		pm_runtime_put_sync(parent); -} -  static ssize_t  pci_read_config(struct file *filp, struct kobject *kobj,  		struct bin_attribute *bin_attr, diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 54858838f09..aabf64798bd 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1858,6 +1858,38 @@ bool pci_dev_run_wake(struct pci_dev *dev)  }  EXPORT_SYMBOL_GPL(pci_dev_run_wake); +void pci_config_pm_runtime_get(struct pci_dev *pdev) +{ +	struct device *dev = &pdev->dev; +	struct device *parent = dev->parent; + +	if (parent) +		pm_runtime_get_sync(parent); +	pm_runtime_get_noresume(dev); +	/* +	 * pdev->current_state is set to PCI_D3cold during suspending, +	 * so wait until suspending completes +	 */ +	pm_runtime_barrier(dev); +	/* +	 * Only need to resume devices in D3cold, because config +	 * registers are still accessible for devices suspended but +	 * not in D3cold. +	 */ +	if (pdev->current_state == PCI_D3cold) +		pm_runtime_resume(dev); +} + +void pci_config_pm_runtime_put(struct pci_dev *pdev) +{ +	struct device *dev = &pdev->dev; +	struct device *parent = dev->parent; + +	pm_runtime_put(dev); +	if (parent) +		pm_runtime_put_sync(parent); +} +  /**   * pci_pm_init - Initialize PM functions of given PCI device   * @dev: PCI device to handle. diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index bacbcba69cf..fd92aab9904 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(struct pci_dev *dev);  extern int pci_finish_runtime_suspend(struct pci_dev *dev);  extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);  extern void pci_wakeup_bus(struct pci_bus *bus); +extern void pci_config_pm_runtime_get(struct pci_dev *dev); +extern void pci_config_pm_runtime_put(struct pci_dev *dev);  extern void pci_pm_init(struct pci_dev *dev);  extern void platform_pci_wakeup_init(struct pci_dev *dev);  extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 06bad96af41..af4e31cd3a3 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -213,6 +213,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)  	struct aer_broadcast_data *result_data;  	result_data = (struct aer_broadcast_data *) data; +	device_lock(&dev->dev);  	dev->error_state = result_data->state;  	if (!dev->driver || @@ -231,12 +232,14 @@ static int report_error_detected(struct pci_dev *dev, void *data)  				   dev->driver ?  				   "no AER-aware driver" : "no driver");  		} -		return 0; +		goto out;  	}  	err_handler = dev->driver->err_handler;  	vote = err_handler->error_detected(dev, result_data->state);  	result_data->result = merge_result(result_data->result, vote); +out: +	device_unlock(&dev->dev);  	return 0;  } @@ -247,14 +250,17 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data)  	struct aer_broadcast_data *result_data;  	result_data = (struct aer_broadcast_data *) data; +	device_lock(&dev->dev);  	if (!dev->driver ||  		!dev->driver->err_handler ||  		!dev->driver->err_handler->mmio_enabled) -		return 0; +		goto out;  	err_handler = dev->driver->err_handler;  	vote = err_handler->mmio_enabled(dev);  	result_data->result = merge_result(result_data->result, vote); +out: +	device_unlock(&dev->dev);  	return 0;  } @@ -265,14 +271,17 @@ static int report_slot_reset(struct pci_dev *dev, void *data)  	struct aer_broadcast_data *result_data;  	result_data = (struct aer_broadcast_data *) data; +	device_lock(&dev->dev);  	if (!dev->driver ||  		!dev->driver->err_handler ||  		!dev->driver->err_handler->slot_reset) -		return 0; +		goto out;  	err_handler = dev->driver->err_handler;  	vote = err_handler->slot_reset(dev);  	result_data->result = merge_result(result_data->result, vote); +out: +	device_unlock(&dev->dev);  	return 0;  } @@ -280,15 +289,18 @@ static int report_resume(struct pci_dev *dev, void *data)  {  	const struct pci_error_handlers *err_handler; +	device_lock(&dev->dev);  	dev->error_state = pci_channel_io_normal;  	if (!dev->driver ||  		!dev->driver->err_handler ||  		!dev->driver->err_handler->resume) -		return 0; +		goto out;  	err_handler = dev->driver->err_handler;  	err_handler->resume(dev); +out: +	device_unlock(&dev->dev);  	return 0;  } diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index d03a7a39b2d..ed129b41462 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -272,7 +272,8 @@ static int get_port_device_capability(struct pci_dev *dev)  	}  	/* Hot-Plug Capable */ -	if (cap_mask & PCIE_PORT_SERVICE_HP) { +	if ((cap_mask & PCIE_PORT_SERVICE_HP) && +	    dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT) {  		pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, ®32);  		if (reg32 & PCI_EXP_SLTCAP_HPC) {  			services |= PCIE_PORT_SERVICE_HP; diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index eb907a8faf2..9b8505ccc56 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp  	if (!access_ok(VERIFY_WRITE, buf, cnt))  		return -EINVAL; +	pci_config_pm_runtime_get(dev); +  	if ((pos & 1) && cnt) {  		unsigned char val;  		pci_user_read_config_byte(dev, pos, &val); @@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp  		cnt--;  	} +	pci_config_pm_runtime_put(dev); +  	*ppos = pos;  	return nbytes;  } @@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof  	if (!access_ok(VERIFY_READ, buf, cnt))  		return -EINVAL; +	pci_config_pm_runtime_get(dev); +  	if ((pos & 1) && cnt) {  		unsigned char val;  		__get_user(val, buf); @@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof  		cnt--;  	} +	pci_config_pm_runtime_put(dev); +  	*ppos = pos;  	i_size_write(ino, dp->size);  	return nbytes; diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 7bf914df6e9..d96caefd914 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -179,11 +179,13 @@ config PINCTRL_COH901  config PINCTRL_SAMSUNG  	bool "Samsung pinctrl driver" +	depends on OF && GPIOLIB  	select PINMUX  	select PINCONF  config PINCTRL_EXYNOS4  	bool "Pinctrl driver data for Exynos4 SoC" +	depends on OF && GPIOLIB  	select PINCTRL_SAMSUNG  config PINCTRL_MVEBU diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 0f1ec9e8ff1..2e39c04fc16 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -1061,8 +1061,10 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)  			seq_printf(s, "group: %s\n", gname);  			for (i = 0; i < num_pins; i++) {  				pname = pin_get_name(pctldev, pins[i]); -				if (WARN_ON(!pname)) +				if (WARN_ON(!pname)) { +					mutex_unlock(&pinctrl_mutex);  					return -EINVAL; +				}  				seq_printf(s, "pin %d (%s)\n", pins[i], pname);  			}  			seq_puts(s, "\n"); diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 43f474cdc11..baee2cc46a1 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -537,8 +537,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what)  	seq_puts(s, "Pin config settings per pin group\n");  	seq_puts(s, "Format: group (name): configs\n"); -	mutex_lock(&pinctrl_mutex); -  	while (selector < ngroups) {  		const char *gname = pctlops->get_group_name(pctldev, selector); @@ -549,8 +547,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what)  		selector++;  	} -	mutex_unlock(&pinctrl_mutex); -  	return 0;  } diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 01aea1c3b5f..cf82d9ce4de 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -1056,7 +1056,7 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)  	struct nmk_gpio_chip *nmk_chip =  		container_of(chip, struct nmk_gpio_chip, chip); -	return irq_find_mapping(nmk_chip->domain, offset); +	return irq_create_mapping(nmk_chip->domain, offset);  }  #ifdef CONFIG_DEBUG_FS @@ -1281,7 +1281,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)  	struct clk *clk;  	int secondary_irq;  	void __iomem *base; -	int irq_start = -1; +	int irq_start = 0;  	int irq;  	int ret; @@ -1387,7 +1387,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)  	if (!np)  		irq_start = NOMADIK_GPIO_TO_IRQ(pdata->first_gpio); -	nmk_chip->domain = irq_domain_add_simple(NULL, +	nmk_chip->domain = irq_domain_add_simple(np,  				NMK_GPIO_PER_CHIP, irq_start,  				&nmk_gpio_irq_simple_ops, nmk_chip);  	if (!nmk_chip->domain) { diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c index 729b686c3ad..7da0b371fd6 100644 --- a/drivers/pinctrl/pinctrl-tegra.c +++ b/drivers/pinctrl/pinctrl-tegra.c @@ -464,7 +464,7 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,  		*bank = g->drv_bank;  		*reg = g->drv_reg;  		*bit = g->lpmd_bit; -		*width = 1; +		*width = 2;  		break;  	case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH:  		*bank = g->drv_bank; diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c index 0386fdf0da1..7894f14c705 100644 --- a/drivers/pinctrl/pinctrl-tegra30.c +++ b/drivers/pinctrl/pinctrl-tegra30.c @@ -3345,10 +3345,10 @@ static const struct tegra_function tegra30_functions[] = {  	FUNCTION(vi_alt3),  }; -#define MUXCTL_REG_A	0x3000 -#define PINGROUP_REG_A	0x868 +#define DRV_PINGROUP_REG_A	0x868	/* bank 0 */ +#define PINGROUP_REG_A		0x3000	/* bank 1 */ -#define PINGROUP_REG_Y(r) ((r) - MUXCTL_REG_A) +#define PINGROUP_REG_Y(r) ((r) - PINGROUP_REG_A)  #define PINGROUP_REG_N(r) -1  #define PINGROUP(pg_name, f0, f1, f2, f3, f_safe, r, od, ior)	\ @@ -3364,25 +3364,25 @@ static const struct tegra_function tegra30_functions[] = {  		},						\  		.func_safe = TEGRA_MUX_ ## f_safe,		\  		.mux_reg = PINGROUP_REG_Y(r),			\ -		.mux_bank = 0,					\ +		.mux_bank = 1,					\  		.mux_bit = 0,					\  		.pupd_reg = PINGROUP_REG_Y(r),			\ -		.pupd_bank = 0,					\ +		.pupd_bank = 1,					\  		.pupd_bit = 2,					\  		.tri_reg = PINGROUP_REG_Y(r),			\ -		.tri_bank = 0,					\ +		.tri_bank = 1,					\  		.tri_bit = 4,					\  		.einput_reg = PINGROUP_REG_Y(r),		\ -		.einput_bank = 0,				\ +		.einput_bank = 1,				\  		.einput_bit = 5,				\  		.odrain_reg = PINGROUP_REG_##od(r),		\ -		.odrain_bank = 0,				\ +		.odrain_bank = 1,				\  		.odrain_bit = 6,				\  		.lock_reg = PINGROUP_REG_Y(r),			\ -		.lock_bank = 0,					\ +		.lock_bank = 1,					\  		.lock_bit = 7,					\  		.ioreset_reg = PINGROUP_REG_##ior(r),		\ -		.ioreset_bank = 0,				\ +		.ioreset_bank = 1,				\  		.ioreset_bit = 8,				\  		.drv_reg = -1,					\  	} @@ -3401,8 +3401,8 @@ static const struct tegra_function tegra30_functions[] = {  		.odrain_reg = -1,				\  		.lock_reg = -1,					\  		.ioreset_reg = -1,				\ -		.drv_reg = ((r) - PINGROUP_REG_A),		\ -		.drv_bank = 1,					\ +		.drv_reg = ((r) - DRV_PINGROUP_REG_A),		\ +		.drv_bank = 0,					\  		.hsm_bit = hsm_b,				\  		.schmitt_bit = schmitt_b,			\  		.lpmd_bit = lpmd_b,				\ diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c index 5d4f44f462f..b1fd6ee33c6 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.c +++ b/drivers/pinctrl/spear/pinctrl-spear.c @@ -244,7 +244,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,  			else  				temp = ~muxreg->val; -			val |= temp; +			val |= muxreg->mask & temp;  			pmx_writel(pmx, val, muxreg->reg);  		}  	} diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c index d6cca8c81b9..0436fc7895d 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1310.c +++ b/drivers/pinctrl/spear/pinctrl-spear1310.c @@ -25,8 +25,8 @@ static const struct pinctrl_pin_desc spear1310_pins[] = {  };  /* registers */ -#define PERIP_CFG					0x32C -	#define MCIF_SEL_SHIFT				3 +#define PERIP_CFG					0x3B0 +	#define MCIF_SEL_SHIFT				5  	#define MCIF_SEL_SD				(0x1 << MCIF_SEL_SHIFT)  	#define MCIF_SEL_CF				(0x2 << MCIF_SEL_SHIFT)  	#define MCIF_SEL_XD				(0x3 << MCIF_SEL_SHIFT) @@ -164,6 +164,10 @@ static const struct pinctrl_pin_desc spear1310_pins[] = {  	#define PMX_SSP0_CS0_MASK			(1 << 29)  	#define PMX_SSP0_CS1_2_MASK			(1 << 30) +#define PAD_DIRECTION_SEL_0				0x65C +#define PAD_DIRECTION_SEL_1				0x660 +#define PAD_DIRECTION_SEL_2				0x664 +  /* combined macros */  #define PMX_GMII_MASK		(PMX_GMIICLK_MASK |			\  				PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK |	\ @@ -237,6 +241,10 @@ static struct spear_muxreg i2c0_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_I2C0_MASK,  		.val = PMX_I2C0_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_I2C0_MASK, +		.val = PMX_I2C0_MASK,  	},  }; @@ -269,6 +277,10 @@ static struct spear_muxreg ssp0_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_SSP0_MASK,  		.val = PMX_SSP0_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_SSP0_MASK, +		.val = PMX_SSP0_MASK,  	},  }; @@ -294,6 +306,10 @@ static struct spear_muxreg ssp0_cs0_muxreg[] = {  		.reg = PAD_FUNCTION_EN_2,  		.mask = PMX_SSP0_CS0_MASK,  		.val = PMX_SSP0_CS0_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_SSP0_CS0_MASK, +		.val = PMX_SSP0_CS0_MASK,  	},  }; @@ -319,6 +335,10 @@ static struct spear_muxreg ssp0_cs1_2_muxreg[] = {  		.reg = PAD_FUNCTION_EN_2,  		.mask = PMX_SSP0_CS1_2_MASK,  		.val = PMX_SSP0_CS1_2_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_SSP0_CS1_2_MASK, +		.val = PMX_SSP0_CS1_2_MASK,  	},  }; @@ -352,6 +372,10 @@ static struct spear_muxreg i2s0_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_I2S0_MASK,  		.val = PMX_I2S0_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_I2S0_MASK, +		.val = PMX_I2S0_MASK,  	},  }; @@ -384,6 +408,10 @@ static struct spear_muxreg i2s1_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_I2S1_MASK,  		.val = PMX_I2S1_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_I2S1_MASK, +		.val = PMX_I2S1_MASK,  	},  }; @@ -418,6 +446,10 @@ static struct spear_muxreg clcd_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_CLCD1_MASK,  		.val = PMX_CLCD1_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_CLCD1_MASK, +		.val = PMX_CLCD1_MASK,  	},  }; @@ -443,6 +475,10 @@ static struct spear_muxreg clcd_high_res_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_CLCD2_MASK,  		.val = PMX_CLCD2_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_CLCD2_MASK, +		.val = PMX_CLCD2_MASK,  	},  }; @@ -461,7 +497,7 @@ static struct spear_pingroup clcd_high_res_pingroup = {  	.nmodemuxs = ARRAY_SIZE(clcd_high_res_modemux),  }; -static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res" }; +static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res_grp" };  static struct spear_function clcd_function = {  	.name = "clcd",  	.groups = clcd_grps, @@ -479,6 +515,14 @@ static struct spear_muxreg arm_gpio_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_EGPIO_1_GRP_MASK,  		.val = PMX_EGPIO_1_GRP_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_EGPIO_0_GRP_MASK, +		.val = PMX_EGPIO_0_GRP_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_EGPIO_1_GRP_MASK, +		.val = PMX_EGPIO_1_GRP_MASK,  	},  }; @@ -511,6 +555,10 @@ static struct spear_muxreg smi_2_chips_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_SMI_MASK,  		.val = PMX_SMI_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_SMI_MASK, +		.val = PMX_SMI_MASK,  	},  }; @@ -539,6 +587,14 @@ static struct spear_muxreg smi_4_chips_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,  		.val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_SMI_MASK, +		.val = PMX_SMI_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK, +		.val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,  	},  }; @@ -573,6 +629,10 @@ static struct spear_muxreg gmii_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_GMII_MASK,  		.val = PMX_GMII_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_GMII_MASK, +		.val = PMX_GMII_MASK,  	},  }; @@ -615,6 +675,18 @@ static struct spear_muxreg rgmii_muxreg[] = {  		.reg = PAD_FUNCTION_EN_2,  		.mask = PMX_RGMII_REG2_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_RGMII_REG0_MASK, +		.val = PMX_RGMII_REG0_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_RGMII_REG1_MASK, +		.val = PMX_RGMII_REG1_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_RGMII_REG2_MASK, +		.val = PMX_RGMII_REG2_MASK,  	},  }; @@ -649,6 +721,10 @@ static struct spear_muxreg smii_0_1_2_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_SMII_0_1_2_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_SMII_0_1_2_MASK, +		.val = PMX_SMII_0_1_2_MASK,  	},  }; @@ -681,6 +757,10 @@ static struct spear_muxreg ras_mii_txclk_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_NFCE2_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_NFCE2_MASK, +		.val = PMX_NFCE2_MASK,  	},  }; @@ -721,6 +801,14 @@ static struct spear_muxreg nand_8bit_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_NAND8BIT_1_MASK,  		.val = PMX_NAND8BIT_1_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_NAND8BIT_0_MASK, +		.val = PMX_NAND8BIT_0_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_NAND8BIT_1_MASK, +		.val = PMX_NAND8BIT_1_MASK,  	},  }; @@ -747,6 +835,10 @@ static struct spear_muxreg nand_16bit_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_NAND16BIT_1_MASK,  		.val = PMX_NAND16BIT_1_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_NAND16BIT_1_MASK, +		.val = PMX_NAND16BIT_1_MASK,  	},  }; @@ -772,6 +864,10 @@ static struct spear_muxreg nand_4_chips_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_NAND_4CHIPS_MASK,  		.val = PMX_NAND_4CHIPS_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_NAND_4CHIPS_MASK, +		.val = PMX_NAND_4CHIPS_MASK,  	},  }; @@ -833,6 +929,10 @@ static struct spear_muxreg keyboard_rowcol6_8_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_KBD_ROWCOL68_MASK,  		.val = PMX_KBD_ROWCOL68_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_KBD_ROWCOL68_MASK, +		.val = PMX_KBD_ROWCOL68_MASK,  	},  }; @@ -866,6 +966,10 @@ static struct spear_muxreg uart0_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_UART0_MASK,  		.val = PMX_UART0_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_UART0_MASK, +		.val = PMX_UART0_MASK,  	},  }; @@ -891,6 +995,10 @@ static struct spear_muxreg uart0_modem_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_UART0_MODEM_MASK,  		.val = PMX_UART0_MODEM_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_UART0_MODEM_MASK, +		.val = PMX_UART0_MODEM_MASK,  	},  }; @@ -923,6 +1031,10 @@ static struct spear_muxreg gpt0_tmr0_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_GPT0_TMR0_MASK,  		.val = PMX_GPT0_TMR0_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_GPT0_TMR0_MASK, +		.val = PMX_GPT0_TMR0_MASK,  	},  }; @@ -948,6 +1060,10 @@ static struct spear_muxreg gpt0_tmr1_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_GPT0_TMR1_MASK,  		.val = PMX_GPT0_TMR1_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_GPT0_TMR1_MASK, +		.val = PMX_GPT0_TMR1_MASK,  	},  }; @@ -980,6 +1096,10 @@ static struct spear_muxreg gpt1_tmr0_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_GPT1_TMR0_MASK,  		.val = PMX_GPT1_TMR0_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_GPT1_TMR0_MASK, +		.val = PMX_GPT1_TMR0_MASK,  	},  }; @@ -1005,6 +1125,10 @@ static struct spear_muxreg gpt1_tmr1_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_GPT1_TMR1_MASK,  		.val = PMX_GPT1_TMR1_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_GPT1_TMR1_MASK, +		.val = PMX_GPT1_TMR1_MASK,  	},  }; @@ -1049,6 +1173,20 @@ static const unsigned mcif_pins[] = { 86, 87, 88, 89, 90, 91, 92, 93, 213, 214,  		.reg = PAD_FUNCTION_EN_2,			\  		.mask = PMX_MCIFALL_2_MASK,			\  		.val = PMX_MCIFALL_2_MASK,			\ +	}, {							\ +		.reg = PAD_DIRECTION_SEL_0,			\ +		.mask = PMX_MCI_DATA8_15_MASK,			\ +		.val = PMX_MCI_DATA8_15_MASK,			\ +	}, {							\ +		.reg = PAD_DIRECTION_SEL_1,			\ +		.mask = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK |	\ +			PMX_NFWPRT2_MASK,			\ +		.val = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK |  \ +			PMX_NFWPRT2_MASK,			\ +	}, {							\ +		.reg = PAD_DIRECTION_SEL_2,			\ +		.mask = PMX_MCIFALL_2_MASK,			\ +		.val = PMX_MCIFALL_2_MASK,			\  	}  /* sdhci device */ @@ -1154,6 +1292,10 @@ static struct spear_muxreg touch_xy_muxreg[] = {  		.reg = PAD_FUNCTION_EN_2,  		.mask = PMX_TOUCH_XY_MASK,  		.val = PMX_TOUCH_XY_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_TOUCH_XY_MASK, +		.val = PMX_TOUCH_XY_MASK,  	},  }; @@ -1187,6 +1329,10 @@ static struct spear_muxreg uart1_dis_i2c_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_I2C0_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_I2C0_MASK, +		.val = PMX_I2C0_MASK,  	},  }; @@ -1213,6 +1359,12 @@ static struct spear_muxreg uart1_dis_sd_muxreg[] = {  		.mask = PMX_MCIDATA1_MASK |  			PMX_MCIDATA2_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_MCIDATA1_MASK | +			PMX_MCIDATA2_MASK, +		.val = PMX_MCIDATA1_MASK | +			PMX_MCIDATA2_MASK,  	},  }; @@ -1246,6 +1398,10 @@ static struct spear_muxreg uart2_3_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_I2S0_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_I2S0_MASK, +		.val = PMX_I2S0_MASK,  	},  }; @@ -1278,6 +1434,10 @@ static struct spear_muxreg uart4_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_I2S0_MASK | PMX_CLCD1_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_I2S0_MASK | PMX_CLCD1_MASK, +		.val = PMX_I2S0_MASK | PMX_CLCD1_MASK,  	},  }; @@ -1310,6 +1470,10 @@ static struct spear_muxreg uart5_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_CLCD1_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_CLCD1_MASK, +		.val = PMX_CLCD1_MASK,  	},  }; @@ -1344,6 +1508,10 @@ static struct spear_muxreg rs485_0_1_tdm_0_1_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_CLCD1_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_CLCD1_MASK, +		.val = PMX_CLCD1_MASK,  	},  }; @@ -1376,6 +1544,10 @@ static struct spear_muxreg i2c_1_2_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_CLCD1_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_CLCD1_MASK, +		.val = PMX_CLCD1_MASK,  	},  }; @@ -1409,6 +1581,10 @@ static struct spear_muxreg i2c3_dis_smi_clcd_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_CLCD1_MASK | PMX_SMI_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_CLCD1_MASK | PMX_SMI_MASK, +		.val = PMX_CLCD1_MASK | PMX_SMI_MASK,  	},  }; @@ -1435,6 +1611,10 @@ static struct spear_muxreg i2c3_dis_sd_i2s0_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK, +		.val = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,  	},  }; @@ -1469,6 +1649,10 @@ static struct spear_muxreg i2c_4_5_dis_smi_muxreg[] = {  		.reg = PAD_FUNCTION_EN_0,  		.mask = PMX_SMI_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_SMI_MASK, +		.val = PMX_SMI_MASK,  	},  }; @@ -1499,6 +1683,14 @@ static struct spear_muxreg i2c4_dis_sd_muxreg[] = {  		.reg = PAD_FUNCTION_EN_2,  		.mask = PMX_MCIDATA5_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_MCIDATA4_MASK, +		.val = PMX_MCIDATA4_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_MCIDATA5_MASK, +		.val = PMX_MCIDATA5_MASK,  	},  }; @@ -1526,6 +1718,12 @@ static struct spear_muxreg i2c5_dis_sd_muxreg[] = {  		.mask = PMX_MCIDATA6_MASK |  			PMX_MCIDATA7_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_MCIDATA6_MASK | +			PMX_MCIDATA7_MASK, +		.val = PMX_MCIDATA6_MASK | +			PMX_MCIDATA7_MASK,  	},  }; @@ -1560,6 +1758,10 @@ static struct spear_muxreg i2c_6_7_dis_kbd_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_KBD_ROWCOL25_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_KBD_ROWCOL25_MASK, +		.val = PMX_KBD_ROWCOL25_MASK,  	},  }; @@ -1587,6 +1789,12 @@ static struct spear_muxreg i2c6_dis_sd_muxreg[] = {  		.mask = PMX_MCIIORDRE_MASK |  			PMX_MCIIOWRWE_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_MCIIORDRE_MASK | +			PMX_MCIIOWRWE_MASK, +		.val = PMX_MCIIORDRE_MASK | +			PMX_MCIIOWRWE_MASK,  	},  }; @@ -1613,6 +1821,12 @@ static struct spear_muxreg i2c7_dis_sd_muxreg[] = {  		.mask = PMX_MCIRESETCF_MASK |  			PMX_MCICS0CE_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_MCIRESETCF_MASK | +			PMX_MCICS0CE_MASK, +		.val = PMX_MCIRESETCF_MASK | +			PMX_MCICS0CE_MASK,  	},  }; @@ -1651,6 +1865,14 @@ static struct spear_muxreg can0_dis_nor_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_NFRSTPWDWN3_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_NFRSTPWDWN2_MASK, +		.val = PMX_NFRSTPWDWN2_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_NFRSTPWDWN3_MASK, +		.val = PMX_NFRSTPWDWN3_MASK,  	},  }; @@ -1677,6 +1899,10 @@ static struct spear_muxreg can0_dis_sd_muxreg[] = {  		.reg = PAD_FUNCTION_EN_2,  		.mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK, +		.val = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,  	},  }; @@ -1711,6 +1937,10 @@ static struct spear_muxreg can1_dis_sd_muxreg[] = {  		.reg = PAD_FUNCTION_EN_2,  		.mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK, +		.val = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,  	},  }; @@ -1737,6 +1967,10 @@ static struct spear_muxreg can1_dis_kbd_muxreg[] = {  		.reg = PAD_FUNCTION_EN_1,  		.mask = PMX_KBD_ROWCOL25_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_KBD_ROWCOL25_MASK, +		.val = PMX_KBD_ROWCOL25_MASK,  	},  }; @@ -1763,29 +1997,64 @@ static struct spear_function can1_function = {  	.ngroups = ARRAY_SIZE(can1_grps),  }; -/* Pad multiplexing for pci device */ -static const unsigned pci_sata_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18, +/* Pad multiplexing for (ras-ip) pci device */ +static const unsigned pci_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18,  	19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,  	37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,  	55, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; -#define PCI_SATA_MUXREG				\ -	{					\ -		.reg = PAD_FUNCTION_EN_0,	\ -		.mask = PMX_MCI_DATA8_15_MASK,	\ -		.val = 0,			\ -	}, {					\ -		.reg = PAD_FUNCTION_EN_1,	\ -		.mask = PMX_PCI_REG1_MASK,	\ -		.val = 0,			\ -	}, {					\ -		.reg = PAD_FUNCTION_EN_2,	\ -		.mask = PMX_PCI_REG2_MASK,	\ -		.val = 0,			\ -	} -/* pad multiplexing for pcie0 device */ +static struct spear_muxreg pci_muxreg[] = { +	{ +		.reg = PAD_FUNCTION_EN_0, +		.mask = PMX_MCI_DATA8_15_MASK, +		.val = 0, +	}, { +		.reg = PAD_FUNCTION_EN_1, +		.mask = PMX_PCI_REG1_MASK, +		.val = 0, +	}, { +		.reg = PAD_FUNCTION_EN_2, +		.mask = PMX_PCI_REG2_MASK, +		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_0, +		.mask = PMX_MCI_DATA8_15_MASK, +		.val = PMX_MCI_DATA8_15_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_PCI_REG1_MASK, +		.val = PMX_PCI_REG1_MASK, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_PCI_REG2_MASK, +		.val = PMX_PCI_REG2_MASK, +	}, +}; + +static struct spear_modemux pci_modemux[] = { +	{ +		.muxregs = pci_muxreg, +		.nmuxregs = ARRAY_SIZE(pci_muxreg), +	}, +}; + +static struct spear_pingroup pci_pingroup = { +	.name = "pci_grp", +	.pins = pci_pins, +	.npins = ARRAY_SIZE(pci_pins), +	.modemuxs = pci_modemux, +	.nmodemuxs = ARRAY_SIZE(pci_modemux), +}; + +static const char *const pci_grps[] = { "pci_grp" }; +static struct spear_function pci_function = { +	.name = "pci", +	.groups = pci_grps, +	.ngroups = ARRAY_SIZE(pci_grps), +}; + +/* pad multiplexing for (fix-part) pcie0 device */  static struct spear_muxreg pcie0_muxreg[] = { -	PCI_SATA_MUXREG,  	{  		.reg = PCIE_SATA_CFG,  		.mask = PCIE_CFG_VAL(0), @@ -1802,15 +2071,12 @@ static struct spear_modemux pcie0_modemux[] = {  static struct spear_pingroup pcie0_pingroup = {  	.name = "pcie0_grp", -	.pins = pci_sata_pins, -	.npins = ARRAY_SIZE(pci_sata_pins),  	.modemuxs = pcie0_modemux,  	.nmodemuxs = ARRAY_SIZE(pcie0_modemux),  }; -/* pad multiplexing for pcie1 device */ +/* pad multiplexing for (fix-part) pcie1 device */  static struct spear_muxreg pcie1_muxreg[] = { -	PCI_SATA_MUXREG,  	{  		.reg = PCIE_SATA_CFG,  		.mask = PCIE_CFG_VAL(1), @@ -1827,15 +2093,12 @@ static struct spear_modemux pcie1_modemux[] = {  static struct spear_pingroup pcie1_pingroup = {  	.name = "pcie1_grp", -	.pins = pci_sata_pins, -	.npins = ARRAY_SIZE(pci_sata_pins),  	.modemuxs = pcie1_modemux,  	.nmodemuxs = ARRAY_SIZE(pcie1_modemux),  }; -/* pad multiplexing for pcie2 device */ +/* pad multiplexing for (fix-part) pcie2 device */  static struct spear_muxreg pcie2_muxreg[] = { -	PCI_SATA_MUXREG,  	{  		.reg = PCIE_SATA_CFG,  		.mask = PCIE_CFG_VAL(2), @@ -1852,22 +2115,20 @@ static struct spear_modemux pcie2_modemux[] = {  static struct spear_pingroup pcie2_pingroup = {  	.name = "pcie2_grp", -	.pins = pci_sata_pins, -	.npins = ARRAY_SIZE(pci_sata_pins),  	.modemuxs = pcie2_modemux,  	.nmodemuxs = ARRAY_SIZE(pcie2_modemux),  }; -static const char *const pci_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp" }; -static struct spear_function pci_function = { -	.name = "pci", -	.groups = pci_grps, -	.ngroups = ARRAY_SIZE(pci_grps), +static const char *const pcie_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp" +}; +static struct spear_function pcie_function = { +	.name = "pci_express", +	.groups = pcie_grps, +	.ngroups = ARRAY_SIZE(pcie_grps),  };  /* pad multiplexing for sata0 device */  static struct spear_muxreg sata0_muxreg[] = { -	PCI_SATA_MUXREG,  	{  		.reg = PCIE_SATA_CFG,  		.mask = SATA_CFG_VAL(0), @@ -1884,15 +2145,12 @@ static struct spear_modemux sata0_modemux[] = {  static struct spear_pingroup sata0_pingroup = {  	.name = "sata0_grp", -	.pins = pci_sata_pins, -	.npins = ARRAY_SIZE(pci_sata_pins),  	.modemuxs = sata0_modemux,  	.nmodemuxs = ARRAY_SIZE(sata0_modemux),  };  /* pad multiplexing for sata1 device */  static struct spear_muxreg sata1_muxreg[] = { -	PCI_SATA_MUXREG,  	{  		.reg = PCIE_SATA_CFG,  		.mask = SATA_CFG_VAL(1), @@ -1909,15 +2167,12 @@ static struct spear_modemux sata1_modemux[] = {  static struct spear_pingroup sata1_pingroup = {  	.name = "sata1_grp", -	.pins = pci_sata_pins, -	.npins = ARRAY_SIZE(pci_sata_pins),  	.modemuxs = sata1_modemux,  	.nmodemuxs = ARRAY_SIZE(sata1_modemux),  };  /* pad multiplexing for sata2 device */  static struct spear_muxreg sata2_muxreg[] = { -	PCI_SATA_MUXREG,  	{  		.reg = PCIE_SATA_CFG,  		.mask = SATA_CFG_VAL(2), @@ -1934,8 +2189,6 @@ static struct spear_modemux sata2_modemux[] = {  static struct spear_pingroup sata2_pingroup = {  	.name = "sata2_grp", -	.pins = pci_sata_pins, -	.npins = ARRAY_SIZE(pci_sata_pins),  	.modemuxs = sata2_modemux,  	.nmodemuxs = ARRAY_SIZE(sata2_modemux),  }; @@ -1957,6 +2210,14 @@ static struct spear_muxreg ssp1_dis_kbd_muxreg[] = {  			PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |  			PMX_NFCE2_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_1, +		.mask = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK | +			PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK | +			PMX_NFCE2_MASK, +		.val = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK | +			PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK | +			PMX_NFCE2_MASK,  	},  }; @@ -1983,6 +2244,12 @@ static struct spear_muxreg ssp1_dis_sd_muxreg[] = {  		.mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |  			PMX_MCICECF_MASK | PMX_MCICEXD_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK | +			PMX_MCICECF_MASK | PMX_MCICEXD_MASK, +		.val = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK | +			PMX_MCICECF_MASK | PMX_MCICEXD_MASK,  	},  }; @@ -2017,6 +2284,12 @@ static struct spear_muxreg gpt64_muxreg[] = {  		.mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK  			| PMX_MCILEDS_MASK,  		.val = 0, +	}, { +		.reg = PAD_DIRECTION_SEL_2, +		.mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK +			| PMX_MCILEDS_MASK, +		.val = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK +			| PMX_MCILEDS_MASK,  	},  }; @@ -2093,6 +2366,7 @@ static struct spear_pingroup *spear1310_pingroups[] = {  	&can0_dis_sd_pingroup,  	&can1_dis_sd_pingroup,  	&can1_dis_kbd_pingroup, +	&pci_pingroup,  	&pcie0_pingroup,  	&pcie1_pingroup,  	&pcie2_pingroup, @@ -2138,6 +2412,7 @@ static struct spear_function *spear1310_functions[] = {  	&can0_function,  	&can1_function,  	&pci_function, +	&pcie_function,  	&sata_function,  	&ssp1_function,  	&gpt64_function, diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c index a0eb057e55b..0606b8cf3f2 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1340.c +++ b/drivers/pinctrl/spear/pinctrl-spear1340.c @@ -213,7 +213,7 @@ static const struct pinctrl_pin_desc spear1340_pins[] = {   * Pad multiplexing for making all pads as gpio's. This is done to override the   * values passed from bootloader and start from scratch.   */ -static const unsigned pads_as_gpio_pins[] = { 251 }; +static const unsigned pads_as_gpio_pins[] = { 12, 88, 89, 251 };  static struct spear_muxreg pads_as_gpio_muxreg[] = {  	{  		.reg = PAD_FUNCTION_EN_1, @@ -1692,7 +1692,43 @@ static struct spear_pingroup clcd_pingroup = {  	.nmodemuxs = ARRAY_SIZE(clcd_modemux),  }; -static const char *const clcd_grps[] = { "clcd_grp" }; +/* Disable cld runtime to save panel damage */ +static struct spear_muxreg clcd_sleep_muxreg[] = { +	{ +		.reg = PAD_SHARED_IP_EN_1, +		.mask = ARM_TRACE_MASK | MIPHY_DBG_MASK, +		.val = 0, +	}, { +		.reg = PAD_FUNCTION_EN_5, +		.mask = CLCD_REG4_MASK | CLCD_AND_ARM_TRACE_REG4_MASK, +		.val = 0x0, +	}, { +		.reg = PAD_FUNCTION_EN_6, +		.mask = CLCD_AND_ARM_TRACE_REG5_MASK, +		.val = 0x0, +	}, { +		.reg = PAD_FUNCTION_EN_7, +		.mask = CLCD_AND_ARM_TRACE_REG6_MASK, +		.val = 0x0, +	}, +}; + +static struct spear_modemux clcd_sleep_modemux[] = { +	{ +		.muxregs = clcd_sleep_muxreg, +		.nmuxregs = ARRAY_SIZE(clcd_sleep_muxreg), +	}, +}; + +static struct spear_pingroup clcd_sleep_pingroup = { +	.name = "clcd_sleep_grp", +	.pins = clcd_pins, +	.npins = ARRAY_SIZE(clcd_pins), +	.modemuxs = clcd_sleep_modemux, +	.nmodemuxs = ARRAY_SIZE(clcd_sleep_modemux), +}; + +static const char *const clcd_grps[] = { "clcd_grp", "clcd_sleep_grp" };  static struct spear_function clcd_function = {  	.name = "clcd",  	.groups = clcd_grps, @@ -1893,6 +1929,7 @@ static struct spear_pingroup *spear1340_pingroups[] = {  	&sdhci_pingroup,  	&cf_pingroup,  	&xd_pingroup, +	&clcd_sleep_pingroup,  	&clcd_pingroup,  	&arm_trace_pingroup,  	&miphy_dbg_pingroup, diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c index 020b1e0bdb3..ca47b0e5078 100644 --- a/drivers/pinctrl/spear/pinctrl-spear320.c +++ b/drivers/pinctrl/spear/pinctrl-spear320.c @@ -2240,6 +2240,10 @@ static struct spear_muxreg pwm2_pin_34_muxreg[] = {  		.mask = PMX_SSP_CS_MASK,  		.val = 0,  	}, { +		.reg = MODE_CONFIG_REG, +		.mask = PMX_PWM_MASK, +		.val = PMX_PWM_MASK, +	}, {  		.reg = IP_SEL_PAD_30_39_REG,  		.mask = PMX_PL_34_MASK,  		.val = PMX_PWM2_PL_34_VAL, @@ -2956,9 +2960,9 @@ static struct spear_function mii2_function = {  };  /* Pad multiplexing for cadence mii 1_2 as smii or rmii device */ -static const unsigned smii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, +static const unsigned rmii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20,  	21, 22, 23, 24, 25, 26, 27 }; -static const unsigned rmii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 }; +static const unsigned smii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 };  static struct spear_muxreg mii0_1_muxreg[] = {  	{  		.reg = PMX_CONFIG_REG, diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.h b/drivers/pinctrl/spear/pinctrl-spear3xx.h index 31f44347f17..7860b36053c 100644 --- a/drivers/pinctrl/spear/pinctrl-spear3xx.h +++ b/drivers/pinctrl/spear/pinctrl-spear3xx.h @@ -15,6 +15,7 @@  #include "pinctrl-spear.h"  /* pad mux declarations */ +#define PMX_PWM_MASK		(1 << 16)  #define PMX_FIRDA_MASK		(1 << 14)  #define PMX_I2C_MASK		(1 << 13)  #define PMX_SSP_CS_MASK		(1 << 12) diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 891cd6c61d0..4eed51044c5 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -392,6 +392,8 @@ static int dryice_rtc_probe(struct platform_device *pdev)  	if (imxdi->ioaddr == NULL)  		return -ENOMEM; +	spin_lock_init(&imxdi->irq_lock); +  	imxdi->irq = platform_get_irq(pdev, 0);  	if (imxdi->irq < 0)  		return imxdi->irq; diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 33bb4d891e1..4af3dfe70ef 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h @@ -112,9 +112,6 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);  extern void css_reiterate_subchannels(void);  void css_update_ssd_info(struct subchannel *sch); -#define __MAX_SUBCHANNEL 65535 -#define __MAX_SSID 3 -  struct channel_subsystem {  	u8 cssid;  	int valid; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index fc916f5d731..fd3143c291c 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1424,7 +1424,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)  	}  	if (device_is_disconnected(cdev))  		return IO_SCH_REPROBE; -	if (cdev->online) +	if (cdev->online && !cdev->private->flags.resuming)  		return IO_SCH_VERIFY;  	if (cdev->private->state == DEV_STATE_NOT_OPER)  		return IO_SCH_UNREG_ATTACH; @@ -1469,12 +1469,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)  		rc = 0;  		goto out_unlock;  	case IO_SCH_VERIFY: -		if (cdev->private->flags.resuming == 1) { -			if (cio_enable_subchannel(sch, (u32)(addr_t)sch)) { -				ccw_device_set_notoper(cdev); -				break; -			} -		}  		/* Trigger path verification. */  		io_subchannel_verify(sch);  		rc = 0; diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c index 199bc679117..65d13e38803 100644 --- a/drivers/s390/cio/idset.c +++ b/drivers/s390/cio/idset.c @@ -125,8 +125,7 @@ int idset_is_empty(struct idset *set)  void idset_add_set(struct idset *to, struct idset *from)  { -	int len = min(__BITOPS_WORDS(to->num_ssid * to->num_id), -		      __BITOPS_WORDS(from->num_ssid * from->num_id)); +	int len = min(to->num_ssid * to->num_id, from->num_ssid * from->num_id);  	bitmap_or(to->bitmap, to->bitmap, from->bitmap, len);  } diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index bd4708a422c..20fd974f903 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -149,6 +149,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)  int  qla24xx_disable_vp(scsi_qla_host_t *vha)  { +	unsigned long flags;  	int ret;  	ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); @@ -156,7 +157,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)  	atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);  	/* Remove port id from vp target map */ +	spin_lock_irqsave(&vha->hw->vport_slock, flags);  	qlt_update_vp_map(vha, RESET_AL_PA); +	spin_unlock_irqrestore(&vha->hw->vport_slock, flags);  	qla2x00_mark_vp_devices_dead(vha);  	atomic_set(&vha->vp_state, VP_FAILED); diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 0e09d8f433d..62aa5584f64 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha,  	int pmap_len;  	fc_port_t *fcport;  	int global_resets; +	unsigned long flags;  retry:  	global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); @@ -625,10 +626,10 @@ retry:  	    sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain,  	    fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id); -	sess->s_id = fcport->d_id; -	sess->loop_id = fcport->loop_id; -	sess->conf_compl_supported = !!(fcport->flags & -	    FCF_CONF_COMP_SUPPORTED); +	spin_lock_irqsave(&ha->hardware_lock, flags); +	ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, +				(fcport->flags & FCF_CONF_COMP_SUPPORTED)); +	spin_unlock_irqrestore(&ha->hardware_lock, flags);  	res = true; @@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess(  				qlt_undelete_sess(sess);  			kref_get(&sess->se_sess->sess_kref); -			sess->s_id = fcport->d_id; -			sess->loop_id = fcport->loop_id; -			sess->conf_compl_supported = !!(fcport->flags & -			    FCF_CONF_COMP_SUPPORTED); +			ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, +						(fcport->flags & FCF_CONF_COMP_SUPPORTED)); +  			if (sess->local && !local)  				sess->local = 0;  			spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess(  	 */  	kref_get(&sess->se_sess->sess_kref); -	sess->conf_compl_supported = !!(fcport->flags & -	    FCF_CONF_COMP_SUPPORTED); +	sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED);  	BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));  	memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); @@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)  			ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,  			    "Reappeared sess %p\n", sess);  		} -		sess->s_id = fcport->d_id; -		sess->loop_id = fcport->loop_id; -		sess->conf_compl_supported = !!(fcport->flags & -		    FCF_CONF_COMP_SUPPORTED); +		ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, +					(fcport->flags & FCF_CONF_COMP_SUPPORTED));  	}  	if (sess && sess->local) { diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 170af157121..bad749561ec 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl {  	int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,  					void *, uint8_t *, uint16_t); +	void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);  	struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,  						const uint16_t);  	struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *, diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 2358c16c4c8..3d74f2f39ae 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg)  				struct tcm_qla2xxx_tpg, se_tpg);  	struct tcm_qla2xxx_lport *lport = tpg->lport; -	return &lport->lport_name[0]; +	return lport->lport_naa_name;  }  static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg) @@ -1457,6 +1457,78 @@ static int tcm_qla2xxx_check_initiator_node_acl(  	return 0;  } +static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id, +				    uint16_t loop_id, bool conf_compl_supported) +{ +	struct qla_tgt *tgt = sess->tgt; +	struct qla_hw_data *ha = tgt->ha; +	struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr; +	struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; +	struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, +			struct tcm_qla2xxx_nacl, se_node_acl); +	u32 key; + + +	if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24) +		pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n", +			sess, +			sess->port_name[0], sess->port_name[1], +			sess->port_name[2], sess->port_name[3], +			sess->port_name[4], sess->port_name[5], +			sess->port_name[6], sess->port_name[7], +			sess->loop_id, loop_id, +			sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, +			s_id.b.domain, s_id.b.area, s_id.b.al_pa); + +	if (sess->loop_id != loop_id) { +		/* +		 * Because we can shuffle loop IDs around and we +		 * update different sessions non-atomically, we might +		 * have overwritten this session's old loop ID +		 * already, and we might end up overwriting some other +		 * session that will be updated later.  So we have to +		 * be extra careful and we can't warn about those things... +		 */ +		if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl) +			lport->lport_loopid_map[sess->loop_id].se_nacl = NULL; + +		lport->lport_loopid_map[loop_id].se_nacl = se_nacl; + +		sess->loop_id = loop_id; +	} + +	if (sess->s_id.b24 != s_id.b24) { +		key = (((u32) sess->s_id.b.domain << 16) | +		       ((u32) sess->s_id.b.area   <<  8) | +		       ((u32) sess->s_id.b.al_pa)); + +		if (btree_lookup32(&lport->lport_fcport_map, key)) +			WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl, +			     "Found wrong se_nacl when updating s_id %x:%x:%x\n", +			     sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); +		else +			WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n", +			     sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); + +		key = (((u32) s_id.b.domain << 16) | +		       ((u32) s_id.b.area   <<  8) | +		       ((u32) s_id.b.al_pa)); + +		if (btree_lookup32(&lport->lport_fcport_map, key)) { +			WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n", +			     s_id.b.domain, s_id.b.area, s_id.b.al_pa); +			btree_update32(&lport->lport_fcport_map, key, se_nacl); +		} else { +			btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC); +		} + +		sess->s_id = s_id; +		nacl->nport_id = key; +	} + +	sess->conf_compl_supported = conf_compl_supported; +} +  /*   * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.   */ @@ -1467,6 +1539,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {  	.free_cmd		= tcm_qla2xxx_free_cmd,  	.free_mcmd		= tcm_qla2xxx_free_mcmd,  	.free_session		= tcm_qla2xxx_free_session, +	.update_sess		= tcm_qla2xxx_update_sess,  	.check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl,  	.find_sess_by_s_id	= tcm_qla2xxx_find_sess_by_s_id,  	.find_sess_by_loop_id	= tcm_qla2xxx_find_sess_by_loop_id, @@ -1534,6 +1607,7 @@ static struct se_wwn *tcm_qla2xxx_make_lport(  	lport->lport_wwpn = wwpn;  	tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN,  				wwpn); +	sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) wwpn);  	ret = tcm_qla2xxx_init_lport(lport);  	if (ret != 0) @@ -1601,6 +1675,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport(  	lport->lport_npiv_wwnn = npiv_wwnn;  	tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0],  			TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); +	sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn);  /* FIXME: tcm_qla2xxx_npiv_make_lport */  	ret = -ENOSYS; diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h index 82549810335..9ba075fe978 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h @@ -61,6 +61,8 @@ struct tcm_qla2xxx_lport {  	u64 lport_npiv_wwnn;  	/* ASCII formatted WWPN for FC Target Lport */  	char lport_name[TCM_QLA2XXX_NAMELEN]; +	/* ASCII formatted naa WWPN for VPD page 83 etc */ +	char lport_naa_name[TCM_QLA2XXX_NAMELEN];  	/* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */  	char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN];  	/* map for fc_port pointers in 24-bit FC Port ID space */ diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index b191dd54920..71fddbc60f1 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -1294,26 +1294,19 @@ static struct scsi_host_template qpti_template = {  static const struct of_device_id qpti_match[];  static int __devinit qpti_sbus_probe(struct platform_device *op)  { -	const struct of_device_id *match; -	struct scsi_host_template *tpnt;  	struct device_node *dp = op->dev.of_node;  	struct Scsi_Host *host;  	struct qlogicpti *qpti;  	static int nqptis;  	const char *fcode; -	match = of_match_device(qpti_match, &op->dev); -	if (!match) -		return -EINVAL; -	tpnt = match->data; -  	/* Sometimes Antares cards come up not completely  	 * setup, and we get a report of a zero IRQ.  	 */  	if (op->archdata.irqs[0] == 0)  		return -ENODEV; -	host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti)); +	host = scsi_host_alloc(&qpti_template, sizeof(struct qlogicpti));  	if (!host)  		return -ENOMEM; @@ -1445,19 +1438,15 @@ static int __devexit qpti_sbus_remove(struct platform_device *op)  static const struct of_device_id qpti_match[] = {  	{  		.name = "ptisp", -		.data = &qpti_template,  	},  	{  		.name = "PTI,ptisp", -		.data = &qpti_template,  	},  	{  		.name = "QLGC,isp", -		.data = &qpti_template,  	},  	{  		.name = "SUNW,isp", -		.data = &qpti_template,  	},  	{},  }; diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index edf1360ab09..86dd04d6bc8 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -323,6 +323,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,  	if (!ret) {  		dev_err(ssp->dev, "DMA transfer timeout\n");  		ret = -ETIMEDOUT; +		dmaengine_terminate_all(ssp->dmach);  		goto err_vmalloc;  	} @@ -480,7 +481,7 @@ static int mxs_spi_transfer_one(struct spi_master *master,  		first = last = 0;  	} -	m->status = 0; +	m->status = status;  	spi_finalize_current_message(master);  	return status; diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 919464102d3..a1db91a99b8 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2186,8 +2186,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)  	printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",  	       adev->res.start, pl022->virtbase); -	pm_runtime_resume(dev); -  	pl022->clk = devm_clk_get(&adev->dev, NULL);  	if (IS_ERR(pl022->clk)) {  		status = PTR_ERR(pl022->clk); @@ -2292,7 +2290,6 @@ pl022_remove(struct amba_device *adev)  	clk_disable(pl022->clk);  	clk_unprepare(pl022->clk); -	pm_runtime_disable(&adev->dev);  	amba_release_regions(adev);  	tasklet_disable(&pl022->pump_transfers);  	spi_unregister_master(pl022->master); diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 4894bde4bbf..30faf6d4ab9 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -147,8 +147,6 @@ struct rspi_data {  	unsigned char spsr;  	/* for dmaengine */ -	struct sh_dmae_slave dma_tx; -	struct sh_dmae_slave dma_rx;  	struct dma_chan *chan_tx;  	struct dma_chan *chan_rx;  	int irq; @@ -663,20 +661,16 @@ static irqreturn_t rspi_irq(int irq, void *_sr)  	return ret;  } -static bool rspi_filter(struct dma_chan *chan, void *filter_param) -{ -	chan->private = filter_param; -	return true; -} - -static void __devinit rspi_request_dma(struct rspi_data *rspi, -				       struct platform_device *pdev) +static int __devinit rspi_request_dma(struct rspi_data *rspi, +				      struct platform_device *pdev)  {  	struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;  	dma_cap_mask_t mask; +	struct dma_slave_config cfg; +	int ret;  	if (!rspi_pd) -		return; +		return 0;	/* The driver assumes no error. */  	rspi->dma_width_16bit = rspi_pd->dma_width_16bit; @@ -684,21 +678,35 @@ static void __devinit rspi_request_dma(struct rspi_data *rspi,  	if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) {  		dma_cap_zero(mask);  		dma_cap_set(DMA_SLAVE, mask); -		rspi->dma_rx.slave_id = rspi_pd->dma_rx_id; -		rspi->chan_rx = dma_request_channel(mask, rspi_filter, -						    &rspi->dma_rx); -		if (rspi->chan_rx) -			dev_info(&pdev->dev, "Use DMA when rx.\n"); +		rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter, +						    (void *)rspi_pd->dma_rx_id); +		if (rspi->chan_rx) { +			cfg.slave_id = rspi_pd->dma_rx_id; +			cfg.direction = DMA_DEV_TO_MEM; +			ret = dmaengine_slave_config(rspi->chan_rx, &cfg); +			if (!ret) +				dev_info(&pdev->dev, "Use DMA when rx.\n"); +			else +				return ret; +		}  	}  	if (rspi_pd->dma_tx_id) {  		dma_cap_zero(mask);  		dma_cap_set(DMA_SLAVE, mask); -		rspi->dma_tx.slave_id = rspi_pd->dma_tx_id; -		rspi->chan_tx = dma_request_channel(mask, rspi_filter, -						    &rspi->dma_tx); -		if (rspi->chan_tx) -			dev_info(&pdev->dev, "Use DMA when tx\n"); +		rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter, +						    (void *)rspi_pd->dma_tx_id); +		if (rspi->chan_tx) { +			cfg.slave_id = rspi_pd->dma_tx_id; +			cfg.direction = DMA_MEM_TO_DEV; +			ret = dmaengine_slave_config(rspi->chan_tx, &cfg); +			if (!ret) +				dev_info(&pdev->dev, "Use DMA when tx\n"); +			else +				return ret; +		}  	} + +	return 0;  }  static void __devexit rspi_release_dma(struct rspi_data *rspi) @@ -788,7 +796,11 @@ static int __devinit rspi_probe(struct platform_device *pdev)  	}  	rspi->irq = irq; -	rspi_request_dma(rspi, pdev); +	ret = rspi_request_dma(rspi, pdev); +	if (ret < 0) { +		dev_err(&pdev->dev, "rspi_request_dma failed.\n"); +		goto error4; +	}  	ret = spi_register_master(master);  	if (ret < 0) { diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 7b0ba92e7e4..5d4610babd8 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -567,7 +567,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,  		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];  		BUG_ON(*page); -		*page = alloc_page(GFP_KERNEL | __GFP_ZERO); +		*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);  		if (*page == NULL) {  			pr_err("binder: %d: binder_alloc_buf failed "  			       "for page at %p\n", proc->pid, page_addr); @@ -2419,14 +2419,38 @@ static void binder_release_work(struct list_head *list)  			struct binder_transaction *t;  			t = container_of(w, struct binder_transaction, work); -			if (t->buffer->target_node && !(t->flags & TF_ONE_WAY)) +			if (t->buffer->target_node && +			    !(t->flags & TF_ONE_WAY)) {  				binder_send_failed_reply(t, BR_DEAD_REPLY); +			} else { +				binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, +					"binder: undelivered transaction %d\n", +					t->debug_id); +				t->buffer->transaction = NULL; +				kfree(t); +				binder_stats_deleted(BINDER_STAT_TRANSACTION); +			}  		} break;  		case BINDER_WORK_TRANSACTION_COMPLETE: { +			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, +				"binder: undelivered TRANSACTION_COMPLETE\n");  			kfree(w);  			binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);  		} break; +		case BINDER_WORK_DEAD_BINDER_AND_CLEAR: +		case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: { +			struct binder_ref_death *death; + +			death = container_of(w, struct binder_ref_death, work); +			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, +				"binder: undelivered death notification, %p\n", +				death->cookie); +			kfree(death); +			binder_stats_deleted(BINDER_STAT_DEATH); +		} break;  		default: +			pr_err("binder: unexpected work type, %d, not freed\n", +			       w->type);  			break;  		}  	} @@ -2899,6 +2923,7 @@ static void binder_deferred_release(struct binder_proc *proc)  		nodes++;  		rb_erase(&node->rb_node, &proc->nodes);  		list_del_init(&node->work.entry); +		binder_release_work(&node->async_todo);  		if (hlist_empty(&node->refs)) {  			kfree(node);  			binder_stats_deleted(BINDER_STAT_NODE); @@ -2937,6 +2962,7 @@ static void binder_deferred_release(struct binder_proc *proc)  		binder_delete_ref(ref);  	}  	binder_release_work(&proc->todo); +	binder_release_work(&proc->delivered_death);  	buffers = 0;  	while ((n = rb_first(&proc->allocated_buffers))) { diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index 7dff3c01dc2..d00aff6671d 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -289,6 +289,8 @@ static void pci_8255_detach(struct comedi_device *dev)  	struct comedi_subdevice *s;  	int i; +	if (!board || !devpriv) +		return;  	if (dev->subdevices) {  		for (i = 0; i < board->n_8255; i++) {  			s = &dev->subdevices[i]; diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 08f305210a6..29eb52d11d2 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1410,6 +1410,8 @@ static void dio200_detach(struct comedi_device *dev)  	const struct dio200_layout_struct *layout;  	unsigned n; +	if (!thisboard) +		return;  	if (dev->irq)  		free_irq(dev->irq, dev);  	if (dev->subdevices) { diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index eacb5e4735d..4e4f3c15df8 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -573,9 +573,10 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev,  static void pc236_detach(struct comedi_device *dev)  {  	const struct pc236_board *thisboard = comedi_board(dev); -	struct pc236_private *devpriv = dev->private; -	if (devpriv) +	if (!thisboard) +		return; +	if (dev->iobase)  		pc236_intr_disable(dev);  	if (dev->irq)  		free_irq(dev->irq, dev); diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 60830ccfb90..d0a4c441228 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -323,6 +323,8 @@ static void pc263_detach(struct comedi_device *dev)  {  	const struct pc263_board *thisboard = comedi_board(dev); +	if (!thisboard) +		return;  	if (is_isa_board(thisboard)) {  		if (dev->iobase)  			release_region(dev->iobase, PC263_IO_SIZE); diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 5fd21fa6c1c..c304528cfb1 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -846,6 +846,8 @@ static void __maybe_unused das08_detach(struct comedi_device *dev)  {  	const struct das08_board_struct *thisboard = comedi_board(dev); +	if (!thisboard) +		return;  	das08_common_detach(dev);  	if (is_isa_board(thisboard)) {  		if (dev->iobase) diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 2ba0ade45c6..68d7c6a5db7 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -95,7 +95,7 @@ static int daq700_dio_insn_bits(struct comedi_device *dev,  	}  	data[1] = s->state & 0xff; -	data[1] |= inb(dev->iobase + DIO_R); +	data[1] |= inb(dev->iobase + DIO_R) << 8;  	return insn->n;  } diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 28b91a6c378..b5a19a0863f 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -772,6 +772,8 @@ void labpc_common_detach(struct comedi_device *dev)  {  	struct comedi_subdevice *s; +	if (!thisboard) +		return;  	if (dev->subdevices) {  		s = &dev->subdevices[2];  		subdev_8255_cleanup(dev, s); diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index 8e37d6e0427..b12ca68cd9e 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -310,30 +310,32 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,  	case IIO_CHAN_INFO_SCALE:  		switch (chan->type) {  		case IIO_VOLTAGE: -			*val = 0; -			if (chan->channel == 0) -				*val2 = 1220; -			else -				*val2 = 610; +			if (chan->channel == 0) { +				*val = 1; +				*val2 = 220000; /* 1.22 mV */ +			} else { +				*val = 0; +				*val2 = 610000; /* 0.610 mV */ +			}  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_TEMP: -			*val = 0; -			*val2 = -470000; +			*val = -470; /* 0.47 C */ +			*val2 = 0;  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_ACCEL:  			*val = 0; -			*val2 = 462500; -			return IIO_VAL_INT_PLUS_MICRO; +			*val2 = IIO_G_TO_M_S_2(462400); /* 0.4624 mg */ +			return IIO_VAL_INT_PLUS_NANO;  		case IIO_INCLI:  			*val = 0; -			*val2 = 100000; +			*val2 = 100000; /* 0.1 degree */  			return IIO_VAL_INT_PLUS_MICRO;  		default:  			return -EINVAL;  		}  		break;  	case IIO_CHAN_INFO_OFFSET: -		*val = 25; +		*val = 25000 / -470 - 1278; /* 25 C = 1278 */  		return IIO_VAL_INT;  	case IIO_CHAN_INFO_CALIBBIAS:  		switch (chan->type) { diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index 002fa9dfc37..e7b3441115a 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -316,25 +316,27 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,  	case IIO_CHAN_INFO_SCALE:  		switch (chan->type) {  		case IIO_VOLTAGE: -			*val = 0; -			if (chan->channel == 0) -				*val2 = 1220; -			else -				*val2 = 610; +			if (chan->channel == 0) { +				*val = 1; +				*val2 = 220000; /* 1.22 mV */ +			} else { +				*val = 0; +				*val2 = 610000; /* 0.61 mV */ +			}  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_TEMP: -			*val = 0; -			*val2 = -470000; +			*val = -470; /* -0.47 C */ +			*val2 = 0;  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_INCLI:  			*val = 0; -			*val2 = 25000; +			*val2 = 25000; /* 0.025 degree */  			return IIO_VAL_INT_PLUS_MICRO;  		default:  			return -EINVAL;  		}  	case IIO_CHAN_INFO_OFFSET: -		*val = 25; +		*val = 25000 / -470 - 1278; /* 25 C = 1278 */  		return IIO_VAL_INT;  	case IIO_CHAN_INFO_CALIBBIAS:  		bits = 14; diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index 05bdb7c2c8e..c6234c2f46a 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -317,26 +317,28 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,  	case IIO_CHAN_INFO_SCALE:  		switch (chan->type) {  		case IIO_VOLTAGE: -			*val = 0; -			if (chan->channel == 0) -				*val2 = 1220; -			else -				*val2 = 610; +			if (chan->channel == 0) { +				*val = 1; +				*val2 = 220000; /* 1.22 mV */ +			} else { +				*val = 0; +				*val2 = 610000; /* 0.61 mV */ +			}  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_TEMP: -			*val = 0; -			*val2 = -470000; +			*val = -470; /* 0.47 C */ +			*val2 = 0;  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_ACCEL:  			*val = 0;  			switch (chan->channel2) {  			case IIO_MOD_X:  			case IIO_MOD_ROOT_SUM_SQUARED_X_Y: -				*val2 = 17125; +				*val2 = IIO_G_TO_M_S_2(17125); /* 17.125 mg */  				break;  			case IIO_MOD_Y:  			case IIO_MOD_Z: -				*val2 = 8407; +				*val2 = IIO_G_TO_M_S_2(8407); /* 8.407 mg */  				break;  			}  			return IIO_VAL_INT_PLUS_MICRO; @@ -345,7 +347,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,  		}  		break;  	case IIO_CHAN_INFO_OFFSET: -		*val = 25; +		*val = 25000 / -470 - 1278; /* 25 C = 1278 */  		return IIO_VAL_INT;  	case IIO_CHAN_INFO_CALIBBIAS:  	case IIO_CHAN_INFO_PEAK: diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index b7333bfe0b2..7ee974b45d7 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -343,28 +343,29 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,  		case IIO_VOLTAGE:  			*val = 0;  			if (chan->channel == 0) -				*val2 = 305180; +				*val2 = 305180; /* 0.30518 mV */  			else -				*val2 = 610500; +				*val2 = 610500; /* 0.6105 mV */  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_TEMP: -			*val = 0; -			*val2 = -470000; +			*val = -470; /* -0.47 C */ +			*val2 = 0;  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_ACCEL:  			*val = 0; -			*val2 = 2394; -			return IIO_VAL_INT_PLUS_MICRO; +			*val2 = IIO_G_TO_M_S_2(244140); /* 0.244140 mg */ +			return IIO_VAL_INT_PLUS_NANO;  		case IIO_INCLI: +		case IIO_ROT:  			*val = 0; -			*val2 = 436; +			*val2 = 25000; /* 0.025 degree */  			return IIO_VAL_INT_PLUS_MICRO;  		default:  			return -EINVAL;  		}  		break;  	case IIO_CHAN_INFO_OFFSET: -		*val = 25; +		*val = 25000 / -470 - 0x4FE; /* 25 C = 0x4FE */  		return IIO_VAL_INT;  	case IIO_CHAN_INFO_CALIBBIAS:  		switch (chan->type) { @@ -491,6 +492,7 @@ static const struct iio_chan_spec adis16209_channels[] = {  		.modified = 1,  		.channel2 = IIO_MOD_X,  		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, +		IIO_CHAN_INFO_SCALE_SHARED_BIT,  		.address = rot,  		.scan_index = ADIS16209_SCAN_ROT,  		.scan_type = { diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index c755089c711..eaadd9df3f7 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -486,7 +486,7 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,  		break;  	case IIO_CHAN_INFO_OFFSET:  		if (chan->type == IIO_TEMP) { -			*val = 25; +			*val = 25000 / -470 - 1278; /* 25 C = 1278 */  			return IIO_VAL_INT;  		}  		addrind = 1; @@ -495,19 +495,22 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,  		addrind = 2;  		break;  	case IIO_CHAN_INFO_SCALE: -		*val = 0;  		switch (chan->type) {  		case IIO_TEMP: -			*val2 = -470000; +			*val = -470; /* -0.47 C */ +			*val2 = 0;  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_ACCEL: -			*val2 = 1887042; +			*val2 = IIO_G_TO_M_S_2(19073); /* 19.073 g */  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_VOLTAGE: -			if (chan->channel == 0) -				*val2 = 0012221; -			else /* Should really be dependent on VDD */ -				*val2 = 305; +			if (chan->channel == 0) { +				*val = 1; +				*val2 = 220700; /* 1.2207 mV */ +			} else { +				/* Should really be dependent on VDD */ +				*val2 = 305180; /* 305.18 uV */ +			}  			return IIO_VAL_INT_PLUS_MICRO;  		default:  			return -EINVAL; diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 0fc26a49d68..35e093973d5 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -373,30 +373,31 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,  	case IIO_CHAN_INFO_SCALE:  		switch (chan->type) {  		case IIO_VOLTAGE: -			*val = 0; -			if (chan->channel == 0) -				*val2 = 4880; -			else +			if (chan->channel == 0) { +				*val = 4; +				*val2 = 880000; /* 4.88 mV */ +				return IIO_VAL_INT_PLUS_MICRO; +			} else {  				return -EINVAL; -			return IIO_VAL_INT_PLUS_MICRO; +			}  		case IIO_TEMP: -			*val = 0; -			*val2 = 244000; +			*val = 244; /* 0.244 C */ +			*val2 = 0;  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_ACCEL:  			*val = 0; -			*val2 = 504062; +			*val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */  			return IIO_VAL_INT_PLUS_MICRO;  		default:  			return -EINVAL;  		}  		break;  	case IIO_CHAN_INFO_PEAK_SCALE: -		*val = 6; -		*val2 = 629295; +		*val = 0; +		*val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */  		return IIO_VAL_INT_PLUS_MICRO;  	case IIO_CHAN_INFO_OFFSET: -		*val = 25; +		*val = 25000 / 244 - 0x133; /* 25 C = 0x133 */  		return IIO_VAL_INT;  	case IIO_CHAN_INFO_CALIBBIAS:  		bits = 10; diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index 9571c03aa4c..aa964a2d829 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -498,28 +498,33 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,  		switch (chan->type) {  		case IIO_ANGL_VEL:  			*val = 0; -			if (spi_get_device_id(st->us)->driver_data) -				*val2 = 320; -			else -				*val2 = 1278; +			if (spi_get_device_id(st->us)->driver_data) { +				/* 0.01832 degree / sec */ +				*val2 = IIO_DEGREE_TO_RAD(18320); +			} else { +				/* 0.07326 degree / sec */ +				*val2 = IIO_DEGREE_TO_RAD(73260); +			}  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_VOLTAGE: -			*val = 0; -			if (chan->channel == 0) -				*val2 = 18315; -			else -				*val2 = 610500; +			if (chan->channel == 0) { +				*val = 1; +				*val2 = 831500; /* 1.8315 mV */ +			} else { +				*val = 0; +				*val2 = 610500; /* 610.5 uV */ +			}  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_TEMP: -			*val = 0; -			*val2 = 145300; +			*val = 145; +			*val2 = 300000; /* 0.1453 C */  			return IIO_VAL_INT_PLUS_MICRO;  		default:  			return -EINVAL;  		}  		break;  	case IIO_CHAN_INFO_OFFSET: -		*val = 25; +		*val = 250000 / 1453; /* 25 C = 0x00 */  		return IIO_VAL_INT;  	case IIO_CHAN_INFO_CALIBBIAS:  		switch (chan->type) { diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h index d59d7ac856a..77c601da184 100644 --- a/drivers/staging/iio/imu/adis16400.h +++ b/drivers/staging/iio/imu/adis16400.h @@ -139,6 +139,8 @@ struct adis16400_chip_info {  	const long flags;  	unsigned int gyro_scale_micro;  	unsigned int accel_scale_micro; +	int temp_scale_nano; +	int temp_offset;  	unsigned long default_scan_mask;  }; diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index b302c9ba271..3144a7b1e1c 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -553,10 +553,13 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_VOLTAGE:  			*val = 0; -			if (chan->channel == 0) -				*val2 = 2418; -			else -				*val2 = 806; +			if (chan->channel == 0) { +				*val = 2; +				*val2 = 418000; /* 2.418 mV */ +			} else { +				*val = 0; +				*val2 = 805800; /* 805.8 uV */ +			}  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_ACCEL:  			*val = 0; @@ -564,11 +567,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_MAGN:  			*val = 0; -			*val2 = 500; +			*val2 = 500; /* 0.5 mgauss */  			return IIO_VAL_INT_PLUS_MICRO;  		case IIO_TEMP: -			*val = 0; -			*val2 = 140000; +			*val = st->variant->temp_scale_nano / 1000000; +			*val2 = (st->variant->temp_scale_nano % 1000000);  			return IIO_VAL_INT_PLUS_MICRO;  		default:  			return -EINVAL; @@ -586,9 +589,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,  		return IIO_VAL_INT;  	case IIO_CHAN_INFO_OFFSET:  		/* currently only temperature */ -		*val = 198; -		*val2 = 160000; -		return IIO_VAL_INT_PLUS_MICRO; +		*val = st->variant->temp_offset; +		return IIO_VAL_INT;  	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:  		mutex_lock(&indio_dev->mlock);  		/* Need both the number of taps and the sampling frequency */ @@ -1035,7 +1037,7 @@ static const struct iio_chan_spec adis16334_channels[] = {  		.indexed = 1,  		.channel = 0,  		.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | +		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |  		IIO_CHAN_INFO_SCALE_SHARED_BIT,  		.address = temp0,  		.scan_index = ADIS16400_SCAN_TEMP, @@ -1058,8 +1060,10 @@ static struct adis16400_chip_info adis16400_chips[] = {  	[ADIS16300] = {  		.channels = adis16300_channels,  		.num_channels = ARRAY_SIZE(adis16300_channels), -		.gyro_scale_micro = 873, +		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */  		.accel_scale_micro = 5884, +		.temp_scale_nano = 140000000, /* 0.14 C */ +		.temp_offset = 25000000 / 140000, /* 25 C = 0x00 */  		.default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) |  		(1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) |  		(1 << ADIS16400_SCAN_ACC_Y) | (1 << ADIS16400_SCAN_ACC_Z) | @@ -1070,8 +1074,10 @@ static struct adis16400_chip_info adis16400_chips[] = {  	[ADIS16334] = {  		.channels = adis16334_channels,  		.num_channels = ARRAY_SIZE(adis16334_channels), -		.gyro_scale_micro = 873, -		.accel_scale_micro = 981, +		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ +		.accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ +		.temp_scale_nano = 67850000, /* 0.06785 C */ +		.temp_offset = 25000000 / 67850, /* 25 C = 0x00 */  		.default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) |  		(1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) |  		(1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) | @@ -1080,8 +1086,10 @@ static struct adis16400_chip_info adis16400_chips[] = {  	[ADIS16350] = {  		.channels = adis16350_channels,  		.num_channels = ARRAY_SIZE(adis16350_channels), -		.gyro_scale_micro = 872664, -		.accel_scale_micro = 24732, +		.gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */ +		.accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */ +		.temp_scale_nano = 145300000, /* 0.1453 C */ +		.temp_offset = 25000000 / 145300, /* 25 C = 0x00 */  		.default_scan_mask = 0x7FF,  		.flags = ADIS16400_NO_BURST,  	}, @@ -1090,8 +1098,10 @@ static struct adis16400_chip_info adis16400_chips[] = {  		.num_channels = ARRAY_SIZE(adis16350_channels),  		.flags = ADIS16400_HAS_PROD_ID,  		.product_id = 0x3FE8, -		.gyro_scale_micro = 1279, -		.accel_scale_micro = 24732, +		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ +		.accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ +		.temp_scale_nano = 136000000, /* 0.136 C */ +		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */  		.default_scan_mask = 0x7FF,  	},  	[ADIS16362] = { @@ -1099,8 +1109,10 @@ static struct adis16400_chip_info adis16400_chips[] = {  		.num_channels = ARRAY_SIZE(adis16350_channels),  		.flags = ADIS16400_HAS_PROD_ID,  		.product_id = 0x3FEA, -		.gyro_scale_micro = 1279, -		.accel_scale_micro = 24732, +		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ +		.accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */ +		.temp_scale_nano = 136000000, /* 0.136 C */ +		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */  		.default_scan_mask = 0x7FF,  	},  	[ADIS16364] = { @@ -1108,8 +1120,10 @@ static struct adis16400_chip_info adis16400_chips[] = {  		.num_channels = ARRAY_SIZE(adis16350_channels),  		.flags = ADIS16400_HAS_PROD_ID,  		.product_id = 0x3FEC, -		.gyro_scale_micro = 1279, -		.accel_scale_micro = 24732, +		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ +		.accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ +		.temp_scale_nano = 136000000, /* 0.136 C */ +		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */  		.default_scan_mask = 0x7FF,  	},  	[ADIS16365] = { @@ -1117,8 +1131,10 @@ static struct adis16400_chip_info adis16400_chips[] = {  		.num_channels = ARRAY_SIZE(adis16350_channels),  		.flags = ADIS16400_HAS_PROD_ID,  		.product_id = 0x3FED, -		.gyro_scale_micro = 1279, -		.accel_scale_micro = 24732, +		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ +		.accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ +		.temp_scale_nano = 136000000, /* 0.136 C */ +		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */  		.default_scan_mask = 0x7FF,  	},  	[ADIS16400] = { @@ -1126,9 +1142,11 @@ static struct adis16400_chip_info adis16400_chips[] = {  		.num_channels = ARRAY_SIZE(adis16400_channels),  		.flags = ADIS16400_HAS_PROD_ID,  		.product_id = 0x4015, -		.gyro_scale_micro = 873, -		.accel_scale_micro = 32656, +		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ +		.accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */  		.default_scan_mask = 0xFFF, +		.temp_scale_nano = 140000000, /* 0.14 C */ +		.temp_offset = 25000000 / 140000, /* 25 C = 0x00 */  	}  }; diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index bb8aa70281c..46d6657280b 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -12,6 +12,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include "tpci200.h"  static u16 tpci200_status_timeout[] = { diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c index 3434e6ec014..66e2c2f8a23 100644 --- a/drivers/staging/omapdrm/omap_gem.c +++ b/drivers/staging/omapdrm/omap_gem.c @@ -246,7 +246,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)  	 * DSS, GPU, etc. are not cache coherent:  	 */  	if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { -		addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL); +		addrs = kmalloc(npages * sizeof(*addrs), GFP_KERNEL);  		if (!addrs) {  			ret = -ENOMEM;  			goto free_pages; @@ -257,7 +257,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)  					0, PAGE_SIZE, DMA_BIDIRECTIONAL);  		}  	} else { -		addrs = kzalloc(npages * sizeof(addrs), GFP_KERNEL); +		addrs = kzalloc(npages * sizeof(*addrs), GFP_KERNEL);  		if (!addrs) {  			ret = -ENOMEM;  			goto free_pages; diff --git a/drivers/staging/ramster/Kconfig b/drivers/staging/ramster/Kconfig index 843c5410143..3abf6619dac 100644 --- a/drivers/staging/ramster/Kconfig +++ b/drivers/staging/ramster/Kconfig @@ -18,6 +18,7 @@ config ZCACHE2  config RAMSTER  	bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem"  	depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE2=y +	depends on NET  	# must ensure struct page is 8-byte aligned  	select HAVE_ALIGNED_STRUCT_PAGE if !64_BIT  	default n diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c index 066a3ceec65..f619fb3c56d 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430.c +++ b/drivers/staging/tidspbridge/core/tiomap3430.c @@ -126,7 +126,8 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context,  				  u32 ul_num_bytes,  				  struct hw_mmu_map_attrs_t *hw_attrs); -bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr); +bool wait_for_start(struct bridge_dev_context *dev_context, +			void __iomem *sync_addr);  /*  ----------------------------------- Globals */ @@ -363,10 +364,11 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,  {  	int status = 0;  	struct bridge_dev_context *dev_context = dev_ctxt; -	u32 dw_sync_addr = 0; +	void __iomem *sync_addr;  	u32 ul_shm_base;	/* Gpp Phys SM base addr(byte) */  	u32 ul_shm_base_virt;	/* Dsp Virt SM base addr */  	u32 ul_tlb_base_virt;	/* Base of MMU TLB entry */ +	u32 shm_sync_pa;  	/* Offset of shm_base_virt from tlb_base_virt */  	u32 ul_shm_offset_virt;  	s32 entry_ndx; @@ -397,15 +399,22 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,  	/* Kernel logical address */  	ul_shm_base = dev_context->atlb_entry[0].gpp_va + ul_shm_offset_virt; +	/* SHM physical sync address */ +	shm_sync_pa = dev_context->atlb_entry[0].gpp_pa + ul_shm_offset_virt + +			SHMSYNCOFFSET; +  	/* 2nd wd is used as sync field */ -	dw_sync_addr = ul_shm_base + SHMSYNCOFFSET; +	sync_addr = ioremap(shm_sync_pa, SZ_32); +	if (!sync_addr) +		return -ENOMEM; +  	/* Write a signature into the shm base + offset; this will  	 * get cleared when the DSP program starts. */  	if ((ul_shm_base_virt == 0) || (ul_shm_base == 0)) {  		pr_err("%s: Illegal SM base\n", __func__);  		status = -EPERM;  	} else -		__raw_writel(0xffffffff, dw_sync_addr); +		__raw_writel(0xffffffff, sync_addr);  	if (!status) {  		resources = dev_context->resources; @@ -419,8 +428,10 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,  			 * function is made available.  			 */  			void __iomem *ctrl = ioremap(0x48002000, SZ_4K); -			if (!ctrl) +			if (!ctrl) { +				iounmap(sync_addr);  				return -ENOMEM; +			}  			(*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK,  					OMAP3430_RST1_IVA2_MASK, OMAP3430_IVA2_MOD, @@ -588,15 +599,15 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,  		(*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, 0,  					OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); -		dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", dw_sync_addr); +		dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", *(u32 *)sync_addr);  		dev_dbg(bridge, "DSP c_int00 Address =  0x%x\n", dsp_addr);  		if (dsp_debug) -			while (__raw_readw(dw_sync_addr)) +			while (__raw_readw(sync_addr))  				;  		/* Wait for DSP to clear word in shared memory */  		/* Read the Location */ -		if (!wait_for_start(dev_context, dw_sync_addr)) +		if (!wait_for_start(dev_context, sync_addr))  			status = -ETIMEDOUT;  		dev_get_symbol(dev_context->dev_obj, "_WDT_enable", &wdt_en); @@ -612,7 +623,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,  			/* Write the synchronization bit to indicate the  			 * completion of OPP table update to DSP  			 */ -			__raw_writel(0XCAFECAFE, dw_sync_addr); +			__raw_writel(0XCAFECAFE, sync_addr);  			/* update board state */  			dev_context->brd_state = BRD_RUNNING; @@ -621,6 +632,9 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,  			dev_context->brd_state = BRD_UNKNOWN;  		}  	} + +	iounmap(sync_addr); +  	return status;  } @@ -1796,12 +1810,13 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context,   *  ======== wait_for_start ========   *      Wait for the singal from DSP that it has started, or time out.   */ -bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr) +bool wait_for_start(struct bridge_dev_context *dev_context, +			void __iomem *sync_addr)  {  	u16 timeout = TIHELEN_ACKTIMEOUT;  	/*  Wait for response from board */ -	while (__raw_readw(dw_sync_addr) && --timeout) +	while (__raw_readw(sync_addr) && --timeout)  		udelay(10);  	/*  If timed out: return false */ diff --git a/drivers/staging/tidspbridge/hw/hw_mmu.c b/drivers/staging/tidspbridge/hw/hw_mmu.c index 71cb8229364..50244a47417 100644 --- a/drivers/staging/tidspbridge/hw/hw_mmu.c +++ b/drivers/staging/tidspbridge/hw/hw_mmu.c @@ -48,37 +48,12 @@ enum hw_mmu_page_size_t {  };  /* - * FUNCTION	      : mmu_flush_entry - * - * INPUTS: - * - *       Identifier      : base_address - *       Type		: const u32 - *       Description     : Base Address of instance of MMU module - * - * RETURNS: - * - *       Type		: hw_status - *       Description     : 0		 -- No errors occurred - *			 RET_BAD_NULL_PARAM     -- A Pointer - *						Parameter was set to NULL - * - * PURPOSE:	      : Flush the TLB entry pointed by the - *			lock counter register - *			even if this entry is set protected - * - * METHOD:	       : Check the Input parameter and Flush a - *			 single entry in the TLB. - */ -static hw_status mmu_flush_entry(const void __iomem *base_address); - -/*   * FUNCTION	      : mmu_set_cam_entry   *   * INPUTS:   *   *       Identifier      : base_address - *       TypE		: const u32 + *       Type		 : void __iomem *   *       Description     : Base Address of instance of MMU module   *   *       Identifier      : page_sz @@ -112,7 +87,7 @@ static hw_status mmu_flush_entry(const void __iomem *base_address);   *   * METHOD:	       	: Check the Input parameters and set the CAM entry.   */ -static hw_status mmu_set_cam_entry(const void __iomem *base_address, +static hw_status mmu_set_cam_entry(void __iomem *base_address,  				   const u32 page_sz,  				   const u32 preserved_bit,  				   const u32 valid_bit, @@ -124,7 +99,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,   * INPUTS:   *   *       Identifier      : base_address - *       Type	    	: const u32 + *       Type		 : void __iomem *   *       Description     : Base Address of instance of MMU module   *   *       Identifier      : physical_addr @@ -157,7 +132,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,   *   * METHOD:	       : Check the Input parameters and set the RAM entry.   */ -static hw_status mmu_set_ram_entry(const void __iomem *base_address, +static hw_status mmu_set_ram_entry(void __iomem *base_address,  				   const u32 physical_addr,  				   enum hw_endianism_t endianism,  				   enum hw_element_size_t element_size, @@ -165,7 +140,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address,  /* HW FUNCTIONS */ -hw_status hw_mmu_enable(const void __iomem *base_address) +hw_status hw_mmu_enable(void __iomem *base_address)  {  	hw_status status = 0; @@ -174,7 +149,7 @@ hw_status hw_mmu_enable(const void __iomem *base_address)  	return status;  } -hw_status hw_mmu_disable(const void __iomem *base_address) +hw_status hw_mmu_disable(void __iomem *base_address)  {  	hw_status status = 0; @@ -183,7 +158,7 @@ hw_status hw_mmu_disable(const void __iomem *base_address)  	return status;  } -hw_status hw_mmu_num_locked_set(const void __iomem *base_address, +hw_status hw_mmu_num_locked_set(void __iomem *base_address,  				u32 num_locked_entries)  {  	hw_status status = 0; @@ -193,7 +168,7 @@ hw_status hw_mmu_num_locked_set(const void __iomem *base_address,  	return status;  } -hw_status hw_mmu_victim_num_set(const void __iomem *base_address, +hw_status hw_mmu_victim_num_set(void __iomem *base_address,  				u32 victim_entry_num)  {  	hw_status status = 0; @@ -203,7 +178,7 @@ hw_status hw_mmu_victim_num_set(const void __iomem *base_address,  	return status;  } -hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask) +hw_status hw_mmu_event_ack(void __iomem *base_address, u32 irq_mask)  {  	hw_status status = 0; @@ -212,7 +187,7 @@ hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask)  	return status;  } -hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask) +hw_status hw_mmu_event_disable(void __iomem *base_address, u32 irq_mask)  {  	hw_status status = 0;  	u32 irq_reg; @@ -224,7 +199,7 @@ hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask)  	return status;  } -hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask) +hw_status hw_mmu_event_enable(void __iomem *base_address, u32 irq_mask)  {  	hw_status status = 0;  	u32 irq_reg; @@ -236,7 +211,7 @@ hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask)  	return status;  } -hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask) +hw_status hw_mmu_event_status(void __iomem *base_address, u32 *irq_mask)  {  	hw_status status = 0; @@ -245,7 +220,7 @@ hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask)  	return status;  } -hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr) +hw_status hw_mmu_fault_addr_read(void __iomem *base_address, u32 *addr)  {  	hw_status status = 0; @@ -255,7 +230,7 @@ hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr)  	return status;  } -hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr) +hw_status hw_mmu_ttb_set(void __iomem *base_address, u32 ttb_phys_addr)  {  	hw_status status = 0;  	u32 load_ttb; @@ -267,7 +242,7 @@ hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr)  	return status;  } -hw_status hw_mmu_twl_enable(const void __iomem *base_address) +hw_status hw_mmu_twl_enable(void __iomem *base_address)  {  	hw_status status = 0; @@ -276,7 +251,7 @@ hw_status hw_mmu_twl_enable(const void __iomem *base_address)  	return status;  } -hw_status hw_mmu_twl_disable(const void __iomem *base_address) +hw_status hw_mmu_twl_disable(void __iomem *base_address)  {  	hw_status status = 0; @@ -285,45 +260,7 @@ hw_status hw_mmu_twl_disable(const void __iomem *base_address)  	return status;  } -hw_status hw_mmu_tlb_flush(const void __iomem *base_address, u32 virtual_addr, -			   u32 page_sz) -{ -	hw_status status = 0; -	u32 virtual_addr_tag; -	enum hw_mmu_page_size_t pg_size_bits; - -	switch (page_sz) { -	case HW_PAGE_SIZE4KB: -		pg_size_bits = HW_MMU_SMALL_PAGE; -		break; - -	case HW_PAGE_SIZE64KB: -		pg_size_bits = HW_MMU_LARGE_PAGE; -		break; - -	case HW_PAGE_SIZE1MB: -		pg_size_bits = HW_MMU_SECTION; -		break; - -	case HW_PAGE_SIZE16MB: -		pg_size_bits = HW_MMU_SUPERSECTION; -		break; - -	default: -		return -EINVAL; -	} - -	/* Generate the 20-bit tag from virtual address */ -	virtual_addr_tag = ((virtual_addr & MMU_ADDR_MASK) >> 12); - -	mmu_set_cam_entry(base_address, pg_size_bits, 0, 0, virtual_addr_tag); - -	mmu_flush_entry(base_address); - -	return status; -} - -hw_status hw_mmu_tlb_add(const void __iomem *base_address, +hw_status hw_mmu_tlb_add(void __iomem *base_address,  			 u32 physical_addr,  			 u32 virtual_addr,  			 u32 page_sz, @@ -503,20 +440,8 @@ hw_status hw_mmu_pte_clear(const u32 pg_tbl_va, u32 virtual_addr, u32 page_size)  	return status;  } -/* mmu_flush_entry */ -static hw_status mmu_flush_entry(const void __iomem *base_address) -{ -	hw_status status = 0; -	u32 flush_entry_data = 0x1; - -	/* write values to register */ -	MMUMMU_FLUSH_ENTRY_WRITE_REGISTER32(base_address, flush_entry_data); - -	return status; -} -  /* mmu_set_cam_entry */ -static hw_status mmu_set_cam_entry(const void __iomem *base_address, +static hw_status mmu_set_cam_entry(void __iomem *base_address,  				   const u32 page_sz,  				   const u32 preserved_bit,  				   const u32 valid_bit, @@ -536,7 +461,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,  }  /* mmu_set_ram_entry */ -static hw_status mmu_set_ram_entry(const void __iomem *base_address, +static hw_status mmu_set_ram_entry(void __iomem *base_address,  				   const u32 physical_addr,  				   enum hw_endianism_t endianism,  				   enum hw_element_size_t element_size, @@ -556,7 +481,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address,  } -void hw_mmu_tlb_flush_all(const void __iomem *base) +void hw_mmu_tlb_flush_all(void __iomem *base)  {  	__raw_writel(1, base + MMU_GFLUSH);  } diff --git a/drivers/staging/tidspbridge/hw/hw_mmu.h b/drivers/staging/tidspbridge/hw/hw_mmu.h index 1458a2c6027..1c50bb36edf 100644 --- a/drivers/staging/tidspbridge/hw/hw_mmu.h +++ b/drivers/staging/tidspbridge/hw/hw_mmu.h @@ -42,44 +42,41 @@ struct hw_mmu_map_attrs_t {  	bool donotlockmpupage;  }; -extern hw_status hw_mmu_enable(const void __iomem *base_address); +extern hw_status hw_mmu_enable(void __iomem *base_address); -extern hw_status hw_mmu_disable(const void __iomem *base_address); +extern hw_status hw_mmu_disable(void __iomem *base_address); -extern hw_status hw_mmu_num_locked_set(const void __iomem *base_address, +extern hw_status hw_mmu_num_locked_set(void __iomem *base_address,  				       u32 num_locked_entries); -extern hw_status hw_mmu_victim_num_set(const void __iomem *base_address, +extern hw_status hw_mmu_victim_num_set(void __iomem *base_address,  				       u32 victim_entry_num);  /* For MMU faults */ -extern hw_status hw_mmu_event_ack(const void __iomem *base_address, +extern hw_status hw_mmu_event_ack(void __iomem *base_address,  				  u32 irq_mask); -extern hw_status hw_mmu_event_disable(const void __iomem *base_address, +extern hw_status hw_mmu_event_disable(void __iomem *base_address,  				      u32 irq_mask); -extern hw_status hw_mmu_event_enable(const void __iomem *base_address, +extern hw_status hw_mmu_event_enable(void __iomem *base_address,  				     u32 irq_mask); -extern hw_status hw_mmu_event_status(const void __iomem *base_address, +extern hw_status hw_mmu_event_status(void __iomem *base_address,  				     u32 *irq_mask); -extern hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, +extern hw_status hw_mmu_fault_addr_read(void __iomem *base_address,  					u32 *addr);  /* Set the TT base address */ -extern hw_status hw_mmu_ttb_set(const void __iomem *base_address, +extern hw_status hw_mmu_ttb_set(void __iomem *base_address,  				u32 ttb_phys_addr); -extern hw_status hw_mmu_twl_enable(const void __iomem *base_address); +extern hw_status hw_mmu_twl_enable(void __iomem *base_address); -extern hw_status hw_mmu_twl_disable(const void __iomem *base_address); +extern hw_status hw_mmu_twl_disable(void __iomem *base_address); -extern hw_status hw_mmu_tlb_flush(const void __iomem *base_address, -				  u32 virtual_addr, u32 page_sz); - -extern hw_status hw_mmu_tlb_add(const void __iomem *base_address, +extern hw_status hw_mmu_tlb_add(void __iomem *base_address,  				u32 physical_addr,  				u32 virtual_addr,  				u32 page_sz, @@ -97,7 +94,7 @@ extern hw_status hw_mmu_pte_set(const u32 pg_tbl_va,  extern hw_status hw_mmu_pte_clear(const u32 pg_tbl_va,  				  u32 virtual_addr, u32 page_size); -void hw_mmu_tlb_flush_all(const void __iomem *base); +void hw_mmu_tlb_flush_all(void __iomem *base);  static inline u32 hw_mmu_pte_addr_l1(u32 l1_base, u32 va)  { diff --git a/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h b/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h index 60a278136bd..b32c75673ab 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h +++ b/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h @@ -53,8 +53,8 @@ struct cfg_hostres {  	u32 chnl_buf_size;  	u32 num_chnls;  	void __iomem *per_base; -	u32 per_pm_base; -	u32 core_pm_base; +	void __iomem *per_pm_base; +	void __iomem *core_pm_base;  	void __iomem *dmmu_base;  }; diff --git a/drivers/staging/tidspbridge/include/dspbridge/host_os.h b/drivers/staging/tidspbridge/include/dspbridge/host_os.h index ed00d3da320..5e2f4d82d92 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/host_os.h +++ b/drivers/staging/tidspbridge/include/dspbridge/host_os.h @@ -47,8 +47,8 @@  #include <asm/cacheflush.h>  #include <linux/dma-mapping.h> -/* TODO -- Remove, once BP defines them */ -#define INT_DSP_MMU_IRQ        28 +/* TODO -- Remove, once omap-iommu is used */ +#define INT_DSP_MMU_IRQ        (28 + NR_IRQS)  #define PRCM_VDD1 1 diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c index 6795205b015..db1da28cecb 100644 --- a/drivers/staging/tidspbridge/rmgr/drv.c +++ b/drivers/staging/tidspbridge/rmgr/drv.c @@ -667,10 +667,10 @@ int drv_request_bridge_res_dsp(void **phost_resources)  							 OMAP_DSP_MEM3_SIZE);  		host_res->per_base = ioremap(OMAP_PER_CM_BASE,  						OMAP_PER_CM_SIZE); -		host_res->per_pm_base = (u32) ioremap(OMAP_PER_PRM_BASE, -							 OMAP_PER_PRM_SIZE); -		host_res->core_pm_base = (u32) ioremap(OMAP_CORE_PRM_BASE, -							  OMAP_CORE_PRM_SIZE); +		host_res->per_pm_base = ioremap(OMAP_PER_PRM_BASE, +						OMAP_PER_PRM_SIZE); +		host_res->core_pm_base = ioremap(OMAP_CORE_PRM_BASE, +							OMAP_CORE_PRM_SIZE);  		host_res->dmmu_base = ioremap(OMAP_DMMU_BASE,  						 OMAP_DMMU_SIZE); diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c index c2fc6137c77..294e9b40f51 100644 --- a/drivers/staging/tidspbridge/rmgr/node.c +++ b/drivers/staging/tidspbridge/rmgr/node.c @@ -304,8 +304,7 @@ int node_allocate(struct proc_object *hprocessor,  	u32 pul_value;  	u32 dynext_base;  	u32 off_set = 0; -	u32 ul_stack_seg_addr, ul_stack_seg_val; -	u32 ul_gpp_mem_base; +	u32 ul_stack_seg_val;  	struct cfg_hostres *host_res;  	struct bridge_dev_context *pbridge_context;  	u32 mapped_addr = 0; @@ -581,6 +580,9 @@ func_cont:  		if (strcmp((char *)  			   pnode->dcd_props.obj_data.node_obj.ndb_props.  			   stack_seg_name, STACKSEGLABEL) == 0) { +			void __iomem *stack_seg; +			u32 stack_seg_pa; +  			status =  			    hnode_mgr->nldr_fxns.  			    get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG", @@ -608,14 +610,21 @@ func_cont:  				goto func_end;  			} -			ul_gpp_mem_base = (u32) host_res->mem_base[1];  			off_set = pul_value - dynext_base; -			ul_stack_seg_addr = ul_gpp_mem_base + off_set; -			ul_stack_seg_val = readl(ul_stack_seg_addr); +			stack_seg_pa = host_res->mem_phys[1] + off_set; +			stack_seg = ioremap(stack_seg_pa, SZ_32); +			if (!stack_seg) { +				status = -ENOMEM; +				goto func_end; +			} + +			ul_stack_seg_val = readl(stack_seg); + +			iounmap(stack_seg);  			dev_dbg(bridge, "%s: StackSegVal = 0x%x, StackSegAddr ="  				" 0x%x\n", __func__, ul_stack_seg_val, -				ul_stack_seg_addr); +				host_res->mem_base[1] + off_set);  			pnode->create_args.asa.task_arg_obj.stack_seg =  			    ul_stack_seg_val; diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 653b074035f..6edefde2372 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -223,8 +223,13 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,  	cmem = zs_map_object(zram->mem_pool, zram->table[index].handle,  				ZS_MM_RO); -	ret = lzo1x_decompress_safe(cmem, zram->table[index].size, +	if (zram->table[index].size == PAGE_SIZE) { +		memcpy(uncmem, cmem, PAGE_SIZE); +		ret = LZO_E_OK; +	} else { +		ret = lzo1x_decompress_safe(cmem, zram->table[index].size,  				    uncmem, &clen); +	}  	if (is_partial_io(bvec)) {  		memcpy(user_mem + bvec->bv_offset, uncmem + offset, @@ -342,8 +347,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,  		goto out;  	} -	if (unlikely(clen > max_zpage_size)) +	if (unlikely(clen > max_zpage_size)) {  		zram_stat_inc(&zram->stats.bad_compress); +		src = uncmem; +		clen = PAGE_SIZE; +	}  	handle = zs_malloc(zram->mem_pool, clen);  	if (!handle) { diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index d6ce2182e67..035c2c76253 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3719,7 +3719,9 @@ restart:  		 */  		iscsit_thread_check_cpumask(conn, current, 1); -		schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT); +		wait_event_interruptible(conn->queues_wq, +					 !iscsit_conn_all_queues_empty(conn) || +					 ts->status == ISCSI_THREAD_SET_RESET);  		if ((ts->status == ISCSI_THREAD_SET_RESET) ||  		     signal_pending(current)) diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 2ba9f9b9435..21048dbf7d1 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -486,6 +486,7 @@ struct iscsi_tmr_req {  };  struct iscsi_conn { +	wait_queue_head_t	queues_wq;  	/* Authentication Successful for this connection */  	u8			auth_complete;  	/* State connection is currently in */ diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index cdc8a10939c..f8dbec05d5e 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -41,6 +41,7 @@  static int iscsi_login_init_conn(struct iscsi_conn *conn)  { +	init_waitqueue_head(&conn->queues_wq);  	INIT_LIST_HEAD(&conn->conn_list);  	INIT_LIST_HEAD(&conn->conn_cmd_list);  	INIT_LIST_HEAD(&conn->immed_queue_list); diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index afd98ccd40a..1a91195ab61 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue(  	atomic_set(&conn->check_immediate_queue, 1);  	spin_unlock_bh(&conn->immed_queue_lock); -	wake_up_process(conn->thread_set->tx_thread); +	wake_up(&conn->queues_wq);  }  struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn) @@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue(  	atomic_inc(&cmd->response_queue_count);  	spin_unlock_bh(&conn->response_queue_lock); -	wake_up_process(conn->thread_set->tx_thread); +	wake_up(&conn->queues_wq);  }  struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn) @@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue(  	}  } +bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn) +{ +	bool empty; + +	spin_lock_bh(&conn->immed_queue_lock); +	empty = list_empty(&conn->immed_queue_list); +	spin_unlock_bh(&conn->immed_queue_lock); + +	if (!empty) +		return empty; + +	spin_lock_bh(&conn->response_queue_lock); +	empty = list_empty(&conn->response_queue_list); +	spin_unlock_bh(&conn->response_queue_lock); + +	return empty; +} +  void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)  {  	struct iscsi_queue_req *qr, *qr_tmp; diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index 44054bd3543..894d0f83792 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_  extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);  extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *);  extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *); +extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *);  extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);  extern void iscsit_release_cmd(struct iscsi_cmd *);  extern void iscsit_free_cmd(struct iscsi_cmd *); diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 015f5be27bf..c123327499a 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3206,7 +3206,8 @@ static int __init target_core_init_configfs(void)  	if (ret < 0)  		goto out; -	if (core_dev_setup_virtual_lun0() < 0) +	ret = core_dev_setup_virtual_lun0(); +	if (ret < 0)  		goto out;  	return 0; diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 8d774da1632..9abef9f8eb7 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev)  static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)  { -	u32 tmp, aligned_max_sectors; +	u32 aligned_max_sectors; +	u32 alignment;  	/*  	 * Limit max_sectors to a PAGE_SIZE aligned value for modern  	 * transport_allocate_data_tasks() operation.  	 */ -	tmp = rounddown((max_sectors * block_size), PAGE_SIZE); -	aligned_max_sectors = (tmp / block_size); -	if (max_sectors != aligned_max_sectors) { -		printk(KERN_INFO "Rounding down aligned max_sectors from %u" -				" to %u\n", max_sectors, aligned_max_sectors); -		return aligned_max_sectors; -	} +	alignment = max(1ul, PAGE_SIZE / block_size); +	aligned_max_sectors = rounddown(max_sectors, alignment); + +	if (max_sectors != aligned_max_sectors) +		pr_info("Rounding down aligned max_sectors from %u to %u\n", +			max_sectors, aligned_max_sectors); -	return max_sectors; +	return aligned_max_sectors;  }  void se_dev_set_default_attribs( diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 868f8aa04f1..a6e27d967c7 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -135,6 +135,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd)  	return 0;  } +static int sbc_emulate_noop(struct se_cmd *cmd) +{ +	target_complete_cmd(cmd, GOOD); +	return 0; +} +  static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)  {  	return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors; @@ -531,6 +537,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)  		size = 0;  		cmd->execute_cmd = sbc_emulate_verify;  		break; +	case REZERO_UNIT: +	case SEEK_6: +	case SEEK_10: +		/* +		 * There are still clients out there which use these old SCSI-2 +		 * commands. This mainly happens when running VMs with legacy +		 * guest systems, connected via SCSI command pass-through to +		 * iSCSI targets. Make them happy and return status GOOD. +		 */ +		size = 0; +		cmd->execute_cmd = sbc_emulate_noop; +		break;  	default:  		ret = spc_parse_cdb(cmd, &size);  		if (ret) diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 9229bd9ad61..6fd434d3d7e 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)  	unsigned char buf[SE_INQUIRY_BUF];  	int p, ret; +	memset(buf, 0, SE_INQUIRY_BUF); +  	if (dev == tpg->tpg_virt_lun0.lun_se_dev)  		buf[0] = 0x3f; /* Not connected */  	else diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 1c59a3c23b2..be75c4331a9 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -140,15 +140,15 @@ void core_tmr_abort_task(  		printk("ABORT_TASK: Found referenced %s task_tag: %u\n",  			se_cmd->se_tfo->get_fabric_name(), ref_tag); -		spin_lock_irq(&se_cmd->t_state_lock); +		spin_lock(&se_cmd->t_state_lock);  		if (se_cmd->transport_state & CMD_T_COMPLETE) {  			printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag); -			spin_unlock_irq(&se_cmd->t_state_lock); +			spin_unlock(&se_cmd->t_state_lock);  			spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);  			goto out;  		}  		se_cmd->transport_state |= CMD_T_ABORTED; -		spin_unlock_irq(&se_cmd->t_state_lock); +		spin_unlock(&se_cmd->t_state_lock);  		list_del_init(&se_cmd->se_cmd_list);  		kref_get(&se_cmd->cmd_kref); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c33baff86aa..9097155e9eb 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1616,7 +1616,6 @@ static void target_complete_tmr_failure(struct work_struct *work)  	se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;  	se_cmd->se_tfo->queue_tm_rsp(se_cmd); -	transport_generic_free_cmd(se_cmd, 0);  }  /** diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c index fd03e8581af..6dd29e4ce36 100644 --- a/drivers/thermal/exynos_thermal.c +++ b/drivers/thermal/exynos_thermal.c @@ -815,7 +815,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = {  	},  	{ },  }; -MODULE_DEVICE_TABLE(platform, exynos4_tmu_driver_ids); +MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);  static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(  			struct platform_device *pdev) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index d4452716aaa..f7a1b574a30 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -210,7 +210,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)  		goto error_free_priv;  	} -	zone = thermal_zone_device_register("rcar_thermal", 0, priv, +	zone = thermal_zone_device_register("rcar_thermal", 0, 0, priv,  					    &rcar_thermal_zone_ops, 0, 0);  	if (IS_ERR(zone)) {  		dev_err(&pdev->dev, "thermal zone device is NULL\n"); diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 6ede6fd92b4..6d3d26a607b 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -671,19 +671,19 @@ serial_omap_configure_xonxoff  	/*  	 * IXON Flag: -	 * Flow control for OMAP.TX -	 * OMAP.RX should listen for XON/XOFF +	 * Enable XON/XOFF flow control on output. +	 * Transmit XON1, XOFF1  	 */  	if (termios->c_iflag & IXON) -		up->efr |= OMAP_UART_SW_RX; +		up->efr |= OMAP_UART_SW_TX;  	/*  	 * IXOFF Flag: -	 * Flow control for OMAP.RX -	 * OMAP.TX should send XON/XOFF +	 * Enable XON/XOFF flow control on input. +	 * Receiver compares XON1, XOFF1.  	 */  	if (termios->c_iflag & IXOFF) -		up->efr |= OMAP_UART_SW_TX; +		up->efr |= OMAP_UART_SW_RX;  	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);  	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 64854d76f52..1af04bdeaf0 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -739,13 +739,16 @@ static void hub_tt_work(struct work_struct *work)  	int			limit = 100;  	spin_lock_irqsave (&hub->tt.lock, flags); -	while (--limit && !list_empty (&hub->tt.clear_list)) { +	while (!list_empty(&hub->tt.clear_list)) {  		struct list_head	*next;  		struct usb_tt_clear	*clear;  		struct usb_device	*hdev = hub->hdev;  		const struct hc_driver	*drv;  		int			status; +		if (!hub->quiescing && --limit < 0) +			break; +  		next = hub->tt.clear_list.next;  		clear = list_entry (next, struct usb_tt_clear, clear_list);  		list_del (&clear->clear_list); @@ -1210,7 +1213,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)  	if (hub->has_indicators)  		cancel_delayed_work_sync(&hub->leds);  	if (hub->tt.hub) -		cancel_work_sync(&hub->tt.clear_work); +		flush_work(&hub->tt.clear_work);  }  /* caller has locked the hub device */ diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index 43ac7482fa9..c009263a47e 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -2069,8 +2069,10 @@ static irqreturn_t net2272_irq(int irq, void *_dev)  #if defined(PLX_PCI_RDK2)  	/* see if PCI int for us by checking irqstat */  	intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT); -	if (!intcsr & (1 << NET2272_PCI_IRQ)) +	if (!intcsr & (1 << NET2272_PCI_IRQ)) { +		spin_unlock(&dev->lock);  		return IRQ_NONE; +	}  	/* check dma interrupts */  #endif  	/* Platform/devcice interrupt handler */ diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 6458764994e..4ec3c0d7a18 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -20,6 +20,7 @@  #include <linux/ctype.h>  #include <linux/etherdevice.h>  #include <linux/ethtool.h> +#include <linux/if_vlan.h>  #include "u_ether.h" @@ -295,7 +296,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)  		while (skb2) {  			if (status < 0  					|| ETH_HLEN > skb2->len -					|| skb2->len > ETH_FRAME_LEN) { +					|| skb2->len > VLAN_ETH_FRAME_LEN) {  				dev->net->stats.rx_errors++;  				dev->net->stats.rx_length_errors++;  				DBG(dev, "rx length %d\n", skb2->len); diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 966d1484ee7..39f9e4a9a2d 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -545,7 +545,14 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {  		/*  Pegatron Lucid (Ordissimo AIRIS) */  		.matches = {  			DMI_MATCH(DMI_BOARD_NAME, "M11JB"), -			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"), +			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), +		}, +	}, +	{ +		/*  Pegatron Lucid (Ordissimo) */ +		.matches = { +			DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"), +			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),  		},  	},  	{ } diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 4b436f5a417..5f3a7c74aa8 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -544,7 +544,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,  	int i;  	/* Fields are 32 bits wide, DMA addresses are in bytes */  	int field_size = 32 / 8; -	struct xhci_slot_ctx *slot_ctx;  	dma_addr_t dma = ctx->dma;  	int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); @@ -570,7 +569,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,  			dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma);  	} -	slot_ctx = xhci_get_slot_ctx(xhci, ctx);  	xhci_dbg_slot_ctx(xhci, ctx);  	xhci_dbg_ep_ctx(xhci, ctx, last_ep);  } diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index aa90ad4d4fd..a686cf4905b 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -151,9 +151,8 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,  		if (portsc & PORT_DEV_REMOVE)  			port_removable |= 1 << (i + 1);  	} -	memset(&desc->u.ss.DeviceRemovable, -			(__force __u16) cpu_to_le16(port_removable), -			sizeof(__u16)); + +	desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable);  }  static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, @@ -809,11 +808,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  			temp = xhci_readl(xhci, port_array[wIndex]);  			xhci_dbg(xhci, "set port power, actual port %d status  = 0x%x\n", wIndex, temp); +			spin_unlock_irqrestore(&xhci->lock, flags);  			temp = usb_acpi_power_manageable(hcd->self.root_hub,  					wIndex);  			if (temp)  				usb_acpi_set_power_state(hcd->self.root_hub,  						wIndex, true); +			spin_lock_irqsave(&xhci->lock, flags);  			break;  		case USB_PORT_FEAT_RESET:  			temp = (temp | PORT_RESET); @@ -917,11 +918,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  			xhci_writel(xhci, temp & ~PORT_POWER,  				port_array[wIndex]); +			spin_unlock_irqrestore(&xhci->lock, flags);  			temp = usb_acpi_power_manageable(hcd->self.root_hub,  					wIndex);  			if (temp)  				usb_acpi_set_power_state(hcd->self.root_hub,  						wIndex, false); +			spin_lock_irqsave(&xhci->lock, flags);  			break;  		default:  			goto error; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index c6ebb176dc4..4e1a8946b8d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd)  	cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,  			xhci->cmd_ring->dequeue, &cycle_state); +	if (!cur_seg) { +		xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n", +				xhci->cmd_ring->dequeue, +				(unsigned long long) +				xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, +					xhci->cmd_ring->dequeue)); +		xhci_debug_ring(xhci, xhci->cmd_ring); +		xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); +		return; +	} +  	/* find the command trb matched by cd from command ring */  	for (cmd_trb = xhci->cmd_ring->dequeue;  			cmd_trb != xhci->cmd_ring->enqueue; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7d462bf2009..c9e419f29b7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1627,7 +1627,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,  	struct xhci_hcd *xhci;  	struct xhci_container_ctx *in_ctx, *out_ctx;  	unsigned int ep_index; -	struct xhci_ep_ctx *ep_ctx;  	struct xhci_slot_ctx *slot_ctx;  	struct xhci_input_control_ctx *ctrl_ctx;  	u32 added_ctxs; @@ -1663,7 +1662,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,  	out_ctx = virt_dev->out_ctx;  	ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);  	ep_index = xhci_get_endpoint_index(&ep->desc); -	ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);  	/* If this endpoint is already in use, and the upper layers are trying  	 * to add it again without dropping it, reject the addition. @@ -1817,6 +1815,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,  	case COMP_EBADSLT:  		dev_warn(&udev->dev, "WARN: slot not enabled for"  				"evaluate context command.\n"); +		ret = -EINVAL; +		break;  	case COMP_CTX_STATE:  		dev_warn(&udev->dev, "WARN: invalid context state for "  				"evaluate context command.\n"); @@ -4021,7 +4021,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)  static unsigned long long xhci_service_interval_to_ns(  		struct usb_endpoint_descriptor *desc)  { -	return (1 << (desc->bInterval - 1)) * 125 * 1000; +	return (1ULL << (desc->bInterval - 1)) * 125 * 1000;  }  static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev, @@ -4142,7 +4142,7 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,  			(xhci_service_interval_to_ns(desc) > timeout_ns))  		timeout_ns = xhci_service_interval_to_ns(desc); -	u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000; +	u2_del_ns = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat) * 1000ULL;  	if (u2_del_ns > timeout_ns)  		timeout_ns = u2_del_ns; diff --git a/drivers/usb/misc/ezusb.c b/drivers/usb/misc/ezusb.c index 4223d761223..6589268a651 100644 --- a/drivers/usb/misc/ezusb.c +++ b/drivers/usb/misc/ezusb.c @@ -158,3 +158,4 @@ int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,  }  EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 444346e1e10..ff5f112053d 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -458,11 +458,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)  	struct platform_device	*musb;  	struct resource *res;  	struct resource	resources[2]; -	char res_name[10]; +	char res_name[11];  	int ret, musbid;  	/* get memory resource */ -	sprintf(res_name, "musb%d", id); +	snprintf(res_name, sizeof(res_name), "musb%d", id);  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);  	if (!res) {  		dev_err(dev, "%s get mem resource failed\n", res_name); @@ -473,7 +473,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)  	resources[0] = *res;  	/* get irq resource */ -	sprintf(res_name, "musb%d-irq", id); +	snprintf(res_name, sizeof(res_name), "musb%d-irq", id);  	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);  	if (!res) {  		dev_err(dev, "%s get irq resource failed\n", res_name); @@ -530,7 +530,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)  		of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);  		of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); -		sprintf(res_name, "port%d-mode", id); +		snprintf(res_name, sizeof(res_name), "port%d-mode", id);  		of_property_read_u32(np, res_name, (u32 *)&pdata->mode);  		of_property_read_u32(np, "power", (u32 *)&pdata->power);  		config->multipoint = of_property_read_bool(np, "multipoint"); diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 143c4e9e1be..c021b202c0f 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -795,6 +795,7 @@ static void xfer_work(struct work_struct *work)  	dev_dbg(dev, "  %s %d (%d/ %d)\n",  		fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); +	usbhs_pipe_enable(pipe);  	usbhsf_dma_start(pipe, fifo);  	dma_async_issue_pending(chan);  } diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 9b69a132329..069cd765400 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -334,6 +334,11 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,  	struct device *dev = usbhs_priv_to_dev(priv);  	unsigned long flags; +	if (unlikely(!uep)) { +		dev_err(dev, "no uep\n"); +		return; +	} +  	/********************  spin lock ********************/  	usbhs_lock(priv, flags); diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index e9c7046ae35..d255f66e708 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -242,13 +242,11 @@ out:	kfree(buffer);  	return r;  } -/* allocate private data */ -static int ch341_attach(struct usb_serial *serial) +static int ch341_port_probe(struct usb_serial_port *port)  {  	struct ch341_private *priv;  	int r; -	/* private data */  	priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);  	if (!priv)  		return -ENOMEM; @@ -258,17 +256,27 @@ static int ch341_attach(struct usb_serial *serial)  	priv->baud_rate = DEFAULT_BAUD_RATE;  	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; -	r = ch341_configure(serial->dev, priv); +	r = ch341_configure(port->serial->dev, priv);  	if (r < 0)  		goto error; -	usb_set_serial_port_data(serial->port[0], priv); +	usb_set_serial_port_data(port, priv);  	return 0;  error:	kfree(priv);  	return r;  } +static int ch341_port_remove(struct usb_serial_port *port) +{ +	struct ch341_private *priv; + +	priv = usb_get_serial_port_data(port); +	kfree(priv); + +	return 0; +} +  static int ch341_carrier_raised(struct usb_serial_port *port)  {  	struct ch341_private *priv = usb_get_serial_port_data(port); @@ -304,7 +312,7 @@ static void ch341_close(struct usb_serial_port *port)  static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)  {  	struct usb_serial *serial = port->serial; -	struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]); +	struct ch341_private *priv = usb_get_serial_port_data(port);  	int r;  	priv->baud_rate = DEFAULT_BAUD_RATE; @@ -608,7 +616,8 @@ static struct usb_serial_driver ch341_device = {  	.tiocmget          = ch341_tiocmget,  	.tiocmset          = ch341_tiocmset,  	.read_int_callback = ch341_read_int_callback, -	.attach            = ch341_attach, +	.port_probe        = ch341_port_probe, +	.port_remove       = ch341_port_remove,  	.reset_resume      = ch341_reset_resume,  }; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index c86f68c6b07..b50fa1c6d88 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -244,6 +244,8 @@ static int digi_startup_device(struct usb_serial *serial);  static int digi_startup(struct usb_serial *serial);  static void digi_disconnect(struct usb_serial *serial);  static void digi_release(struct usb_serial *serial); +static int digi_port_probe(struct usb_serial_port *port); +static int digi_port_remove(struct usb_serial_port *port);  static void digi_read_bulk_callback(struct urb *urb);  static int digi_read_inb_callback(struct urb *urb);  static int digi_read_oob_callback(struct urb *urb); @@ -294,6 +296,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {  	.attach =			digi_startup,  	.disconnect =			digi_disconnect,  	.release =			digi_release, +	.port_probe =			digi_port_probe, +	.port_remove =			digi_port_remove,  };  static struct usb_serial_driver digi_acceleport_4_device = { @@ -320,6 +324,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {  	.attach =			digi_startup,  	.disconnect =			digi_disconnect,  	.release =			digi_release, +	.port_probe =			digi_port_probe, +	.port_remove =			digi_port_remove,  };  static struct usb_serial_driver * const serial_drivers[] = { @@ -1240,59 +1246,50 @@ static int digi_startup_device(struct usb_serial *serial)  	return ret;  } - -static int digi_startup(struct usb_serial *serial) +static int digi_port_init(struct usb_serial_port *port, unsigned port_num)  { - -	int i;  	struct digi_port *priv; -	struct digi_serial *serial_priv; -	/* allocate the private data structures for all ports */ -	/* number of regular ports + 1 for the out-of-band port */ -	for (i = 0; i < serial->type->num_ports + 1; i++) { -		/* allocate port private structure */ -		priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL); -		if (priv == NULL) { -			while (--i >= 0) -				kfree(usb_get_serial_port_data(serial->port[i])); -			return 1;			/* error */ -		} +	priv = kzalloc(sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; -		/* initialize port private structure */ -		spin_lock_init(&priv->dp_port_lock); -		priv->dp_port_num = i; -		priv->dp_out_buf_len = 0; -		priv->dp_write_urb_in_use = 0; -		priv->dp_modem_signals = 0; -		init_waitqueue_head(&priv->dp_modem_change_wait); -		priv->dp_transmit_idle = 0; -		init_waitqueue_head(&priv->dp_transmit_idle_wait); -		priv->dp_throttled = 0; -		priv->dp_throttle_restart = 0; -		init_waitqueue_head(&priv->dp_flush_wait); -		init_waitqueue_head(&priv->dp_close_wait); -		INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); -		priv->dp_port = serial->port[i]; -		/* initialize write wait queue for this port */ -		init_waitqueue_head(&serial->port[i]->write_wait); +	spin_lock_init(&priv->dp_port_lock); +	priv->dp_port_num = port_num; +	init_waitqueue_head(&priv->dp_modem_change_wait); +	init_waitqueue_head(&priv->dp_transmit_idle_wait); +	init_waitqueue_head(&priv->dp_flush_wait); +	init_waitqueue_head(&priv->dp_close_wait); +	INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); +	priv->dp_port = port; -		usb_set_serial_port_data(serial->port[i], priv); -	} +	init_waitqueue_head(&port->write_wait); -	/* allocate serial private structure */ -	serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL); -	if (serial_priv == NULL) { -		for (i = 0; i < serial->type->num_ports + 1; i++) -			kfree(usb_get_serial_port_data(serial->port[i])); -		return 1;			/* error */ -	} +	usb_set_serial_port_data(port, priv); + +	return 0; +} + +static int digi_startup(struct usb_serial *serial) +{ +	struct digi_serial *serial_priv; +	int ret; + +	serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); +	if (!serial_priv) +		return -ENOMEM; -	/* initialize serial private structure */  	spin_lock_init(&serial_priv->ds_serial_lock);  	serial_priv->ds_oob_port_num = serial->type->num_ports;  	serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; -	serial_priv->ds_device_started = 0; + +	ret = digi_port_init(serial_priv->ds_oob_port, +						serial_priv->ds_oob_port_num); +	if (ret) { +		kfree(serial_priv); +		return ret; +	} +  	usb_set_serial_data(serial, serial_priv);  	return 0; @@ -1313,15 +1310,35 @@ static void digi_disconnect(struct usb_serial *serial)  static void digi_release(struct usb_serial *serial)  { -	int i; +	struct digi_serial *serial_priv; +	struct digi_port *priv; + +	serial_priv = usb_get_serial_data(serial); + +	priv = usb_get_serial_port_data(serial_priv->ds_oob_port); +	kfree(priv); + +	kfree(serial_priv); +} -	/* free the private data structures for all ports */ -	/* number of regular ports + 1 for the out-of-band port */ -	for (i = 0; i < serial->type->num_ports + 1; i++) -		kfree(usb_get_serial_port_data(serial->port[i])); -	kfree(usb_get_serial_data(serial)); +static int digi_port_probe(struct usb_serial_port *port) +{ +	unsigned port_num; + +	port_num = port->number - port->serial->minor; + +	return digi_port_init(port, port_num);  } +static int digi_port_remove(struct usb_serial_port *port) +{ +	struct digi_port *priv; + +	priv = usb_get_serial_port_data(port); +	kfree(priv); + +	return 0; +}  static void digi_read_bulk_callback(struct urb *urb)  { diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 20a132ec39e..4264821a3b3 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -203,8 +203,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)  	return 0;  } -/* fake probe - only to allocate data structures */ -static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id) +static int ipw_attach(struct usb_serial *serial)  {  	struct usb_wwan_intf_private *data; @@ -303,9 +302,9 @@ static struct usb_serial_driver ipw_device = {  	.num_ports =		1,  	.open =			ipw_open,  	.close =		ipw_close, -	.probe =		ipw_probe, -	.attach =		usb_wwan_startup, +	.attach =		ipw_attach,  	.release =		ipw_release, +	.port_probe =		usb_wwan_port_probe,  	.port_remove =		usb_wwan_port_remove,  	.dtr_rts =		ipw_dtr_rts,  	.write =		usb_wwan_write, diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 29c943d737d..7179b0c5f81 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1374,13 +1374,9 @@ static struct callbacks {  	   data in device_details */  static void keyspan_setup_urbs(struct usb_serial *serial)  { -	int				i, j;  	struct keyspan_serial_private 	*s_priv;  	const struct keyspan_device_details	*d_details; -	struct usb_serial_port		*port; -	struct keyspan_port_private	*p_priv;  	struct callbacks		*cback; -	int				endp;  	s_priv = usb_get_serial_data(serial);  	d_details = s_priv->device_details; @@ -1404,45 +1400,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial)  		(serial, d_details->glocont_endpoint, USB_DIR_OUT,  		 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,  		 cback->glocont_callback); - -	/* Setup endpoints for each port specific thing */ -	for (i = 0; i < d_details->num_ports; i++) { -		port = serial->port[i]; -		p_priv = usb_get_serial_port_data(port); - -		/* Do indat endpoints first, once for each flip */ -		endp = d_details->indat_endpoints[i]; -		for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) { -			p_priv->in_urbs[j] = keyspan_setup_urb -				(serial, endp, USB_DIR_IN, port, -				 p_priv->in_buffer[j], 64, -				 cback->indat_callback); -		} -		for (; j < 2; ++j) -			p_priv->in_urbs[j] = NULL; - -		/* outdat endpoints also have flip */ -		endp = d_details->outdat_endpoints[i]; -		for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) { -			p_priv->out_urbs[j] = keyspan_setup_urb -				(serial, endp, USB_DIR_OUT, port, -				 p_priv->out_buffer[j], 64, -				 cback->outdat_callback); -		} -		for (; j < 2; ++j) -			p_priv->out_urbs[j] = NULL; - -		/* inack endpoint */ -		p_priv->inack_urb = keyspan_setup_urb -			(serial, d_details->inack_endpoints[i], USB_DIR_IN, -			 port, p_priv->inack_buffer, 1, cback->inack_callback); - -		/* outcont endpoint */ -		p_priv->outcont_urb = keyspan_setup_urb -			(serial, d_details->outcont_endpoints[i], USB_DIR_OUT, -			 port, p_priv->outcont_buffer, 64, -			 cback->outcont_callback); -	}  }  /* usa19 function doesn't require prescaler */ @@ -2407,9 +2364,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)  static int keyspan_startup(struct usb_serial *serial)  {  	int				i, err; -	struct usb_serial_port		*port;  	struct keyspan_serial_private 	*s_priv; -	struct keyspan_port_private	*p_priv;  	const struct keyspan_device_details	*d_details;  	for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i) @@ -2432,19 +2387,6 @@ static int keyspan_startup(struct usb_serial *serial)  	s_priv->device_details = d_details;  	usb_set_serial_data(serial, s_priv); -	/* Now setup per port private data */ -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		p_priv = kzalloc(sizeof(struct keyspan_port_private), -								GFP_KERNEL); -		if (!p_priv) { -			dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i); -			return 1; -		} -		p_priv->device_details = d_details; -		usb_set_serial_port_data(port, p_priv); -	} -  	keyspan_setup_urbs(serial);  	if (s_priv->instat_urb != NULL) { @@ -2463,59 +2405,112 @@ static int keyspan_startup(struct usb_serial *serial)  static void keyspan_disconnect(struct usb_serial *serial)  { -	int				i, j; -	struct usb_serial_port		*port; -	struct keyspan_serial_private 	*s_priv; -	struct keyspan_port_private	*p_priv; +	struct keyspan_serial_private *s_priv;  	s_priv = usb_get_serial_data(serial); -	/* Stop reading/writing urbs */  	stop_urb(s_priv->instat_urb);  	stop_urb(s_priv->glocont_urb);  	stop_urb(s_priv->indat_urb); -	for (i = 0; i < serial->num_ports; ++i) { -		port = serial->port[i]; -		p_priv = usb_get_serial_port_data(port); -		stop_urb(p_priv->inack_urb); -		stop_urb(p_priv->outcont_urb); -		for (j = 0; j < 2; j++) { -			stop_urb(p_priv->in_urbs[j]); -			stop_urb(p_priv->out_urbs[j]); -		} -	} +} + +static void keyspan_release(struct usb_serial *serial) +{ +	struct keyspan_serial_private *s_priv; + +	s_priv = usb_get_serial_data(serial); -	/* Now free them */  	usb_free_urb(s_priv->instat_urb);  	usb_free_urb(s_priv->indat_urb);  	usb_free_urb(s_priv->glocont_urb); -	for (i = 0; i < serial->num_ports; ++i) { -		port = serial->port[i]; -		p_priv = usb_get_serial_port_data(port); -		usb_free_urb(p_priv->inack_urb); -		usb_free_urb(p_priv->outcont_urb); -		for (j = 0; j < 2; j++) { -			usb_free_urb(p_priv->in_urbs[j]); -			usb_free_urb(p_priv->out_urbs[j]); -		} -	} + +	kfree(s_priv);  } -static void keyspan_release(struct usb_serial *serial) +static int keyspan_port_probe(struct usb_serial_port *port)  { -	int				i; -	struct usb_serial_port		*port; -	struct keyspan_serial_private 	*s_priv; +	struct usb_serial *serial = port->serial; +	struct keyspan_port_private *s_priv; +	struct keyspan_port_private *p_priv; +	const struct keyspan_device_details *d_details; +	struct callbacks *cback; +	int endp; +	int port_num; +	int i;  	s_priv = usb_get_serial_data(serial); +	d_details = s_priv->device_details; -	kfree(s_priv); +	p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL); +	if (!p_priv) +		return -ENOMEM; -	/* Now free per port private data */ -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		kfree(usb_get_serial_port_data(port)); +	s_priv = usb_get_serial_data(port->serial); +	p_priv->device_details = d_details; + +	/* Setup values for the various callback routines */ +	cback = &keyspan_callbacks[d_details->msg_format]; + +	port_num = port->number - port->serial->minor; + +	/* Do indat endpoints first, once for each flip */ +	endp = d_details->indat_endpoints[port_num]; +	for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) { +		p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp, +						USB_DIR_IN, port, +						p_priv->in_buffer[i], 64, +						cback->indat_callback);  	} +	/* outdat endpoints also have flip */ +	endp = d_details->outdat_endpoints[port_num]; +	for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) { +		p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp, +						USB_DIR_OUT, port, +						p_priv->out_buffer[i], 64, +						cback->outdat_callback); +	} +	/* inack endpoint */ +	p_priv->inack_urb = keyspan_setup_urb(serial, +					d_details->inack_endpoints[port_num], +					USB_DIR_IN, port, +					p_priv->inack_buffer, 1, +					cback->inack_callback); +	/* outcont endpoint */ +	p_priv->outcont_urb = keyspan_setup_urb(serial, +					d_details->outcont_endpoints[port_num], +					USB_DIR_OUT, port, +					p_priv->outcont_buffer, 64, +					 cback->outcont_callback); + +	usb_set_serial_port_data(port, p_priv); + +	return 0; +} + +static int keyspan_port_remove(struct usb_serial_port *port) +{ +	struct keyspan_port_private *p_priv; +	int i; + +	p_priv = usb_get_serial_port_data(port); + +	stop_urb(p_priv->inack_urb); +	stop_urb(p_priv->outcont_urb); +	for (i = 0; i < 2; i++) { +		stop_urb(p_priv->in_urbs[i]); +		stop_urb(p_priv->out_urbs[i]); +	} + +	usb_free_urb(p_priv->inack_urb); +	usb_free_urb(p_priv->outcont_urb); +	for (i = 0; i < 2; i++) { +		usb_free_urb(p_priv->in_urbs[i]); +		usb_free_urb(p_priv->out_urbs[i]); +	} + +	kfree(p_priv); + +	return 0;  }  MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 0a8a40b5711..0273dda303a 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -42,6 +42,8 @@ static void keyspan_dtr_rts		(struct usb_serial_port *port, int on);  static int  keyspan_startup		(struct usb_serial *serial);  static void keyspan_disconnect		(struct usb_serial *serial);  static void keyspan_release		(struct usb_serial *serial); +static int keyspan_port_probe(struct usb_serial_port *port); +static int keyspan_port_remove(struct usb_serial_port *port);  static int  keyspan_write_room		(struct tty_struct *tty);  static int  keyspan_write		(struct tty_struct *tty, @@ -567,6 +569,8 @@ static struct usb_serial_driver keyspan_1port_device = {  	.attach			= keyspan_startup,  	.disconnect		= keyspan_disconnect,  	.release		= keyspan_release, +	.port_probe		= keyspan_port_probe, +	.port_remove		= keyspan_port_remove,  };  static struct usb_serial_driver keyspan_2port_device = { @@ -589,6 +593,8 @@ static struct usb_serial_driver keyspan_2port_device = {  	.attach			= keyspan_startup,  	.disconnect		= keyspan_disconnect,  	.release		= keyspan_release, +	.port_probe		= keyspan_port_probe, +	.port_remove		= keyspan_port_remove,  };  static struct usb_serial_driver keyspan_4port_device = { @@ -611,6 +617,8 @@ static struct usb_serial_driver keyspan_4port_device = {  	.attach			= keyspan_startup,  	.disconnect		= keyspan_disconnect,  	.release		= keyspan_release, +	.port_probe		= keyspan_port_probe, +	.port_remove		= keyspan_port_remove,  };  static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index f3947712e13..8a208100410 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -49,7 +49,8 @@   * Function prototypes   */  static int  mct_u232_startup(struct usb_serial *serial); -static void mct_u232_release(struct usb_serial *serial); +static int  mct_u232_port_probe(struct usb_serial_port *port); +static int  mct_u232_port_remove(struct usb_serial_port *remove);  static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);  static void mct_u232_close(struct usb_serial_port *port);  static void mct_u232_dtr_rts(struct usb_serial_port *port, int on); @@ -99,7 +100,8 @@ static struct usb_serial_driver mct_u232_device = {  	.tiocmget =	     mct_u232_tiocmget,  	.tiocmset =	     mct_u232_tiocmset,  	.attach =	     mct_u232_startup, -	.release =	     mct_u232_release, +	.port_probe =        mct_u232_port_probe, +	.port_remove =       mct_u232_port_remove,  	.ioctl =             mct_u232_ioctl,  	.get_icount =        mct_u232_get_icount,  }; @@ -388,18 +390,8 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port,  static int mct_u232_startup(struct usb_serial *serial)  { -	struct mct_u232_private *priv;  	struct usb_serial_port *port, *rport; -	priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL); -	if (!priv) -		return -ENOMEM; -	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->msr_wait); -	usb_set_serial_port_data(serial->port[0], priv); - -	init_waitqueue_head(&serial->port[0]->write_wait); -  	/* Puh, that's dirty */  	port = serial->port[0];  	rport = serial->port[1]; @@ -412,18 +404,31 @@ static int mct_u232_startup(struct usb_serial *serial)  	return 0;  } /* mct_u232_startup */ +static int mct_u232_port_probe(struct usb_serial_port *port) +{ +	struct mct_u232_private *priv; + +	priv = kzalloc(sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; + +	spin_lock_init(&priv->lock); +	init_waitqueue_head(&priv->msr_wait); + +	usb_set_serial_port_data(port, priv); -static void mct_u232_release(struct usb_serial *serial) +	return 0; +} + +static int mct_u232_port_remove(struct usb_serial_port *port)  {  	struct mct_u232_private *priv; -	int i; -	for (i = 0; i < serial->num_ports; ++i) { -		/* My special items, the standard routines free my urbs */ -		priv = usb_get_serial_port_data(serial->port[i]); -		kfree(priv); -	} -} /* mct_u232_release */ +	priv = usb_get_serial_port_data(port); +	kfree(priv); + +	return 0; +}  static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)  { @@ -515,12 +520,14 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)  static void mct_u232_close(struct usb_serial_port *port)  { -	if (port->serial->dev) { -		/* shutdown our urbs */ -		usb_kill_urb(port->write_urb); -		usb_kill_urb(port->read_urb); -		usb_kill_urb(port->interrupt_in_urb); -	} +	/* +	 * Must kill the read urb as it is actually an interrupt urb, which +	 * generic close thus fails to kill. +	 */ +	usb_kill_urb(port->read_urb); +	usb_kill_urb(port->interrupt_in_urb); + +	usb_serial_generic_close(port);  } /* mct_u232_close */ diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 0b257ddffbd..6f29c74eb76 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -179,16 +179,13 @@ static void metrousb_cleanup(struct usb_serial_port *port)  {  	dev_dbg(&port->dev, "%s\n", __func__); -	if (port->serial->dev) { -		/* Shutdown any interrupt in urbs. */ -		if (port->interrupt_in_urb) { -			usb_unlink_urb(port->interrupt_in_urb); -			usb_kill_urb(port->interrupt_in_urb); -		} +	usb_unlink_urb(port->interrupt_in_urb); +	usb_kill_urb(port->interrupt_in_urb); -		/* Send deactivate cmd to device */ +	mutex_lock(&port->serial->disc_mutex); +	if (!port->serial->disconnected)  		metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); -	} +	mutex_unlock(&port->serial->disc_mutex);  }  static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -271,51 +268,27 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr  	return retval;  } -static void metrousb_shutdown(struct usb_serial *serial) +static int metrousb_port_probe(struct usb_serial_port *port)  { -	int i = 0; +	struct metrousb_private *metro_priv; -	dev_dbg(&serial->dev->dev, "%s\n", __func__); +	metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL); +	if (!metro_priv) +		return -ENOMEM; -	/* Stop reading and writing on all ports. */ -	for (i = 0; i < serial->num_ports; ++i) { -		/* Close any open urbs. */ -		metrousb_cleanup(serial->port[i]); +	spin_lock_init(&metro_priv->lock); -		/* Free memory. */ -		kfree(usb_get_serial_port_data(serial->port[i])); -		usb_set_serial_port_data(serial->port[i], NULL); +	usb_set_serial_port_data(port, metro_priv); -		dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n", -			__func__, serial->port[i]->number); -	} +	return 0;  } -static int metrousb_startup(struct usb_serial *serial) +static int metrousb_port_remove(struct usb_serial_port *port)  {  	struct metrousb_private *metro_priv; -	struct usb_serial_port *port; -	int i = 0; -	dev_dbg(&serial->dev->dev, "%s\n", __func__); - -	/* Loop through the serial ports setting up the private structures. -	 * Currently we only use one port. */ -	for (i = 0; i < serial->num_ports; ++i) { -		port = serial->port[i]; - -		/* Declare memory. */ -		metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL); -		if (!metro_priv) -			return -ENOMEM; - -		/* Initialize memory. */ -		spin_lock_init(&metro_priv->lock); -		usb_set_serial_port_data(port, metro_priv); - -		dev_dbg(&serial->dev->dev, "%s - port number=%d\n ", -			__func__, port->number); -	} +	metro_priv = usb_get_serial_port_data(port); +	kfree(metro_priv);  	return 0;  } @@ -414,8 +387,8 @@ static struct usb_serial_driver metrousb_device = {  	.close			= metrousb_cleanup,  	.read_int_callback	= metrousb_read_int_callback,  	.write_int_callback	= metrousb_write_int_callback, -	.attach			= metrousb_startup, -	.release		= metrousb_shutdown, +	.port_probe		= metrousb_port_probe, +	.port_remove		= metrousb_port_remove,  	.throttle		= metrousb_throttle,  	.unthrottle		= metrousb_unthrottle,  	.tiocmget		= metrousb_tiocmget, diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 1bf1ad06666..75267421aad 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1966,9 +1966,7 @@ static int mos7720_ioctl(struct tty_struct *tty,  static int mos7720_startup(struct usb_serial *serial)  { -	struct moschip_port *mos7720_port;  	struct usb_device *dev; -	int i;  	char data;  	u16 product;  	int ret_val; @@ -1999,29 +1997,6 @@ static int mos7720_startup(struct usb_serial *serial)  		serial->port[1]->interrupt_in_buffer = NULL;  	} - -	/* set up serial port private structures */ -	for (i = 0; i < serial->num_ports; ++i) { -		mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); -		if (mos7720_port == NULL) { -			dev_err(&dev->dev, "%s - Out of memory\n", __func__); -			return -ENOMEM; -		} - -		/* Initialize all port interrupt end point to port 0 int -		 * endpoint.  Our device has only one interrupt endpoint -		 * common to all ports */ -		serial->port[i]->interrupt_in_endpointAddress = -				serial->port[0]->interrupt_in_endpointAddress; - -		mos7720_port->port = serial->port[i]; -		usb_set_serial_port_data(serial->port[i], mos7720_port); - -		dev_dbg(&dev->dev, "port number is %d\n", serial->port[i]->number); -		dev_dbg(&dev->dev, "serial number is %d\n", serial->minor); -	} - -  	/* setting configuration feature to one */  	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),  			(__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ); @@ -2049,8 +2024,6 @@ static int mos7720_startup(struct usb_serial *serial)  static void mos7720_release(struct usb_serial *serial)  { -	int i; -  #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT  	/* close the parallel port */ @@ -2089,9 +2062,36 @@ static void mos7720_release(struct usb_serial *serial)  		kref_put(&mos_parport->ref_count, destroy_mos_parport);  	}  #endif -	/* free private structure allocated for serial port */ -	for (i = 0; i < serial->num_ports; ++i) -		kfree(usb_get_serial_port_data(serial->port[i])); +} + +static int mos7720_port_probe(struct usb_serial_port *port) +{ +	struct moschip_port *mos7720_port; + +	mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL); +	if (!mos7720_port) +		return -ENOMEM; + +	/* Initialize all port interrupt end point to port 0 int endpoint. +	 * Our device has only one interrupt endpoint common to all ports. +	 */ +	port->interrupt_in_endpointAddress = +		port->serial->port[0]->interrupt_in_endpointAddress; +	mos7720_port->port = port; + +	usb_set_serial_port_data(port, mos7720_port); + +	return 0; +} + +static int mos7720_port_remove(struct usb_serial_port *port) +{ +	struct moschip_port *mos7720_port; + +	mos7720_port = usb_get_serial_port_data(port); +	kfree(mos7720_port); + +	return 0;  }  static struct usb_serial_driver moschip7720_2port_driver = { @@ -2109,6 +2109,8 @@ static struct usb_serial_driver moschip7720_2port_driver = {  	.probe			= mos77xx_probe,  	.attach			= mos7720_startup,  	.release		= mos7720_release, +	.port_probe		= mos7720_port_probe, +	.port_remove		= mos7720_port_remove,  	.ioctl			= mos7720_ioctl,  	.tiocmget		= mos7720_tiocmget,  	.tiocmset		= mos7720_tiocmset, diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index d6d4eeca8c6..1cf3375ec1a 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -218,12 +218,10 @@ struct moschip_port {  	int port_num;		/*Actual port number in the device(1,2,etc) */  	struct urb *write_urb;	/* write URB for this port */  	struct urb *read_urb;	/* read URB for this port */ -	struct urb *int_urb;  	__u8 shadowLCR;		/* last LCR value received */  	__u8 shadowMCR;		/* last MCR value received */  	char open;  	char open_ports; -	char zombie;  	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */  	wait_queue_head_t delta_msr_wait;	/* for handling sleeping while waiting for msr change to happen */  	int delta_msr_cond; @@ -478,7 +476,6 @@ static void mos7840_control_callback(struct urb *urb)  	struct moschip_port *mos7840_port;  	struct device *dev = &urb->dev->dev;  	__u8 regval = 0x0; -	int result = 0;  	int status = urb->status;  	mos7840_port = urb->context; @@ -495,7 +492,7 @@ static void mos7840_control_callback(struct urb *urb)  		return;  	default:  		dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); -		goto exit; +		return;  	}  	dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length); @@ -508,16 +505,6 @@ static void mos7840_control_callback(struct urb *urb)  		mos7840_handle_new_msr(mos7840_port, regval);  	else if (mos7840_port->MsrLsr == 1)  		mos7840_handle_new_lsr(mos7840_port, regval); - -exit: -	spin_lock(&mos7840_port->pool_lock); -	if (!mos7840_port->zombie) -		result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC); -	spin_unlock(&mos7840_port->pool_lock); -	if (result) { -		dev_err(dev, "%s - Error %d submitting interrupt urb\n", -			__func__, result); -	}  }  static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, @@ -686,14 +673,7 @@ static void mos7840_interrupt_callback(struct urb *urb)  					wreg = MODEM_STATUS_REGISTER;  					break;  				} -				spin_lock(&mos7840_port->pool_lock); -				if (!mos7840_port->zombie) { -					rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); -				} else { -					spin_unlock(&mos7840_port->pool_lock); -					return; -				} -				spin_unlock(&mos7840_port->pool_lock); +				rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);  			}  		}  	} @@ -2347,309 +2327,249 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)  	return mos7840_num_ports;  } -/**************************************************************************** - * mos7840_startup - ****************************************************************************/ - -static int mos7840_startup(struct usb_serial *serial) +static int mos7840_port_probe(struct usb_serial_port *port)  { +	struct usb_serial *serial = port->serial;  	struct moschip_port *mos7840_port; -	struct usb_device *dev; -	int i, status; +	int status; +	int pnum;  	__u16 Data; -	dev = serial->dev; -  	/* we set up the pointers to the endpoints in the mos7840_open *  	 * function, as the structures aren't created yet.             */ -	/* set up port private structures */ -	for (i = 0; i < serial->num_ports; ++i) { -		dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i); -		mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); -		if (mos7840_port == NULL) { -			dev_err(&dev->dev, "%s - Out of memory\n", __func__); -			status = -ENOMEM; -			i--; /* don't follow NULL pointer cleaning up */ -			goto error; -		} +	pnum = port->number - serial->minor; -		/* Initialize all port interrupt end point to port 0 int -		 * endpoint. Our device has only one interrupt end point -		 * common to all port */ +	dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum); +	mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); +	if (mos7840_port == NULL) { +		dev_err(&port->dev, "%s - Out of memory\n", __func__); +		return -ENOMEM; +	} -		mos7840_port->port = serial->port[i]; -		mos7840_set_port_private(serial->port[i], mos7840_port); -		spin_lock_init(&mos7840_port->pool_lock); +	/* Initialize all port interrupt end point to port 0 int +	 * endpoint. Our device has only one interrupt end point +	 * common to all port */ -		/* minor is not initialised until later by -		 * usb-serial.c:get_free_serial() and cannot therefore be used -		 * to index device instances */ -		mos7840_port->port_num = i + 1; -		dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number); -		dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor); -		dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); -		dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor); +	mos7840_port->port = port; +	mos7840_set_port_private(port, mos7840_port); +	spin_lock_init(&mos7840_port->pool_lock); -		if (mos7840_port->port_num == 1) { -			mos7840_port->SpRegOffset = 0x0; -			mos7840_port->ControlRegOffset = 0x1; -			mos7840_port->DcrRegOffset = 0x4; -		} else if ((mos7840_port->port_num == 2) -			   && (serial->num_ports == 4)) { -			mos7840_port->SpRegOffset = 0x8; -			mos7840_port->ControlRegOffset = 0x9; -			mos7840_port->DcrRegOffset = 0x16; -		} else if ((mos7840_port->port_num == 2) -			   && (serial->num_ports == 2)) { -			mos7840_port->SpRegOffset = 0xa; -			mos7840_port->ControlRegOffset = 0xb; -			mos7840_port->DcrRegOffset = 0x19; -		} else if ((mos7840_port->port_num == 3) -			   && (serial->num_ports == 4)) { -			mos7840_port->SpRegOffset = 0xa; -			mos7840_port->ControlRegOffset = 0xb; -			mos7840_port->DcrRegOffset = 0x19; -		} else if ((mos7840_port->port_num == 4) -			   && (serial->num_ports == 4)) { -			mos7840_port->SpRegOffset = 0xc; -			mos7840_port->ControlRegOffset = 0xd; -			mos7840_port->DcrRegOffset = 0x1c; -		} -		mos7840_dump_serial_port(serial->port[i], mos7840_port); -		mos7840_set_port_private(serial->port[i], mos7840_port); +	/* minor is not initialised until later by +	 * usb-serial.c:get_free_serial() and cannot therefore be used +	 * to index device instances */ +	mos7840_port->port_num = pnum + 1; +	dev_dbg(&port->dev, "port->number = %d\n", port->number); +	dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); +	dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); +	dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor); -		/* enable rx_disable bit in control register */ -		status = mos7840_get_reg_sync(serial->port[i], -				 mos7840_port->ControlRegOffset, &Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); -		Data |= 0x08;	/* setting driver done bit */ -		Data |= 0x04;	/* sp1_bit to have cts change reflect in -				   modem status reg */ +	if (mos7840_port->port_num == 1) { +		mos7840_port->SpRegOffset = 0x0; +		mos7840_port->ControlRegOffset = 0x1; +		mos7840_port->DcrRegOffset = 0x4; +	} else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) { +		mos7840_port->SpRegOffset = 0x8; +		mos7840_port->ControlRegOffset = 0x9; +		mos7840_port->DcrRegOffset = 0x16; +	} else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) { +		mos7840_port->SpRegOffset = 0xa; +		mos7840_port->ControlRegOffset = 0xb; +		mos7840_port->DcrRegOffset = 0x19; +	} else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) { +		mos7840_port->SpRegOffset = 0xa; +		mos7840_port->ControlRegOffset = 0xb; +		mos7840_port->DcrRegOffset = 0x19; +	} else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) { +		mos7840_port->SpRegOffset = 0xc; +		mos7840_port->ControlRegOffset = 0xd; +		mos7840_port->DcrRegOffset = 0x1c; +	} +	mos7840_dump_serial_port(port, mos7840_port); +	mos7840_set_port_private(port, mos7840_port); -		/* Data |= 0x20; //rx_disable bit */ -		status = mos7840_set_reg_sync(serial->port[i], -					 mos7840_port->ControlRegOffset, Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status); +	/* enable rx_disable bit in control register */ +	status = mos7840_get_reg_sync(port, +			mos7840_port->ControlRegOffset, &Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); +	Data |= 0x08;	/* setting driver done bit */ +	Data |= 0x04;	/* sp1_bit to have cts change reflect in +			   modem status reg */ -		/* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 -		   and 0x24 in DCR3 */ -		Data = 0x01; -		status = mos7840_set_reg_sync(serial->port[i], -			 (__u16) (mos7840_port->DcrRegOffset + 0), Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status); +	/* Data |= 0x20; //rx_disable bit */ +	status = mos7840_set_reg_sync(port, +			mos7840_port->ControlRegOffset, Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status); -		Data = 0x05; -		status = mos7840_set_reg_sync(serial->port[i], -			 (__u16) (mos7840_port->DcrRegOffset + 1), Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status); +	/* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 +	   and 0x24 in DCR3 */ +	Data = 0x01; +	status = mos7840_set_reg_sync(port, +			(__u16) (mos7840_port->DcrRegOffset + 0), Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status); -		Data = 0x24; -		status = mos7840_set_reg_sync(serial->port[i], -			 (__u16) (mos7840_port->DcrRegOffset + 2), Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status); +	Data = 0x05; +	status = mos7840_set_reg_sync(port, +			(__u16) (mos7840_port->DcrRegOffset + 1), Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status); -		/* write values in clkstart0x0 and clkmulti 0x20 */ -		Data = 0x0; -		status = mos7840_set_reg_sync(serial->port[i], -					 CLK_START_VALUE_REGISTER, Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); +	Data = 0x24; +	status = mos7840_set_reg_sync(port, +			(__u16) (mos7840_port->DcrRegOffset + 2), Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status); -		Data = 0x20; -		status = mos7840_set_reg_sync(serial->port[i], -					CLK_MULTI_REGISTER, Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); -			goto error; -		} else -			dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); +	/* write values in clkstart0x0 and clkmulti 0x20 */ +	Data = 0x0; +	status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); -		/* write value 0x0 to scratchpad register */ -		Data = 0x00; -		status = mos7840_set_uart_reg(serial->port[i], -						SCRATCH_PAD_REGISTER, Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); +	Data = 0x20; +	status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); +		goto error; +	} else +		dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); -		/* Zero Length flag register */ -		if ((mos7840_port->port_num != 1) -		    && (serial->num_ports == 2)) { +	/* write value 0x0 to scratchpad register */ +	Data = 0x00; +	status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); -			Data = 0xff; -			status = mos7840_set_reg_sync(serial->port[i], -				      (__u16) (ZLP_REG1 + -				      ((__u16)mos7840_port->port_num)), Data); -			dev_dbg(&dev->dev, "ZLIP offset %x\n", +	/* Zero Length flag register */ +	if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) { +		Data = 0xff; +		status = mos7840_set_reg_sync(port, +				(__u16) (ZLP_REG1 + +					((__u16)mos7840_port->port_num)), Data); +		dev_dbg(&port->dev, "ZLIP offset %x\n",  				(__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); -			if (status < 0) { -				dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status); -				break; -			} else -				dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status); -		} else { -			Data = 0xff; -			status = mos7840_set_reg_sync(serial->port[i], -			      (__u16) (ZLP_REG1 + -			      ((__u16)mos7840_port->port_num) - 0x1), Data); -			dev_dbg(&dev->dev, "ZLIP offset %x\n", +		if (status < 0) { +			dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status); +			goto out; +		} else +			dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status); +	} else { +		Data = 0xff; +		status = mos7840_set_reg_sync(port, +				(__u16) (ZLP_REG1 + +					((__u16)mos7840_port->port_num) - 0x1), Data); +		dev_dbg(&port->dev, "ZLIP offset %x\n",  				(__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); -			if (status < 0) { -				dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status); -				break; -			} else -				dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status); +		if (status < 0) { +			dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status); +			goto out; +		} else +			dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status); -		} -		mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); -		mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); -		mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), -								GFP_KERNEL); -		if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || -							!mos7840_port->dr) { -			status = -ENOMEM; -			goto error; -		} +	} +	mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); +	mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); +	mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), +			GFP_KERNEL); +	if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || +			!mos7840_port->dr) { +		status = -ENOMEM; +		goto error; +	} -		mos7840_port->has_led = false; +	mos7840_port->has_led = false; -		/* Initialize LED timers */ -		if (device_type == MOSCHIP_DEVICE_ID_7810) { -			mos7840_port->has_led = true; +	/* Initialize LED timers */ +	if (device_type == MOSCHIP_DEVICE_ID_7810) { +		mos7840_port->has_led = true; -			init_timer(&mos7840_port->led_timer1); -			mos7840_port->led_timer1.function = mos7840_led_off; -			mos7840_port->led_timer1.expires = -					jiffies + msecs_to_jiffies(LED_ON_MS); -			mos7840_port->led_timer1.data = -						(unsigned long)mos7840_port; +		init_timer(&mos7840_port->led_timer1); +		mos7840_port->led_timer1.function = mos7840_led_off; +		mos7840_port->led_timer1.expires = +			jiffies + msecs_to_jiffies(LED_ON_MS); +		mos7840_port->led_timer1.data = (unsigned long)mos7840_port; -			init_timer(&mos7840_port->led_timer2); -			mos7840_port->led_timer2.function = -						mos7840_led_flag_off; -			mos7840_port->led_timer2.expires = -					jiffies + msecs_to_jiffies(LED_OFF_MS); -			mos7840_port->led_timer2.data = -						(unsigned long)mos7840_port; +		init_timer(&mos7840_port->led_timer2); +		mos7840_port->led_timer2.function = mos7840_led_flag_off; +		mos7840_port->led_timer2.expires = +			jiffies + msecs_to_jiffies(LED_OFF_MS); +		mos7840_port->led_timer2.data = (unsigned long)mos7840_port; -			mos7840_port->led_flag = false; +		mos7840_port->led_flag = false; -			/* Turn off LED */ -			mos7840_set_led_sync(serial->port[i], -						MODEM_CONTROL_REGISTER, 0x0300); -		} +		/* Turn off LED */ +		mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);  	} +out: +	if (pnum == serial->num_ports - 1) { +		/* Zero Length flag enable */ +		Data = 0x0f; +		status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); +		if (status < 0) { +			dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); +			goto error; +		} else +			dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status); -	/* Zero Length flag enable */ -	Data = 0x0f; -	status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); -	if (status < 0) { -		dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); -		goto error; -	} else -		dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status); - -	/* setting configuration feature to one */ -	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), -			(__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT); +		/* setting configuration feature to one */ +		usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), +				0x03, 0x00, 0x01, 0x00, NULL, 0x00, +				MOS_WDR_TIMEOUT); +	}  	return 0;  error: -	for (/* nothing */; i >= 0; i--) { -		mos7840_port = mos7840_get_port_private(serial->port[i]); +	kfree(mos7840_port->dr); +	kfree(mos7840_port->ctrl_buf); +	usb_free_urb(mos7840_port->control_urb); +	kfree(mos7840_port); -		kfree(mos7840_port->dr); -		kfree(mos7840_port->ctrl_buf); -		usb_free_urb(mos7840_port->control_urb); -		kfree(mos7840_port); -		serial->port[i] = NULL; -	}  	return status;  } -/**************************************************************************** - * mos7840_disconnect - *	This function is called whenever the device is removed from the usb bus. - ****************************************************************************/ - -static void mos7840_disconnect(struct usb_serial *serial) +static int mos7840_port_remove(struct usb_serial_port *port)  { -	int i; -	unsigned long flags;  	struct moschip_port *mos7840_port; -	/* check for the ports to be closed,close the ports and disconnect */ +	mos7840_port = mos7840_get_port_private(port); -	/* free private structure allocated for serial port  * -	 * stop reads and writes on all ports                */ +	if (mos7840_port->has_led) { +		/* Turn off LED */ +		mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); -	for (i = 0; i < serial->num_ports; ++i) { -		mos7840_port = mos7840_get_port_private(serial->port[i]); -		if (mos7840_port) { -			spin_lock_irqsave(&mos7840_port->pool_lock, flags); -			mos7840_port->zombie = 1; -			spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); -			usb_kill_urb(mos7840_port->control_urb); -		} +		del_timer_sync(&mos7840_port->led_timer1); +		del_timer_sync(&mos7840_port->led_timer2);  	} -} - -/**************************************************************************** - * mos7840_release - *	This function is called when the usb_serial structure is freed. - ****************************************************************************/ - -static void mos7840_release(struct usb_serial *serial) -{ -	int i; -	struct moschip_port *mos7840_port; - -	/* check for the ports to be closed,close the ports and disconnect */ +	usb_kill_urb(mos7840_port->control_urb); +	usb_free_urb(mos7840_port->control_urb); +	kfree(mos7840_port->ctrl_buf); +	kfree(mos7840_port->dr); +	kfree(mos7840_port); -	/* free private structure allocated for serial port  * -	 * stop reads and writes on all ports                */ - -	for (i = 0; i < serial->num_ports; ++i) { -		mos7840_port = mos7840_get_port_private(serial->port[i]); -		if (mos7840_port) { -			if (mos7840_port->has_led) { -				/* Turn off LED */ -				mos7840_set_led_sync(mos7840_port->port, -						MODEM_CONTROL_REGISTER, 0x0300); - -				del_timer_sync(&mos7840_port->led_timer1); -				del_timer_sync(&mos7840_port->led_timer2); -			} -			kfree(mos7840_port->ctrl_buf); -			kfree(mos7840_port->dr); -			kfree(mos7840_port); -		} -	} +	return 0;  }  static struct usb_serial_driver moschip7840_4port_device = { @@ -2677,9 +2597,8 @@ static struct usb_serial_driver moschip7840_4port_device = {  	.tiocmget = mos7840_tiocmget,  	.tiocmset = mos7840_tiocmset,  	.get_icount = mos7840_get_icount, -	.attach = mos7840_startup, -	.disconnect = mos7840_disconnect, -	.release = mos7840_release, +	.port_probe = mos7840_port_probe, +	.port_remove = mos7840_port_remove,  	.read_bulk_callback = mos7840_bulk_in_callback,  	.read_int_callback = mos7840_interrupt_callback,  }; diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 6def58b7938..9ab73d29577 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -44,8 +44,8 @@ static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,  				const unsigned char *buf, int count);  static int  omninet_write_room(struct tty_struct *tty);  static void omninet_disconnect(struct usb_serial *serial); -static void omninet_release(struct usb_serial *serial); -static int omninet_attach(struct usb_serial *serial); +static int omninet_port_probe(struct usb_serial_port *port); +static int omninet_port_remove(struct usb_serial_port *port);  static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) }, @@ -62,7 +62,8 @@ static struct usb_serial_driver zyxel_omninet_device = {  	.description =		"ZyXEL - omni.net lcd plus usb",  	.id_table =		id_table,  	.num_ports =		1, -	.attach =		omninet_attach, +	.port_probe =		omninet_port_probe, +	.port_remove =		omninet_port_remove,  	.open =			omninet_open,  	.close =		omninet_close,  	.write =		omninet_write, @@ -70,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = {  	.read_bulk_callback =	omninet_read_bulk_callback,  	.write_bulk_callback =	omninet_write_bulk_callback,  	.disconnect =		omninet_disconnect, -	.release =		omninet_release,  };  static struct usb_serial_driver * const serial_drivers[] = { @@ -112,18 +112,26 @@ struct omninet_data {  	__u8	od_outseq;	/* Sequence number for bulk_out URBs */  }; -static int omninet_attach(struct usb_serial *serial) +static int omninet_port_probe(struct usb_serial_port *port)  {  	struct omninet_data *od; -	struct usb_serial_port *port = serial->port[0];  	od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL); -	if (!od) { -		dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", -			__func__, sizeof(struct omninet_data)); +	if (!od)  		return -ENOMEM; -	} +  	usb_set_serial_port_data(port, od); + +	return 0; +} + +static int omninet_port_remove(struct usb_serial_port *port) +{ +	struct omninet_data *od; + +	od = usb_get_serial_port_data(port); +	kfree(od); +  	return 0;  } @@ -279,14 +287,6 @@ static void omninet_disconnect(struct usb_serial *serial)  	usb_kill_urb(wport->write_urb);  } - -static void omninet_release(struct usb_serial *serial) -{ -	struct usb_serial_port *port = serial->port[0]; - -	kfree(usb_get_serial_port_data(port)); -} -  module_usb_serial_driver(serial_drivers, id_table);  MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 41b1647306e..6aba731d486 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -155,7 +155,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,  {  	struct usb_serial *serial = port->serial;  	int retval; -	u8 buffer[2]; +	u8 *buffer; + +	buffer = kzalloc(1, GFP_KERNEL); +	if (!buffer) +		return -ENOMEM;  	buffer[0] = val;  	/* Send the message to the vendor control endpoint @@ -164,6 +168,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,  				requesttype,  				USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,  				0, 0, buffer, 1, 0); +	kfree(buffer);  	return retval;  } @@ -281,7 +286,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,  	if (!dr) {  		dev_err(&port->dev, "out of memory\n");  		count = -ENOMEM; -		goto error; +		goto error_no_dr;  	}  	dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; @@ -311,6 +316,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,  	return count;  error: +	kfree(dr); +error_no_dr:  	usb_free_urb(urb);  error_no_urb:  	kfree(buffer); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 54d4148d01d..5dee7d61241 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -47,6 +47,7 @@  /* Function prototypes */  static int  option_probe(struct usb_serial *serial,  			const struct usb_device_id *id); +static int option_attach(struct usb_serial *serial);  static void option_release(struct usb_serial *serial);  static int option_send_setup(struct usb_serial_port *port);  static void option_instat_callback(struct urb *urb); @@ -1288,8 +1289,9 @@ static struct usb_serial_driver option_1port_device = {  	.tiocmget          = usb_wwan_tiocmget,  	.tiocmset          = usb_wwan_tiocmset,  	.ioctl             = usb_wwan_ioctl, -	.attach            = usb_wwan_startup, +	.attach            = option_attach,  	.release           = option_release, +	.port_probe        = usb_wwan_port_probe,  	.port_remove	   = usb_wwan_port_remove,  	.read_int_callback = option_instat_callback,  #ifdef CONFIG_PM @@ -1335,8 +1337,6 @@ static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason,  static int option_probe(struct usb_serial *serial,  			const struct usb_device_id *id)  { -	struct usb_wwan_intf_private *data; -	struct option_private *priv;  	struct usb_interface_descriptor *iface_desc =  				&serial->interface->cur_altsetting->desc;  	struct usb_device_descriptor *dev_desc = &serial->dev->descriptor; @@ -1374,6 +1374,19 @@ static int option_probe(struct usb_serial *serial,  		iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)  		return -ENODEV; +	/* Store device id so we can use it during attach. */ +	usb_set_serial_data(serial, (void *)id); + +	return 0; +} + +static int option_attach(struct usb_serial *serial) +{ +	struct usb_interface_descriptor *iface_desc; +	const struct usb_device_id *id; +	struct usb_wwan_intf_private *data; +	struct option_private *priv; +  	data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);  	if (!data)  		return -ENOMEM; @@ -1384,6 +1397,10 @@ static int option_probe(struct usb_serial *serial,  		return -ENOMEM;  	} +	/* Retrieve device id stored at probe. */ +	id = usb_get_serial_data(serial); +	iface_desc = &serial->interface->cur_altsetting->desc; +  	priv->bInterfaceNumber = iface_desc->bInterfaceNumber;  	data->private = priv; diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index c3ddb65c05f..aa148c21ea4 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -138,7 +138,6 @@ MODULE_DEVICE_TABLE(usb, id_table);  static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)  { -	struct usb_wwan_intf_private *data;  	struct usb_host_interface *intf = serial->interface->cur_altsetting;  	struct device *dev = &serial->dev->dev;  	int retval = -ENODEV; @@ -154,13 +153,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)  	ifnum = intf->desc.bInterfaceNumber;  	dev_dbg(dev, "This Interface = %d\n", ifnum); -	data = kzalloc(sizeof(struct usb_wwan_intf_private), -					 GFP_KERNEL); -	if (!data) -		return -ENOMEM; - -	spin_lock_init(&data->susp_lock); -  	if (nintf == 1) {  		/* QDL mode */  		/* Gobi 2000 has a single altsetting, older ones have two */ @@ -253,20 +245,28 @@ done:  		}  	} -	/* Set serial->private if not returning error */ -	if (retval == 0) -		usb_set_serial_data(serial, data); -	else -		kfree(data); -  	return retval;  } +static int qc_attach(struct usb_serial *serial) +{ +	struct usb_wwan_intf_private *data; + +	data = kzalloc(sizeof(*data), GFP_KERNEL); +	if (!data) +		return -ENOMEM; + +	spin_lock_init(&data->susp_lock); + +	usb_set_serial_data(serial, data); + +	return 0; +} +  static void qc_release(struct usb_serial *serial)  {  	struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); -	/* Free the private data allocated in qcprobe */  	usb_set_serial_data(serial, NULL);  	kfree(priv);  } @@ -285,8 +285,9 @@ static struct usb_serial_driver qcdevice = {  	.write		     = usb_wwan_write,  	.write_room	     = usb_wwan_write_room,  	.chars_in_buffer     = usb_wwan_chars_in_buffer, -	.attach		     = usb_wwan_startup, +	.attach              = qc_attach,  	.release	     = qc_release, +	.port_probe          = usb_wwan_port_probe,  	.port_remove	     = usb_wwan_port_remove,  #ifdef CONFIG_PM  	.suspend	     = usb_wwan_suspend, diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 2cdfdcc90b3..ffcfc962ab1 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -143,12 +143,12 @@ static void qt2_read_bulk_callback(struct urb *urb);  static void qt2_release(struct usb_serial *serial)  { -	int i; +	struct qt2_serial_private *serial_priv; -	kfree(usb_get_serial_data(serial)); +	serial_priv = usb_get_serial_data(serial); -	for (i = 0; i < serial->num_ports; i++) -		kfree(usb_get_serial_port_data(serial->port[i])); +	usb_free_urb(serial_priv->read_urb); +	kfree(serial_priv);  }  static inline int calc_baud_divisor(int baudrate) @@ -423,11 +423,16 @@ static void qt2_close(struct usb_serial_port *port)  	port_priv->is_open = false;  	spin_lock_irqsave(&port_priv->urb_lock, flags); -	if (port_priv->write_urb->status == -EINPROGRESS) -		usb_kill_urb(port_priv->write_urb); +	usb_kill_urb(port_priv->write_urb);  	port_priv->urb_in_use = false;  	spin_unlock_irqrestore(&port_priv->urb_lock, flags); +	mutex_lock(&port->serial->disc_mutex); +	if (port->serial->disconnected) { +		mutex_unlock(&port->serial->disc_mutex); +		return; +	} +  	/* flush the port transmit buffer */  	i = usb_control_msg(serial->dev,  			    usb_rcvctrlpipe(serial->dev, 0), @@ -459,26 +464,14 @@ static void qt2_close(struct usb_serial_port *port)  		dev_err(&port->dev, "%s - close port failed %i\n",  			__func__, i); +	mutex_unlock(&port->serial->disc_mutex);  }  static void qt2_disconnect(struct usb_serial *serial)  {  	struct qt2_serial_private *serial_priv = usb_get_serial_data(serial); -	struct qt2_port_private *port_priv; -	int i; - -	if (serial_priv->read_urb->status == -EINPROGRESS) -		usb_kill_urb(serial_priv->read_urb); - -	usb_free_urb(serial_priv->read_urb); -	for (i = 0; i < serial->num_ports; i++) { -		port_priv = usb_get_serial_port_data(serial->port[i]); - -		if (port_priv->write_urb->status == -EINPROGRESS) -			usb_kill_urb(port_priv->write_urb); -		usb_free_urb(port_priv->write_urb); -	} +	usb_kill_urb(serial_priv->read_urb);  }  static int get_serial_info(struct usb_serial_port *port, @@ -773,11 +766,9 @@ static void qt2_read_bulk_callback(struct urb *urb)  static int qt2_setup_urbs(struct usb_serial *serial)  { -	struct usb_serial_port *port;  	struct usb_serial_port *port0;  	struct qt2_serial_private *serial_priv; -	struct qt2_port_private *port_priv; -	int pcount, status; +	int status;  	port0 = serial->port[0]; @@ -795,46 +786,21 @@ static int qt2_setup_urbs(struct usb_serial *serial)  			  sizeof(serial_priv->read_buffer),  			  qt2_read_bulk_callback, serial); -	/* setup write_urb for each port */ -	for (pcount = 0; pcount < serial->num_ports; pcount++) { - -		port = serial->port[pcount]; -		port_priv = usb_get_serial_port_data(port); - -		port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); -		if (!port_priv->write_urb) { -			dev_err(&serial->dev->dev, -				"failed to alloc write_urb for port %i\n", -				pcount); -			return -ENOMEM; -		} - -		usb_fill_bulk_urb(port_priv->write_urb, -				  serial->dev, -				  usb_sndbulkpipe(serial->dev, -						  port0-> -						  bulk_out_endpointAddress), -				  port_priv->write_buffer, -				  sizeof(port_priv->write_buffer), -				  qt2_write_bulk_callback, port); -	} -  	status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL);  	if (status != 0) {  		dev_err(&serial->dev->dev,  			"%s - submit read urb failed %i\n", __func__, status); +		usb_free_urb(serial_priv->read_urb);  		return status;  	}  	return 0; -  }  static int qt2_attach(struct usb_serial *serial)  {  	struct qt2_serial_private *serial_priv; -	struct qt2_port_private *port_priv; -	int status, pcount; +	int status;  	/* power on unit */  	status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -854,26 +820,6 @@ static int qt2_attach(struct usb_serial *serial)  	usb_set_serial_data(serial, serial_priv); -	for (pcount = 0; pcount < serial->num_ports; pcount++) { -		port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); -		if (!port_priv) { -			dev_err(&serial->dev->dev, -				"%s- kmalloc(%Zd) failed.\n", __func__, -				sizeof(*port_priv)); -			pcount--; -			status = -ENOMEM; -			goto attach_failed; -		} - -		spin_lock_init(&port_priv->lock); -		spin_lock_init(&port_priv->urb_lock); -		init_waitqueue_head(&port_priv->delta_msr_wait); - -		port_priv->port = serial->port[pcount]; - -		usb_set_serial_port_data(serial->port[pcount], port_priv); -	} -  	status = qt2_setup_urbs(serial);  	if (status != 0)  		goto attach_failed; @@ -881,14 +827,53 @@ static int qt2_attach(struct usb_serial *serial)  	return 0;  attach_failed: -	for (/* empty */; pcount >= 0; pcount--) { -		port_priv = usb_get_serial_port_data(serial->port[pcount]); -		kfree(port_priv); -	}  	kfree(serial_priv);  	return status;  } +static int qt2_port_probe(struct usb_serial_port *port) +{ +	struct usb_serial *serial = port->serial; +	struct qt2_port_private *port_priv; +	u8 bEndpointAddress; + +	port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); +	if (!port_priv) +		return -ENOMEM; + +	spin_lock_init(&port_priv->lock); +	spin_lock_init(&port_priv->urb_lock); +	init_waitqueue_head(&port_priv->delta_msr_wait); +	port_priv->port = port; + +	port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); +	if (!port_priv->write_urb) { +		kfree(port_priv); +		return -ENOMEM; +	} +	bEndpointAddress = serial->port[0]->bulk_out_endpointAddress; +	usb_fill_bulk_urb(port_priv->write_urb, serial->dev, +				usb_sndbulkpipe(serial->dev, bEndpointAddress), +				port_priv->write_buffer, +				sizeof(port_priv->write_buffer), +				qt2_write_bulk_callback, port); + +	usb_set_serial_port_data(port, port_priv); + +	return 0; +} + +static int qt2_port_remove(struct usb_serial_port *port) +{ +	struct qt2_port_private *port_priv; + +	port_priv = usb_get_serial_port_data(port); +	usb_free_urb(port_priv->write_urb); +	kfree(port_priv); + +	return 0; +} +  static int qt2_tiocmget(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; @@ -1127,6 +1112,8 @@ static struct usb_serial_driver qt2_device = {  	.attach              = qt2_attach,  	.release             = qt2_release,  	.disconnect          = qt2_disconnect, +	.port_probe          = qt2_port_probe, +	.port_remove         = qt2_port_remove,  	.dtr_rts             = qt2_dtr_rts,  	.break_ctl           = qt2_break_ctl,  	.tiocmget            = qt2_tiocmget, diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 01d882cf377..270860f6bb2 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -161,7 +161,6 @@ static int sierra_probe(struct usb_serial *serial,  {  	int result = 0;  	struct usb_device *udev; -	struct sierra_intf_private *data;  	u8 ifnum;  	udev = serial->dev; @@ -188,11 +187,6 @@ static int sierra_probe(struct usb_serial *serial,  		return -ENODEV;  	} -	data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL); -	if (!data) -		return -ENOMEM; -	spin_lock_init(&data->susp_lock); -  	return result;  } @@ -884,11 +878,15 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on)  static int sierra_startup(struct usb_serial *serial)  { -	struct usb_serial_port *port; -	struct sierra_port_private *portdata; -	struct sierra_iface_info *himemoryp = NULL; -	int i; -	u8 ifnum; +	struct sierra_intf_private *intfdata; + +	intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL); +	if (!intfdata) +		return -ENOMEM; + +	spin_lock_init(&intfdata->susp_lock); + +	usb_set_serial_data(serial, intfdata);  	/* Set Device mode to D0 */  	sierra_set_power_state(serial->dev, 0x0000); @@ -897,68 +895,71 @@ static int sierra_startup(struct usb_serial *serial)  	if (nmea)  		sierra_vsc_set_nmea(serial->dev, 1); -	/* Now setup per port private data */ -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); -		if (!portdata) { -			dev_dbg(&port->dev, "%s: kmalloc for " -				"sierra_port_private (%d) failed!\n", -				__func__, i); -			return -ENOMEM; -		} -		spin_lock_init(&portdata->lock); -		init_usb_anchor(&portdata->active); -		init_usb_anchor(&portdata->delayed); -		ifnum = i; -		/* Assume low memory requirements */ -		portdata->num_out_urbs = N_OUT_URB; -		portdata->num_in_urbs  = N_IN_URB; +	return 0; +} -		/* Determine actual memory requirements */ -		if (serial->num_ports == 1) { -			/* Get interface number for composite device */ -			ifnum = sierra_calc_interface(serial); -			himemoryp = -			    (struct sierra_iface_info *)&typeB_interface_list; -			if (is_himemory(ifnum, himemoryp)) { -				portdata->num_out_urbs = N_OUT_URB_HM; -				portdata->num_in_urbs  = N_IN_URB_HM; -			} -		} -		else { -			himemoryp = -			    (struct sierra_iface_info *)&typeA_interface_list; -			if (is_himemory(i, himemoryp)) { -				portdata->num_out_urbs = N_OUT_URB_HM; -				portdata->num_in_urbs  = N_IN_URB_HM; -			} -		} -		dev_dbg(&serial->dev->dev, -			"Memory usage (urbs) interface #%d, in=%d, out=%d\n", -			ifnum,portdata->num_in_urbs, portdata->num_out_urbs ); -		/* Set the port private data pointer */ -		usb_set_serial_port_data(port, portdata); +static void sierra_release(struct usb_serial *serial) +{ +	struct sierra_intf_private *intfdata; + +	intfdata = usb_get_serial_data(serial); +	kfree(intfdata); +} + +static int sierra_port_probe(struct usb_serial_port *port) +{ +	struct usb_serial *serial = port->serial; +	struct sierra_port_private *portdata; +	const struct sierra_iface_info *himemoryp; +	u8 ifnum; + +	portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); +	if (!portdata) +		return -ENOMEM; + +	spin_lock_init(&portdata->lock); +	init_usb_anchor(&portdata->active); +	init_usb_anchor(&portdata->delayed); + +	/* Assume low memory requirements */ +	portdata->num_out_urbs = N_OUT_URB; +	portdata->num_in_urbs  = N_IN_URB; + +	/* Determine actual memory requirements */ +	if (serial->num_ports == 1) { +		/* Get interface number for composite device */ +		ifnum = sierra_calc_interface(serial); +		himemoryp = &typeB_interface_list; +	} else { +		/* This is really the usb-serial port number of the interface +		 * rather than the interface number. +		 */ +		ifnum = port->number - serial->minor; +		himemoryp = &typeA_interface_list;  	} +	if (is_himemory(ifnum, himemoryp)) { +		portdata->num_out_urbs = N_OUT_URB_HM; +		portdata->num_in_urbs  = N_IN_URB_HM; +	} + +	dev_dbg(&port->dev, +			"Memory usage (urbs) interface #%d, in=%d, out=%d\n", +			ifnum, portdata->num_in_urbs, portdata->num_out_urbs); + +	usb_set_serial_port_data(port, portdata); +  	return 0;  } -static void sierra_release(struct usb_serial *serial) +static int sierra_port_remove(struct usb_serial_port *port)  { -	int i; -	struct usb_serial_port *port;  	struct sierra_port_private *portdata; -	for (i = 0; i < serial->num_ports; ++i) { -		port = serial->port[i]; -		if (!port) -			continue; -		portdata = usb_get_serial_port_data(port); -		if (!portdata) -			continue; -		kfree(portdata); -	} +	portdata = usb_get_serial_port_data(port); +	kfree(portdata); + +	return 0;  }  #ifdef CONFIG_PM @@ -1062,6 +1063,8 @@ static struct usb_serial_driver sierra_device = {  	.tiocmset          = sierra_tiocmset,  	.attach            = sierra_startup,  	.release           = sierra_release, +	.port_probe        = sierra_port_probe, +	.port_remove       = sierra_port_remove,  	.suspend	   = sierra_suspend,  	.resume		   = sierra_resume,  	.read_int_callback = sierra_instat_callback, diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 1f034d2397c..684739b8efd 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -8,7 +8,7 @@  extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on);  extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port);  extern void usb_wwan_close(struct usb_serial_port *port); -extern int usb_wwan_startup(struct usb_serial *serial); +extern int usb_wwan_port_probe(struct usb_serial_port *port);  extern int usb_wwan_port_remove(struct usb_serial_port *port);  extern int usb_wwan_write_room(struct tty_struct *tty);  extern void usb_wwan_set_termios(struct tty_struct *tty, diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index e42aa398ed3..61a73ad1a18 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -447,10 +447,12 @@ void usb_wwan_close(struct usb_serial_port *port)  EXPORT_SYMBOL(usb_wwan_close);  /* Helper functions used by usb_wwan_setup_urbs */ -static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, +static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, +				      int endpoint,  				      int dir, void *ctx, char *buf, int len,  				      void (*callback) (struct urb *))  { +	struct usb_serial *serial = port->serial;  	struct urb *urb;  	if (endpoint == -1) @@ -472,101 +474,75 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,  	return urb;  } -/* Setup urbs */ -static void usb_wwan_setup_urbs(struct usb_serial *serial) +int usb_wwan_port_probe(struct usb_serial_port *port)  { -	int i, j; -	struct usb_serial_port *port;  	struct usb_wwan_port_private *portdata; +	struct urb *urb; +	u8 *buffer; +	int err; +	int i; -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		portdata = usb_get_serial_port_data(port); +	portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); +	if (!portdata) +		return -ENOMEM; -		/* Do indat endpoints first */ -		for (j = 0; j < N_IN_URB; ++j) { -			portdata->in_urbs[j] = usb_wwan_setup_urb(serial, -								  port-> -								  bulk_in_endpointAddress, -								  USB_DIR_IN, -								  port, -								  portdata-> -								  in_buffer[j], -								  IN_BUFLEN, -								  usb_wwan_indat_callback); -		} +	init_usb_anchor(&portdata->delayed); -		/* outdat endpoints */ -		for (j = 0; j < N_OUT_URB; ++j) { -			portdata->out_urbs[j] = usb_wwan_setup_urb(serial, -								   port-> -								   bulk_out_endpointAddress, -								   USB_DIR_OUT, -								   port, -								   portdata-> -								   out_buffer -								   [j], -								   OUT_BUFLEN, -								   usb_wwan_outdat_callback); -		} -	} -} +	for (i = 0; i < N_IN_URB; i++) { +		buffer = (u8 *)__get_free_page(GFP_KERNEL); +		if (!buffer) +			goto bail_out_error; +		portdata->in_buffer[i] = buffer; -int usb_wwan_startup(struct usb_serial *serial) -{ -	int i, j, err; -	struct usb_serial_port *port; -	struct usb_wwan_port_private *portdata; -	u8 *buffer; +		urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress, +						USB_DIR_IN, port, +						buffer, IN_BUFLEN, +						usb_wwan_indat_callback); +		portdata->in_urbs[i] = urb; +	} -	/* Now setup per port private data */ -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); -		if (!portdata) { -			dev_dbg(&port->dev, "%s: kmalloc for usb_wwan_port_private (%d) failed!.\n", -				__func__, i); -			return 1; -		} -		init_usb_anchor(&portdata->delayed); +	for (i = 0; i < N_OUT_URB; i++) { +		if (port->bulk_out_endpointAddress == -1) +			continue; -		for (j = 0; j < N_IN_URB; j++) { -			buffer = (u8 *) __get_free_page(GFP_KERNEL); -			if (!buffer) -				goto bail_out_error; -			portdata->in_buffer[j] = buffer; -		} +		buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); +		if (!buffer) +			goto bail_out_error2; +		portdata->out_buffer[i] = buffer; -		for (j = 0; j < N_OUT_URB; j++) { -			buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); -			if (!buffer) -				goto bail_out_error2; -			portdata->out_buffer[j] = buffer; -		} +		urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress, +						USB_DIR_OUT, port, +						buffer, OUT_BUFLEN, +						usb_wwan_outdat_callback); +		portdata->out_urbs[i] = urb; +	} -		usb_set_serial_port_data(port, portdata); +	usb_set_serial_port_data(port, portdata); -		if (!port->interrupt_in_urb) -			continue; +	if (port->interrupt_in_urb) {  		err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);  		if (err)  			dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n",  				__func__, err);  	} -	usb_wwan_setup_urbs(serial); +  	return 0;  bail_out_error2: -	for (j = 0; j < N_OUT_URB; j++) -		kfree(portdata->out_buffer[j]); +	for (i = 0; i < N_OUT_URB; i++) { +		usb_free_urb(portdata->out_urbs[i]); +		kfree(portdata->out_buffer[i]); +	}  bail_out_error: -	for (j = 0; j < N_IN_URB; j++) -		if (portdata->in_buffer[j]) -			free_page((unsigned long)portdata->in_buffer[j]); +	for (i = 0; i < N_IN_URB; i++) { +		usb_free_urb(portdata->in_urbs[i]); +		free_page((unsigned long)portdata->in_buffer[i]); +	}  	kfree(portdata); -	return 1; + +	return -ENOMEM;  } -EXPORT_SYMBOL(usb_wwan_startup); +EXPORT_SYMBOL_GPL(usb_wwan_port_probe);  int usb_wwan_port_remove(struct usb_serial_port *port)  { diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 346c7efc20b..b9fca3586d7 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -83,6 +83,8 @@ static int  whiteheat_firmware_attach(struct usb_serial *serial);  /* function prototypes for the Connect Tech WhiteHEAT serial converter */  static int  whiteheat_attach(struct usb_serial *serial);  static void whiteheat_release(struct usb_serial *serial); +static int  whiteheat_port_probe(struct usb_serial_port *port); +static int  whiteheat_port_remove(struct usb_serial_port *port);  static int  whiteheat_open(struct tty_struct *tty,  			struct usb_serial_port *port);  static void whiteheat_close(struct usb_serial_port *port); @@ -117,6 +119,8 @@ static struct usb_serial_driver whiteheat_device = {  	.num_ports =		4,  	.attach =		whiteheat_attach,  	.release =		whiteheat_release, +	.port_probe =		whiteheat_port_probe, +	.port_remove =		whiteheat_port_remove,  	.open =			whiteheat_open,  	.close =		whiteheat_close,  	.ioctl =		whiteheat_ioctl, @@ -218,15 +222,12 @@ static int whiteheat_attach(struct usb_serial *serial)  {  	struct usb_serial_port *command_port;  	struct whiteheat_command_private *command_info; -	struct usb_serial_port *port; -	struct whiteheat_private *info;  	struct whiteheat_hw_info *hw_info;  	int pipe;  	int ret;  	int alen;  	__u8 *command;  	__u8 *result; -	int i;  	command_port = serial->port[COMMAND_PORT]; @@ -285,22 +286,6 @@ static int whiteheat_attach(struct usb_serial *serial)  		 serial->type->description,  		 hw_info->sw_major_rev, hw_info->sw_minor_rev); -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; - -		info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL); -		if (info == NULL) { -			dev_err(&port->dev, -				"%s: Out of memory for port structures\n", -				serial->type->description); -			goto no_private; -		} - -		info->mcr = 0; - -		usb_set_serial_port_data(port, info); -	} -  	command_info = kmalloc(sizeof(struct whiteheat_command_private),  								GFP_KERNEL);  	if (command_info == NULL) { @@ -333,16 +318,10 @@ no_firmware:  		"%s: please contact support@connecttech.com\n",  		serial->type->description);  	kfree(result); +	kfree(command);  	return -ENODEV;  no_command_private: -	for (i = serial->num_ports - 1; i >= 0; i--) { -		port = serial->port[i]; -		info = usb_get_serial_port_data(port); -		kfree(info); -no_private: -		; -	}  	kfree(result);  no_result_buffer:  	kfree(command); @@ -350,21 +329,36 @@ no_command_buffer:  	return -ENOMEM;  } -  static void whiteheat_release(struct usb_serial *serial)  {  	struct usb_serial_port *command_port; -	struct whiteheat_private *info; -	int i;  	/* free up our private data for our command port */  	command_port = serial->port[COMMAND_PORT];  	kfree(usb_get_serial_port_data(command_port)); +} -	for (i = 0; i < serial->num_ports; i++) { -		info = usb_get_serial_port_data(serial->port[i]); -		kfree(info); -	} +static int whiteheat_port_probe(struct usb_serial_port *port) +{ +	struct whiteheat_private *info; + +	info = kzalloc(sizeof(*info), GFP_KERNEL); +	if (!info) +		return -ENOMEM; + +	usb_set_serial_port_data(port, info); + +	return 0; +} + +static int whiteheat_port_remove(struct usb_serial_port *port) +{ +	struct whiteheat_private *info; + +	info = usb_get_serial_port_data(port); +	kfree(info); + +	return 0;  }  static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 779cd954abc..d305a5aa3a5 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,  		USB_SC_8070, USB_PR_CB, NULL,  		US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ), +/* Submitted by Oleksandr Chumachenko <ledest@gmail.com> */ +UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100, +		"Casio", +		"EX-N1 DigitalCamera", +		USB_SC_8070, USB_PR_DEVICE, NULL, 0), +  /* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/  UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,  		"Samsung", diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 072cbbadbc3..7f93f34b7f9 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -379,7 +379,8 @@ static void handle_rx(struct vhost_net *net)  		.hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE  	};  	size_t total_len = 0; -	int err, headcount, mergeable; +	int err, mergeable; +	s16 headcount;  	size_t vhost_hlen, sock_hlen;  	size_t vhost_len, sock_len;  	/* TODO: check that we are running from vhost_worker? */ diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index c101697a4ba..765a945f8ea 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -60,7 +60,8 @@ config LCD_LTV350QV  	  The LTV350QV panel is present on all ATSTK1000 boards.  config LCD_ILI9320 -	tristate +	tristate "ILI Technology ILI9320 controller support" +	depends on SPI  	help  	  If you have a panel based on the ILI9320 controller chip  	  then say y to include a power driver for it. diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index b7f5173ff9e..917bb568168 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c @@ -641,7 +641,6 @@ static void xenfb_backend_changed(struct xenbus_device *dev,  	case XenbusStateReconfiguring:  	case XenbusStateReconfigured:  	case XenbusStateUnknown: -	case XenbusStateClosed:  		break;  	case XenbusStateInitWait: @@ -670,6 +669,10 @@ InitWait:  		info->feature_resize = val;  		break; +	case XenbusStateClosed: +		if (dev->state == XenbusStateClosed) +			break; +		/* Missed the backend's CLOSING state -- fallthrough */  	case XenbusStateClosing:  		xenbus_frontend_closed(dev);  		break; diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 1e8659ca27e..809b0de59c0 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -225,8 +225,10 @@ EXPORT_SYMBOL_GPL(register_virtio_device);  void unregister_virtio_device(struct virtio_device *dev)  { +	int index = dev->index; /* save for after device release */ +  	device_unregister(&dev->dev); -	ida_simple_remove(&virtio_index_ida, dev->index); +	ida_simple_remove(&virtio_index_ida, index);  }  EXPORT_SYMBOL_GPL(unregister_virtio_device); diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index d4dffcd5287..126d8ce591c 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -3,6 +3,7 @@ menu "Xen driver support"  config XEN_BALLOON  	bool "Xen memory balloon driver" +	depends on !ARM  	default y  	help  	  The balloon driver allows the Xen domain to request more memory from @@ -145,6 +146,7 @@ config SWIOTLB_XEN  config XEN_TMEM  	bool +	depends on !ARM  	default y if (CLEANCACHE || FRONTSWAP)  	help  	  Shim to interface in-kernel Transcendent Memory hooks diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 0e863703545..74354708c6c 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -2,6 +2,7 @@ ifneq ($(CONFIG_ARM),y)  obj-y	+= manage.o balloon.o  obj-$(CONFIG_HOTPLUG_CPU)		+= cpu_hotplug.o  endif +obj-$(CONFIG_X86)			+= fallback.o  obj-y	+= grant-table.o features.o events.o  obj-y	+= xenbus/ diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 912ac81b6db..0be4df39e95 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -1395,10 +1395,10 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)  {  	struct pt_regs *old_regs = set_irq_regs(regs); +	irq_enter();  #ifdef CONFIG_X86  	exit_idle();  #endif -	irq_enter();  	__xen_evtchn_do_upcall(); diff --git a/drivers/xen/fallback.c b/drivers/xen/fallback.c new file mode 100644 index 00000000000..0ef7c4d40f8 --- /dev/null +++ b/drivers/xen/fallback.c @@ -0,0 +1,80 @@ +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/bug.h> +#include <linux/export.h> +#include <asm/hypervisor.h> +#include <asm/xen/hypercall.h> + +int xen_event_channel_op_compat(int cmd, void *arg) +{ +	struct evtchn_op op; +	int rc; + +	op.cmd = cmd; +	memcpy(&op.u, arg, sizeof(op.u)); +	rc = _hypercall1(int, event_channel_op_compat, &op); + +	switch (cmd) { +	case EVTCHNOP_close: +	case EVTCHNOP_send: +	case EVTCHNOP_bind_vcpu: +	case EVTCHNOP_unmask: +		/* no output */ +		break; + +#define COPY_BACK(eop) \ +	case EVTCHNOP_##eop: \ +		memcpy(arg, &op.u.eop, sizeof(op.u.eop)); \ +		break + +	COPY_BACK(bind_interdomain); +	COPY_BACK(bind_virq); +	COPY_BACK(bind_pirq); +	COPY_BACK(status); +	COPY_BACK(alloc_unbound); +	COPY_BACK(bind_ipi); +#undef COPY_BACK + +	default: +		WARN_ON(rc != -ENOSYS); +		break; +	} + +	return rc; +} +EXPORT_SYMBOL_GPL(xen_event_channel_op_compat); + +int HYPERVISOR_physdev_op_compat(int cmd, void *arg) +{ +	struct physdev_op op; +	int rc; + +	op.cmd = cmd; +	memcpy(&op.u, arg, sizeof(op.u)); +	rc = _hypercall1(int, physdev_op_compat, &op); + +	switch (cmd) { +	case PHYSDEVOP_IRQ_UNMASK_NOTIFY: +	case PHYSDEVOP_set_iopl: +	case PHYSDEVOP_set_iobitmap: +	case PHYSDEVOP_apic_write: +		/* no output */ +		break; + +#define COPY_BACK(pop, fld) \ +	case PHYSDEVOP_##pop: \ +		memcpy(arg, &op.u.fld, sizeof(op.u.fld)); \ +		break + +	COPY_BACK(irq_status_query, irq_status_query); +	COPY_BACK(apic_read, apic_op); +	COPY_BACK(ASSIGN_VECTOR, irq_op); +#undef COPY_BACK + +	default: +		WARN_ON(rc != -ENOSYS); +		break; +	} + +	return rc; +} diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 610bfc6be17..2e22df2f7a3 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv,  #endif  } +static void gntdev_free_map(struct grant_map *map) +{ +	if (map == NULL) +		return; + +	if (map->pages) +		free_xenballooned_pages(map->count, map->pages); +	kfree(map->pages); +	kfree(map->grants); +	kfree(map->map_ops); +	kfree(map->unmap_ops); +	kfree(map->kmap_ops); +	kfree(map); +} +  static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)  {  	struct grant_map *add; @@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)  	return add;  err: -	kfree(add->pages); -	kfree(add->grants); -	kfree(add->map_ops); -	kfree(add->unmap_ops); -	kfree(add->kmap_ops); -	kfree(add); +	gntdev_free_map(add);  	return NULL;  } @@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map)  		evtchn_put(map->notify.event);  	} -	if (map->pages) { -		if (!use_ptemod) -			unmap_grant_pages(map, 0, map->count); - -		free_xenballooned_pages(map->count, map->pages); -	} -	kfree(map->pages); -	kfree(map->grants); -	kfree(map->map_ops); -	kfree(map->unmap_ops); -	kfree(map); +	if (map->pages && !use_ptemod) +		unmap_grant_pages(map, 0, map->count); +	gntdev_free_map(map);  }  /* ------------------------------------------------------------------ */ diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c index 89f76252a16..ac727028e65 100644 --- a/drivers/xen/xenbus/xenbus_dev_frontend.c +++ b/drivers/xen/xenbus/xenbus_dev_frontend.c @@ -458,7 +458,7 @@ static ssize_t xenbus_file_write(struct file *filp,  		goto out;  	/* Can't write a xenbus message larger we can buffer */ -	if ((len + u->len) > sizeof(u->u.buffer)) { +	if (len > sizeof(u->u.buffer) - u->len) {  		/* On error, dump existing buffer */  		u->len = 0;  		rc = -EINVAL; @@ -75,6 +75,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)  	unsigned int sz = sizeof(struct bio) + extra_size;  	struct kmem_cache *slab = NULL;  	struct bio_slab *bslab, *new_bio_slabs; +	unsigned int new_bio_slab_max;  	unsigned int i, entry = -1;  	mutex_lock(&bio_slab_lock); @@ -97,12 +98,13 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)  		goto out_unlock;  	if (bio_slab_nr == bio_slab_max && entry == -1) { -		bio_slab_max <<= 1; +		new_bio_slab_max = bio_slab_max << 1;  		new_bio_slabs = krealloc(bio_slabs, -					 bio_slab_max * sizeof(struct bio_slab), +					 new_bio_slab_max * sizeof(struct bio_slab),  					 GFP_KERNEL);  		if (!new_bio_slabs)  			goto out_unlock; +		bio_slab_max = new_bio_slab_max;  		bio_slabs = new_bio_slabs;  	}  	if (entry == -1) diff --git a/fs/block_dev.c b/fs/block_dev.c index b3c1d3dae77..1a1e5e3b1ea 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1661,6 +1661,39 @@ static int blkdev_mmap(struct file *file, struct vm_area_struct *vma)  	return ret;  } +static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos, +				  struct pipe_inode_info *pipe, size_t len, +				  unsigned int flags) +{ +	ssize_t ret; +	struct block_device *bdev = I_BDEV(file->f_mapping->host); + +	percpu_down_read(&bdev->bd_block_size_semaphore); + +	ret = generic_file_splice_read(file, ppos, pipe, len, flags); + +	percpu_up_read(&bdev->bd_block_size_semaphore); + +	return ret; +} + +static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe, +				   struct file *file, loff_t *ppos, size_t len, +				   unsigned int flags) +{ +	ssize_t ret; +	struct block_device *bdev = I_BDEV(file->f_mapping->host); + +	percpu_down_read(&bdev->bd_block_size_semaphore); + +	ret = generic_file_splice_write(pipe, file, ppos, len, flags); + +	percpu_up_read(&bdev->bd_block_size_semaphore); + +	return ret; +} + +  /*   * Try to release a page associated with block device when the system   * is under memory pressure. @@ -1699,8 +1732,8 @@ const struct file_operations def_blk_fops = {  #ifdef CONFIG_COMPAT  	.compat_ioctl	= compat_blkdev_ioctl,  #endif -	.splice_read	= generic_file_splice_read, -	.splice_write	= generic_file_splice_write, +	.splice_read	= blkdev_splice_read, +	.splice_write	= blkdev_splice_write,  };  int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index f3187938e08..208d8aa5b07 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -283,9 +283,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,  		goto out;  	} -	rcu_read_lock(); -	root_level = btrfs_header_level(root->node); -	rcu_read_unlock(); +	root_level = btrfs_old_root_level(root, time_seq);  	if (root_level + 1 == level)  		goto out; @@ -1177,16 +1175,15 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid,  	return ret;  } -static char *ref_to_path(struct btrfs_root *fs_root, -			 struct btrfs_path *path, -			 u32 name_len, unsigned long name_off, -			 struct extent_buffer *eb_in, u64 parent, -			 char *dest, u32 size) +char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, +			u32 name_len, unsigned long name_off, +			struct extent_buffer *eb_in, u64 parent, +			char *dest, u32 size)  {  	int slot;  	u64 next_inum;  	int ret; -	s64 bytes_left = size - 1; +	s64 bytes_left = ((s64)size) - 1;  	struct extent_buffer *eb = eb_in;  	struct btrfs_key found_key;  	int leave_spinning = path->leave_spinning; @@ -1266,10 +1263,10 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root,  			 struct extent_buffer *eb_in, u64 parent,  			 char *dest, u32 size)  { -	return ref_to_path(fs_root, path, -			   btrfs_inode_ref_name_len(eb_in, iref), -			   (unsigned long)(iref + 1), -			   eb_in, parent, dest, size); +	return btrfs_ref_to_path(fs_root, path, +				 btrfs_inode_ref_name_len(eb_in, iref), +				 (unsigned long)(iref + 1), +				 eb_in, parent, dest, size);  }  /* @@ -1715,9 +1712,8 @@ static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off,  					ipath->fspath->bytes_left - s_ptr : 0;  	fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr; -	fspath = ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, -			     name_off, eb, inum, fspath_min, -			     bytes_left); +	fspath = btrfs_ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, +				   name_off, eb, inum, fspath_min, bytes_left);  	if (IS_ERR(fspath))  		return PTR_ERR(fspath); diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h index e75533043a5..d61feca7945 100644 --- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h @@ -62,6 +62,10 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans,  char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,  			 struct btrfs_inode_ref *iref, struct extent_buffer *eb,  			 u64 parent, char *dest, u32 size); +char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, +			u32 name_len, unsigned long name_off, +			struct extent_buffer *eb_in, u64 parent, +			char *dest, u32 size);  struct btrfs_data_container *init_data_container(u32 total_bytes);  struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index b3343621100..cdfb4c49a80 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -596,6 +596,11 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,  	if (tree_mod_dont_log(fs_info, eb))  		return 0; +	/* +	 * When we override something during the move, we log these removals. +	 * This can only happen when we move towards the beginning of the +	 * buffer, i.e. dst_slot < src_slot. +	 */  	for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) {  		ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot,  					      MOD_LOG_KEY_REMOVE_WHILE_MOVING); @@ -647,8 +652,6 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,  	if (tree_mod_dont_log(fs_info, NULL))  		return 0; -	__tree_mod_log_free_eb(fs_info, old_root); -  	ret = tree_mod_alloc(fs_info, flags, &tm);  	if (ret < 0)  		goto out; @@ -926,12 +929,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,  			ret = btrfs_dec_ref(trans, root, buf, 1, 1);  			BUG_ON(ret); /* -ENOMEM */  		} -		/* -		 * don't log freeing in case we're freeing the root node, this -		 * is done by tree_mod_log_set_root_pointer later -		 */ -		if (buf != root->node && btrfs_header_level(buf) != 0) -			tree_mod_log_free_eb(root->fs_info, buf); +		tree_mod_log_free_eb(root->fs_info, buf);  		clean_tree_block(trans, root, buf);  		*last_ref = 1;  	} @@ -1225,6 +1223,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,  	free_extent_buffer(eb);  	__tree_mod_log_rewind(eb_rewin, time_seq, tm); +	WARN_ON(btrfs_header_nritems(eb_rewin) > +		BTRFS_NODEPTRS_PER_BLOCK(fs_info->fs_root));  	return eb_rewin;  } @@ -1241,9 +1241,11 @@ get_old_root(struct btrfs_root *root, u64 time_seq)  {  	struct tree_mod_elem *tm;  	struct extent_buffer *eb; +	struct extent_buffer *old;  	struct tree_mod_root *old_root = NULL;  	u64 old_generation = 0;  	u64 logical; +	u32 blocksize;  	eb = btrfs_read_lock_root_node(root);  	tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); @@ -1259,14 +1261,32 @@ get_old_root(struct btrfs_root *root, u64 time_seq)  	}  	tm = tree_mod_log_search(root->fs_info, logical, time_seq); -	if (old_root) +	if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) { +		btrfs_tree_read_unlock(root->node); +		free_extent_buffer(root->node); +		blocksize = btrfs_level_size(root, old_root->level); +		old = read_tree_block(root, logical, blocksize, 0); +		if (!old) { +			pr_warn("btrfs: failed to read tree block %llu from get_old_root\n", +				logical); +			WARN_ON(1); +		} else { +			eb = btrfs_clone_extent_buffer(old); +			free_extent_buffer(old); +		} +	} else if (old_root) { +		btrfs_tree_read_unlock(root->node); +		free_extent_buffer(root->node);  		eb = alloc_dummy_extent_buffer(logical, root->nodesize); -	else +	} else {  		eb = btrfs_clone_extent_buffer(root->node); -	btrfs_tree_read_unlock(root->node); -	free_extent_buffer(root->node); +		btrfs_tree_read_unlock(root->node); +		free_extent_buffer(root->node); +	} +  	if (!eb)  		return NULL; +	extent_buffer_get(eb);  	btrfs_tree_read_lock(eb);  	if (old_root) {  		btrfs_set_header_bytenr(eb, eb->start); @@ -1279,11 +1299,28 @@ get_old_root(struct btrfs_root *root, u64 time_seq)  		__tree_mod_log_rewind(eb, time_seq, tm);  	else  		WARN_ON(btrfs_header_level(eb) != 0); -	extent_buffer_get(eb); +	WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root));  	return eb;  } +int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq) +{ +	struct tree_mod_elem *tm; +	int level; + +	tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); +	if (tm && tm->op == MOD_LOG_ROOT_REPLACE) { +		level = tm->old_root.level; +	} else { +		rcu_read_lock(); +		level = btrfs_header_level(root->node); +		rcu_read_unlock(); +	} + +	return level; +} +  static inline int should_cow_block(struct btrfs_trans_handle *trans,  				   struct btrfs_root *root,  				   struct extent_buffer *buf) @@ -1725,6 +1762,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,  			goto enospc;  		} +		tree_mod_log_free_eb(root->fs_info, root->node);  		tree_mod_log_set_root_pointer(root, child);  		rcu_assign_pointer(root->node, child); @@ -2970,8 +3008,10 @@ static int push_node_left(struct btrfs_trans_handle *trans,  			   push_items * sizeof(struct btrfs_key_ptr));  	if (push_items < src_nritems) { -		tree_mod_log_eb_move(root->fs_info, src, 0, push_items, -				     src_nritems - push_items); +		/* +		 * don't call tree_mod_log_eb_move here, key removal was already +		 * fully logged by tree_mod_log_eb_copy above. +		 */  		memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0),  				      btrfs_node_key_ptr_offset(push_items),  				      (src_nritems - push_items) * diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 926c9ffc66d..c72ead86950 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -3120,6 +3120,7 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info)  {  	return atomic_inc_return(&fs_info->tree_mod_seq);  } +int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq);  /* root-item.c */  int btrfs_find_root_ref(struct btrfs_root *tree_root, @@ -3338,6 +3339,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,  int btrfs_update_inode(struct btrfs_trans_handle *trans,  			      struct btrfs_root *root,  			      struct inode *inode); +int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, +				struct btrfs_root *root, struct inode *inode);  int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode);  int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);  int btrfs_orphan_cleanup(struct btrfs_root *root); diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 8036d3a8485..472873a94d9 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -4110,8 +4110,8 @@ struct extent_buffer *alloc_dummy_extent_buffer(u64 start, unsigned long len)  	return eb;  err: -	for (i--; i >= 0; i--) -		__free_page(eb->pages[i]); +	for (; i > 0; i--) +		__free_page(eb->pages[i - 1]);  	__free_extent_buffer(eb);  	return NULL;  } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 85a1e5053fe..95542a1b3df 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -94,8 +94,6 @@ static noinline int cow_file_range(struct inode *inode,  				   struct page *locked_page,  				   u64 start, u64 end, int *page_started,  				   unsigned long *nr_written, int unlock); -static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, -				struct btrfs_root *root, struct inode *inode);  static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,  				     struct inode *inode,  struct inode *dir, @@ -2746,8 +2744,9 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,  	return btrfs_update_inode_item(trans, root, inode);  } -static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, -				struct btrfs_root *root, struct inode *inode) +noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, +					 struct btrfs_root *root, +					 struct inode *inode)  {  	int ret; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 61168805f17..8fcf9a59c28 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -343,7 +343,8 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)  		return -EOPNOTSUPP;  	if (copy_from_user(&range, arg, sizeof(range)))  		return -EFAULT; -	if (range.start > total_bytes) +	if (range.start > total_bytes || +	    range.len < fs_info->sb->s_blocksize)  		return -EINVAL;  	range.len = min(range.len, total_bytes - range.start); @@ -570,7 +571,8 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,  		ret = btrfs_commit_transaction(trans,  					       root->fs_info->extent_root);  	} -	BUG_ON(ret); +	if (ret) +		goto fail;  	ret = pending_snapshot->error;  	if (ret) diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 5039686df6a..fe9d02c45f8 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -790,8 +790,10 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,  	}  	path = btrfs_alloc_path(); -	if (!path) -		return -ENOMEM; +	if (!path) { +		ret = -ENOMEM; +		goto out_free_root; +	}  	key.objectid = 0;  	key.type = BTRFS_QGROUP_STATUS_KEY; @@ -800,7 +802,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,  	ret = btrfs_insert_empty_item(trans, quota_root, path, &key,  				      sizeof(*ptr));  	if (ret) -		goto out; +		goto out_free_path;  	leaf = path->nodes[0];  	ptr = btrfs_item_ptr(leaf, path->slots[0], @@ -818,8 +820,15 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,  	fs_info->quota_root = quota_root;  	fs_info->pending_quota_state = 1;  	spin_unlock(&fs_info->qgroup_lock); -out: +out_free_path:  	btrfs_free_path(path); +out_free_root: +	if (ret) { +		free_extent_buffer(quota_root->node); +		free_extent_buffer(quota_root->commit_root); +		kfree(quota_root); +	} +out:  	return ret;  } diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index c7beb543a4a..e78b297b0b0 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -745,31 +745,36 @@ typedef int (*iterate_inode_ref_t)(int num, u64 dir, int index,  				   void *ctx);  /* - * Helper function to iterate the entries in ONE btrfs_inode_ref. + * Helper function to iterate the entries in ONE btrfs_inode_ref or + * btrfs_inode_extref.   * The iterate callback may return a non zero value to stop iteration. This can   * be a negative value for error codes or 1 to simply stop it.   * - * path must point to the INODE_REF when called. + * path must point to the INODE_REF or INODE_EXTREF when called.   */  static int iterate_inode_ref(struct send_ctx *sctx,  			     struct btrfs_root *root, struct btrfs_path *path,  			     struct btrfs_key *found_key, int resolve,  			     iterate_inode_ref_t iterate, void *ctx)  { -	struct extent_buffer *eb; +	struct extent_buffer *eb = path->nodes[0];  	struct btrfs_item *item;  	struct btrfs_inode_ref *iref; +	struct btrfs_inode_extref *extref;  	struct btrfs_path *tmp_path;  	struct fs_path *p; -	u32 cur; -	u32 len; +	u32 cur = 0;  	u32 total; -	int slot; +	int slot = path->slots[0];  	u32 name_len;  	char *start;  	int ret = 0; -	int num; +	int num = 0;  	int index; +	u64 dir; +	unsigned long name_off; +	unsigned long elem_size; +	unsigned long ptr;  	p = fs_path_alloc_reversed(sctx);  	if (!p) @@ -781,24 +786,40 @@ static int iterate_inode_ref(struct send_ctx *sctx,  		return -ENOMEM;  	} -	eb = path->nodes[0]; -	slot = path->slots[0]; -	item = btrfs_item_nr(eb, slot); -	iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref); -	cur = 0; -	len = 0; -	total = btrfs_item_size(eb, item); -	num = 0; +	if (found_key->type == BTRFS_INODE_REF_KEY) { +		ptr = (unsigned long)btrfs_item_ptr(eb, slot, +						    struct btrfs_inode_ref); +		item = btrfs_item_nr(eb, slot); +		total = btrfs_item_size(eb, item); +		elem_size = sizeof(*iref); +	} else { +		ptr = btrfs_item_ptr_offset(eb, slot); +		total = btrfs_item_size_nr(eb, slot); +		elem_size = sizeof(*extref); +	} +  	while (cur < total) {  		fs_path_reset(p); -		name_len = btrfs_inode_ref_name_len(eb, iref); -		index = btrfs_inode_ref_index(eb, iref); +		if (found_key->type == BTRFS_INODE_REF_KEY) { +			iref = (struct btrfs_inode_ref *)(ptr + cur); +			name_len = btrfs_inode_ref_name_len(eb, iref); +			name_off = (unsigned long)(iref + 1); +			index = btrfs_inode_ref_index(eb, iref); +			dir = found_key->offset; +		} else { +			extref = (struct btrfs_inode_extref *)(ptr + cur); +			name_len = btrfs_inode_extref_name_len(eb, extref); +			name_off = (unsigned long)&extref->name; +			index = btrfs_inode_extref_index(eb, extref); +			dir = btrfs_inode_extref_parent(eb, extref); +		} +  		if (resolve) { -			start = btrfs_iref_to_path(root, tmp_path, iref, eb, -						found_key->offset, p->buf, -						p->buf_len); +			start = btrfs_ref_to_path(root, tmp_path, name_len, +						  name_off, eb, dir, +						  p->buf, p->buf_len);  			if (IS_ERR(start)) {  				ret = PTR_ERR(start);  				goto out; @@ -809,9 +830,10 @@ static int iterate_inode_ref(struct send_ctx *sctx,  						p->buf_len + p->buf - start);  				if (ret < 0)  					goto out; -				start = btrfs_iref_to_path(root, tmp_path, iref, -						eb, found_key->offset, p->buf, -						p->buf_len); +				start = btrfs_ref_to_path(root, tmp_path, +							  name_len, name_off, +							  eb, dir, +							  p->buf, p->buf_len);  				if (IS_ERR(start)) {  					ret = PTR_ERR(start);  					goto out; @@ -820,21 +842,16 @@ static int iterate_inode_ref(struct send_ctx *sctx,  			}  			p->start = start;  		} else { -			ret = fs_path_add_from_extent_buffer(p, eb, -					(unsigned long)(iref + 1), name_len); +			ret = fs_path_add_from_extent_buffer(p, eb, name_off, +							     name_len);  			if (ret < 0)  				goto out;  		} - -		len = sizeof(*iref) + name_len; -		iref = (struct btrfs_inode_ref *)((char *)iref + len); -		cur += len; - -		ret = iterate(num, found_key->offset, index, p, ctx); +		cur += elem_size + name_len; +		ret = iterate(num, dir, index, p, ctx);  		if (ret)  			goto out; -  		num++;  	} @@ -998,7 +1015,8 @@ static int get_inode_path(struct send_ctx *sctx, struct btrfs_root *root,  	}  	btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]);  	if (found_key.objectid != ino || -		found_key.type != BTRFS_INODE_REF_KEY) { +	    (found_key.type != BTRFS_INODE_REF_KEY && +	     found_key.type != BTRFS_INODE_EXTREF_KEY)) {  		ret = -ENOENT;  		goto out;  	} @@ -1551,8 +1569,8 @@ static int get_first_ref(struct send_ctx *sctx,  	struct btrfs_key key;  	struct btrfs_key found_key;  	struct btrfs_path *path; -	struct btrfs_inode_ref *iref;  	int len; +	u64 parent_dir;  	path = alloc_path_for_send();  	if (!path) @@ -1568,27 +1586,41 @@ static int get_first_ref(struct send_ctx *sctx,  	if (!ret)  		btrfs_item_key_to_cpu(path->nodes[0], &found_key,  				path->slots[0]); -	if (ret || found_key.objectid != key.objectid || -	    found_key.type != key.type) { +	if (ret || found_key.objectid != ino || +	    (found_key.type != BTRFS_INODE_REF_KEY && +	     found_key.type != BTRFS_INODE_EXTREF_KEY)) {  		ret = -ENOENT;  		goto out;  	} -	iref = btrfs_item_ptr(path->nodes[0], path->slots[0], -			struct btrfs_inode_ref); -	len = btrfs_inode_ref_name_len(path->nodes[0], iref); -	ret = fs_path_add_from_extent_buffer(name, path->nodes[0], -			(unsigned long)(iref + 1), len); +	if (key.type == BTRFS_INODE_REF_KEY) { +		struct btrfs_inode_ref *iref; +		iref = btrfs_item_ptr(path->nodes[0], path->slots[0], +				      struct btrfs_inode_ref); +		len = btrfs_inode_ref_name_len(path->nodes[0], iref); +		ret = fs_path_add_from_extent_buffer(name, path->nodes[0], +						     (unsigned long)(iref + 1), +						     len); +		parent_dir = found_key.offset; +	} else { +		struct btrfs_inode_extref *extref; +		extref = btrfs_item_ptr(path->nodes[0], path->slots[0], +					struct btrfs_inode_extref); +		len = btrfs_inode_extref_name_len(path->nodes[0], extref); +		ret = fs_path_add_from_extent_buffer(name, path->nodes[0], +					(unsigned long)&extref->name, len); +		parent_dir = btrfs_inode_extref_parent(path->nodes[0], extref); +	}  	if (ret < 0)  		goto out;  	btrfs_release_path(path); -	ret = get_inode_info(root, found_key.offset, NULL, dir_gen, NULL, NULL, +	ret = get_inode_info(root, parent_dir, NULL, dir_gen, NULL, NULL,  			NULL, NULL);  	if (ret < 0)  		goto out; -	*dir = found_key.offset; +	*dir = parent_dir;  out:  	btrfs_free_path(path); @@ -2430,7 +2462,8 @@ verbose_printk("btrfs: send_create_inode %llu\n", ino);  		TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p);  	} else if (S_ISCHR(mode) || S_ISBLK(mode) ||  		   S_ISFIFO(mode) || S_ISSOCK(mode)) { -		TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, rdev); +		TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, new_encode_dev(rdev)); +		TLV_PUT_U64(sctx, BTRFS_SEND_A_MODE, mode);  	}  	ret = send_cmd(sctx); @@ -3226,7 +3259,8 @@ static int process_all_refs(struct send_ctx *sctx,  		btrfs_item_key_to_cpu(eb, &found_key, slot);  		if (found_key.objectid != key.objectid || -		    found_key.type != key.type) +		    (found_key.type != BTRFS_INODE_REF_KEY && +		     found_key.type != BTRFS_INODE_EXTREF_KEY))  			break;  		ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb, @@ -3987,7 +4021,7 @@ static int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end)  	if (sctx->cur_ino == 0)  		goto out;  	if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid && -	    sctx->cmp_key->type <= BTRFS_INODE_REF_KEY) +	    sctx->cmp_key->type <= BTRFS_INODE_EXTREF_KEY)  		goto out;  	if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs))  		goto out; @@ -4033,22 +4067,21 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)  	if (ret < 0)  		goto out; -	if (!S_ISLNK(sctx->cur_inode_mode)) { -		if (!sctx->parent_root || sctx->cur_inode_new) { +	if (!sctx->parent_root || sctx->cur_inode_new) { +		need_chown = 1; +		if (!S_ISLNK(sctx->cur_inode_mode))  			need_chmod = 1; -			need_chown = 1; -		} else { -			ret = get_inode_info(sctx->parent_root, sctx->cur_ino, -					NULL, NULL, &right_mode, &right_uid, -					&right_gid, NULL); -			if (ret < 0) -				goto out; +	} else { +		ret = get_inode_info(sctx->parent_root, sctx->cur_ino, +				NULL, NULL, &right_mode, &right_uid, +				&right_gid, NULL); +		if (ret < 0) +			goto out; -			if (left_uid != right_uid || left_gid != right_gid) -				need_chown = 1; -			if (left_mode != right_mode) -				need_chmod = 1; -		} +		if (left_uid != right_uid || left_gid != right_gid) +			need_chown = 1; +		if (!S_ISLNK(sctx->cur_inode_mode) && left_mode != right_mode) +			need_chmod = 1;  	}  	if (S_ISREG(sctx->cur_inode_mode)) { @@ -4335,7 +4368,8 @@ static int changed_cb(struct btrfs_root *left_root,  	if (key->type == BTRFS_INODE_ITEM_KEY)  		ret = changed_inode(sctx, result); -	else if (key->type == BTRFS_INODE_REF_KEY) +	else if (key->type == BTRFS_INODE_REF_KEY || +		 key->type == BTRFS_INODE_EXTREF_KEY)  		ret = changed_ref(sctx, result);  	else if (key->type == BTRFS_XATTR_ITEM_KEY)  		ret = changed_xattr(sctx, result); diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 77db875b511..04bbfb1052e 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1200,7 +1200,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,  	btrfs_i_size_write(parent_inode, parent_inode->i_size +  					 dentry->d_name.len * 2);  	parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; -	ret = btrfs_update_inode(trans, parent_root, parent_inode); +	ret = btrfs_update_inode_fallback(trans, parent_root, parent_inode);  	if (ret)  		btrfs_abort_transaction(trans, root, ret);  fail: diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 029b903a4ae..0f5ebb72a5e 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1819,6 +1819,13 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)  				    "Failed to relocate sys chunks after "  				    "device initialization. This can be fixed "  				    "using the \"btrfs balance\" command."); +		trans = btrfs_attach_transaction(root); +		if (IS_ERR(trans)) { +			if (PTR_ERR(trans) == -ENOENT) +				return 0; +			return PTR_ERR(trans); +		} +		ret = btrfs_commit_transaction(trans, root);  	}  	return ret; diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 02ce90972d8..9349bb37a2f 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -90,6 +90,8 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,  		*max_len = handle_length;  		type = 255;  	} +	if (dentry) +		dput(dentry);  	return type;  } diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index fc783e26442..0fb15bbbe43 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -225,6 +225,13 @@ sid_to_str(struct cifs_sid *sidptr, char *sidstr)  }  static void +cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src) +{ +	memcpy(dst, src, sizeof(*dst)); +	dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS); +} + +static void  id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,  		struct cifs_sid_id **psidid, char *typestr)  { @@ -248,7 +255,7 @@ id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,  		}  	} -	memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid)); +	cifs_copy_sid(&(*psidid)->sid, sidptr);  	(*psidid)->time = jiffies - (SID_MAP_RETRY + 1);  	(*psidid)->refcount = 0; @@ -354,7 +361,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)  	 * any fields of the node after a reference is put .  	 */  	if (test_bit(SID_ID_MAPPED, &psidid->state)) { -		memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); +		cifs_copy_sid(ssid, &psidid->sid);  		psidid->time = jiffies; /* update ts for accessing */  		goto id_sid_out;  	} @@ -370,14 +377,14 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)  		if (IS_ERR(sidkey)) {  			rc = -EINVAL;  			cFYI(1, "%s: Can't map and id to a SID", __func__); +		} else if (sidkey->datalen < sizeof(struct cifs_sid)) { +			rc = -EIO; +			cFYI(1, "%s: Downcall contained malformed key " +				"(datalen=%hu)", __func__, sidkey->datalen);  		} else {  			lsid = (struct cifs_sid *)sidkey->payload.data; -			memcpy(&psidid->sid, lsid, -				sidkey->datalen < sizeof(struct cifs_sid) ? -				sidkey->datalen : sizeof(struct cifs_sid)); -			memcpy(ssid, &psidid->sid, -				sidkey->datalen < sizeof(struct cifs_sid) ? -				sidkey->datalen : sizeof(struct cifs_sid)); +			cifs_copy_sid(&psidid->sid, lsid); +			cifs_copy_sid(ssid, &psidid->sid);  			set_bit(SID_ID_MAPPED, &psidid->state);  			key_put(sidkey);  			kfree(psidid->sidstr); @@ -396,7 +403,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)  			return rc;  		}  		if (test_bit(SID_ID_MAPPED, &psidid->state)) -			memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); +			cifs_copy_sid(ssid, &psidid->sid);  		else  			rc = -EINVAL;  	} @@ -675,8 +682,6 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)  static void copy_sec_desc(const struct cifs_ntsd *pntsd,  				struct cifs_ntsd *pnntsd, __u32 sidsoffset)  { -	int i; -  	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;  	struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr; @@ -692,26 +697,14 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd,  	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +  				le32_to_cpu(pntsd->osidoffset));  	nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset); - -	nowner_sid_ptr->revision = owner_sid_ptr->revision; -	nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth; -	for (i = 0; i < 6; i++) -		nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i]; -	for (i = 0; i < 5; i++) -		nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i]; +	cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);  	/* copy group sid */  	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +  				le32_to_cpu(pntsd->gsidoffset));  	ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +  					sizeof(struct cifs_sid)); - -	ngroup_sid_ptr->revision = group_sid_ptr->revision; -	ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth; -	for (i = 0; i < 6; i++) -		ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i]; -	for (i = 0; i < 5; i++) -		ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i]; +	cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);  	return;  } @@ -1120,8 +1113,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,  				kfree(nowner_sid_ptr);  				return rc;  			} -			memcpy(owner_sid_ptr, nowner_sid_ptr, -					sizeof(struct cifs_sid)); +			cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);  			kfree(nowner_sid_ptr);  			*aclflag = CIFS_ACL_OWNER;  		} @@ -1139,8 +1131,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,  				kfree(ngroup_sid_ptr);  				return rc;  			} -			memcpy(group_sid_ptr, ngroup_sid_ptr, -					sizeof(struct cifs_sid)); +			cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);  			kfree(ngroup_sid_ptr);  			*aclflag = CIFS_ACL_GROUP;  		} diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 7c0a8128364..d3671f2acb2 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -398,7 +398,16 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,  	 * in network traffic in the other paths.  	 */  	if (!(oflags & O_CREAT)) { -		struct dentry *res = cifs_lookup(inode, direntry, 0); +		struct dentry *res; + +		/* +		 * Check for hashed negative dentry. We have already revalidated +		 * the dentry and it is fine. No need to perform another lookup. +		 */ +		if (!d_unhashed(direntry)) +			return -ENOENT; + +		res = cifs_lookup(inode, direntry, 0);  		if (IS_ERR(res))  			return PTR_ERR(res); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index f5054025f9d..4c6285fff59 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -210,6 +210,8 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd,  	err  = get_user(palp, &up->palette);  	err |= get_user(length, &up->length); +	if (err) +		return -EFAULT;  	up_native = compat_alloc_user_space(sizeof(struct video_spu_palette));  	err  = put_user(compat_ptr(palp), &up_native->palette); diff --git a/fs/eventpoll.c b/fs/eventpoll.c index da72250ddc1..cd96649bfe6 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -346,7 +346,7 @@ static inline struct epitem *ep_item_from_epqueue(poll_table *p)  /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */  static inline int ep_op_has_event(int op)  { -	return op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD; +	return op != EPOLL_CTL_DEL;  }  /* Initialize the poll safe wake up structure */ @@ -676,34 +676,6 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)  	return 0;  } -/* - * Disables a "struct epitem" in the eventpoll set. Returns -EBUSY if the item - * had no event flags set, indicating that another thread may be currently - * handling that item's events (in the case that EPOLLONESHOT was being - * used). Otherwise a zero result indicates that the item has been disabled - * from receiving events. A disabled item may be re-enabled via - * EPOLL_CTL_MOD. Must be called with "mtx" held. - */ -static int ep_disable(struct eventpoll *ep, struct epitem *epi) -{ -	int result = 0; -	unsigned long flags; - -	spin_lock_irqsave(&ep->lock, flags); -	if (epi->event.events & ~EP_PRIVATE_BITS) { -		if (ep_is_linked(&epi->rdllink)) -			list_del_init(&epi->rdllink); -		/* Ensure ep_poll_callback will not add epi back onto ready -		   list: */ -		epi->event.events &= EP_PRIVATE_BITS; -		} -	else -		result = -EBUSY; -	spin_unlock_irqrestore(&ep->lock, flags); - -	return result; -} -  static void ep_free(struct eventpoll *ep)  {  	struct rb_node *rbp; @@ -1048,6 +1020,8 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)  	rb_insert_color(&epi->rbn, &ep->rbr);  } + +  #define PATH_ARR_SIZE 5  /*   * These are the number paths of length 1 to 5, that we are allowing to emanate @@ -1813,12 +1787,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,  		} else  			error = -ENOENT;  		break; -	case EPOLL_CTL_DISABLE: -		if (epi) -			error = ep_disable(ep, epi); -		else -			error = -ENOENT; -		break;  	}  	mutex_unlock(&ep->mtx); diff --git a/fs/exec.c b/fs/exec.c index 8b9011b6704..0039055b1fc 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1083,7 +1083,8 @@ int flush_old_exec(struct linux_binprm * bprm)  	bprm->mm = NULL;		/* We're using it now */  	set_fs(USER_DS); -	current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD); +	current->flags &= +		~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE);  	flush_thread();  	current->personality &= ~bprm->per_clear; diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 4facdd29a35..3a100e7a62a 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -725,6 +725,10 @@ repeat_in_this_group:  				   "inode=%lu", ino + 1);  			continue;  		} +		BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); +		err = ext4_journal_get_write_access(handle, inode_bitmap_bh); +		if (err) +			goto fail;  		ext4_lock_group(sb, group);  		ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data);  		ext4_unlock_group(sb, group); @@ -738,6 +742,11 @@ repeat_in_this_group:  	goto out;  got: +	BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); +	err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); +	if (err) +		goto fail; +  	/* We may have to initialize the block bitmap if it isn't already */  	if (ext4_has_group_desc_csum(sb) &&  	    gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { @@ -771,11 +780,6 @@ got:  			goto fail;  	} -	BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); -	err = ext4_journal_get_write_access(handle, inode_bitmap_bh); -	if (err) -		goto fail; -  	BUFFER_TRACE(group_desc_bh, "get_write_access");  	err = ext4_journal_get_write_access(handle, group_desc_bh);  	if (err) @@ -823,11 +827,6 @@ got:  	}  	ext4_unlock_group(sb, group); -	BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); -	err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); -	if (err) -		goto fail; -  	BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata");  	err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh);  	if (err) diff --git a/fs/file.c b/fs/file.c index d3b5fa80b71..708d997a774 100644 --- a/fs/file.c +++ b/fs/file.c @@ -900,7 +900,7 @@ int replace_fd(unsigned fd, struct file *file, unsigned flags)  		return __close_fd(files, fd);  	if (fd >= rlimit(RLIMIT_NOFILE)) -		return -EMFILE; +		return -EBADF;  	spin_lock(&files->file_lock);  	err = expand_files(files, fd); @@ -926,7 +926,7 @@ SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags)  		return -EINVAL;  	if (newfd >= rlimit(RLIMIT_NOFILE)) -		return -EMFILE; +		return -EBADF;  	spin_lock(&files->file_lock);  	err = expand_files(files, newfd); diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 0def0504afc..e056b4ce487 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -516,15 +516,13 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)  		struct gfs2_holder i_gh;  		int error; -		gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); -		error = gfs2_glock_nq(&i_gh); -		if (error == 0) { -			file_accessed(file); -			gfs2_glock_dq(&i_gh); -		} -		gfs2_holder_uninit(&i_gh); +		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, +					   &i_gh);  		if (error)  			return error; +		/* grab lock to update inode */ +		gfs2_glock_dq_uninit(&i_gh); +		file_accessed(file);  	}  	vma->vm_ops = &gfs2_vm_ops; @@ -677,10 +675,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,  	size_t writesize = iov_length(iov, nr_segs);  	struct dentry *dentry = file->f_dentry;  	struct gfs2_inode *ip = GFS2_I(dentry->d_inode); -	struct gfs2_sbd *sdp;  	int ret; -	sdp = GFS2_SB(file->f_mapping->host);  	ret = gfs2_rs_alloc(ip);  	if (ret)  		return ret; diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 8ff95a2d54e..9ceccb1595a 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -393,12 +393,10 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)  	struct gfs2_meta_header *mh;  	struct gfs2_trans *tr; -	lock_buffer(bd->bd_bh); -	gfs2_log_lock(sdp);  	tr = current->journal_info;  	tr->tr_touched = 1;  	if (!list_empty(&bd->bd_list)) -		goto out; +		return;  	set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);  	set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);  	mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; @@ -414,9 +412,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)  	sdp->sd_log_num_buf++;  	list_add(&bd->bd_list, &sdp->sd_log_le_buf);  	tr->tr_num_buf_new++; -out: -	gfs2_log_unlock(sdp); -	unlock_buffer(bd->bd_bh);  }  static void gfs2_check_magic(struct buffer_head *bh) @@ -621,7 +616,6 @@ static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)  static void revoke_lo_before_commit(struct gfs2_sbd *sdp)  { -	struct gfs2_log_descriptor *ld;  	struct gfs2_meta_header *mh;  	unsigned int offset;  	struct list_head *head = &sdp->sd_log_le_revoke; @@ -634,7 +628,6 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp)  	length = gfs2_struct2blk(sdp, sdp->sd_log_num_revoke, sizeof(u64));  	page = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE, length, sdp->sd_log_num_revoke); -	ld = page_address(page);  	offset = sizeof(struct gfs2_log_descriptor);  	list_for_each_entry(bd, head, bd_list) { @@ -777,12 +770,10 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)  	struct address_space *mapping = bd->bd_bh->b_page->mapping;  	struct gfs2_inode *ip = GFS2_I(mapping->host); -	lock_buffer(bd->bd_bh); -	gfs2_log_lock(sdp);  	if (tr)  		tr->tr_touched = 1;  	if (!list_empty(&bd->bd_list)) -		goto out; +		return;  	set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);  	set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);  	if (gfs2_is_jdata(ip)) { @@ -793,9 +784,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)  	} else {  		list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered);  	} -out: -	gfs2_log_unlock(sdp); -	unlock_buffer(bd->bd_bh);  }  /** diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 40c4b0d42fa..c5af8e18f27 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -497,8 +497,11 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)  	struct gfs2_quota_data **qd;  	int error; -	if (ip->i_res == NULL) -		gfs2_rs_alloc(ip); +	if (ip->i_res == NULL) { +		error = gfs2_rs_alloc(ip); +		if (error) +			return error; +	}  	qd = ip->i_res->rs_qa_qd; diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 3cc402ce6fe..38fe18f2f05 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -553,7 +553,6 @@ void gfs2_free_clones(struct gfs2_rgrpd *rgd)   */  int gfs2_rs_alloc(struct gfs2_inode *ip)  { -	int error = 0;  	struct gfs2_blkreserv *res;  	if (ip->i_res) @@ -561,7 +560,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)  	res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS);  	if (!res) -		error = -ENOMEM; +		return -ENOMEM;  	RB_CLEAR_NODE(&res->rs_node); @@ -571,7 +570,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)  	else  		ip->i_res = res;  	up_write(&ip->i_rw_mutex); -	return error; +	return 0;  }  static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs) @@ -1263,7 +1262,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)  	int ret = 0;  	u64 amt;  	u64 trimmed = 0; +	u64 start, end, minlen;  	unsigned int x; +	unsigned bs_shift = sdp->sd_sb.sb_bsize_shift;  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; @@ -1271,19 +1272,25 @@ int gfs2_fitrim(struct file *filp, void __user *argp)  	if (!blk_queue_discard(q))  		return -EOPNOTSUPP; -	if (argp == NULL) { -		r.start = 0; -		r.len = ULLONG_MAX; -		r.minlen = 0; -	} else if (copy_from_user(&r, argp, sizeof(r))) +	if (copy_from_user(&r, argp, sizeof(r)))  		return -EFAULT;  	ret = gfs2_rindex_update(sdp);  	if (ret)  		return ret; -	rgd = gfs2_blk2rgrpd(sdp, r.start, 0); -	rgd_end = gfs2_blk2rgrpd(sdp, r.start + r.len, 0); +	start = r.start >> bs_shift; +	end = start + (r.len >> bs_shift); +	minlen = max_t(u64, r.minlen, +		       q->limits.discard_granularity) >> bs_shift; + +	rgd = gfs2_blk2rgrpd(sdp, start, 0); +	rgd_end = gfs2_blk2rgrpd(sdp, end - 1, 0); + +	if (end <= start || +	    minlen > sdp->sd_max_rg_data || +	    start > rgd_end->rd_data0 + rgd_end->rd_data) +		return -EINVAL;  	while (1) { @@ -1295,7 +1302,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)  			/* Trim each bitmap in the rgrp */  			for (x = 0; x < rgd->rd_length; x++) {  				struct gfs2_bitmap *bi = rgd->rd_bits + x; -				ret = gfs2_rgrp_send_discards(sdp, rgd->rd_data0, NULL, bi, r.minlen, &amt); +				ret = gfs2_rgrp_send_discards(sdp, +						rgd->rd_data0, NULL, bi, minlen, +						&amt);  				if (ret) {  					gfs2_glock_dq_uninit(&gh);  					goto out; @@ -1324,7 +1333,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp)  out:  	r.len = trimmed << 9; -	if (argp && copy_to_user(argp, &r, sizeof(r))) +	if (copy_to_user(argp, &r, sizeof(r)))  		return -EFAULT;  	return ret; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index bc737261f23..d6488674d91 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -810,7 +810,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)  			return;  		}  		need_unlock = 1; -	} +	} else if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE)) +		return;  	if (current->journal_info == NULL) {  		ret = gfs2_trans_begin(sdp, RES_DINODE, 0); diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index adbd27875ef..413627072f3 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c @@ -155,14 +155,22 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta)  	struct gfs2_sbd *sdp = gl->gl_sbd;  	struct gfs2_bufdata *bd; +	lock_buffer(bh); +	gfs2_log_lock(sdp);  	bd = bh->b_private;  	if (bd)  		gfs2_assert(sdp, bd->bd_gl == gl);  	else { +		gfs2_log_unlock(sdp); +		unlock_buffer(bh);  		gfs2_attach_bufdata(gl, bh, meta);  		bd = bh->b_private; +		lock_buffer(bh); +		gfs2_log_lock(sdp);  	}  	lops_add(sdp, bd); +	gfs2_log_unlock(sdp); +	unlock_buffer(bh);  }  void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index e4fb3ba5a58..3d7e09bcc0e 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -85,29 +85,38 @@ static struct rpc_clnt *nsm_create(struct net *net)  	return rpc_create(&args);  } +static struct rpc_clnt *nsm_client_set(struct lockd_net *ln, +		struct rpc_clnt *clnt) +{ +	spin_lock(&ln->nsm_clnt_lock); +	if (ln->nsm_users == 0) { +		if (clnt == NULL) +			goto out; +		ln->nsm_clnt = clnt; +	} +	clnt = ln->nsm_clnt; +	ln->nsm_users++; +out: +	spin_unlock(&ln->nsm_clnt_lock); +	return clnt; +} +  static struct rpc_clnt *nsm_client_get(struct net *net)  { -	static DEFINE_MUTEX(nsm_create_mutex); -	struct rpc_clnt	*clnt; +	struct rpc_clnt	*clnt, *new;  	struct lockd_net *ln = net_generic(net, lockd_net_id); -	spin_lock(&ln->nsm_clnt_lock); -	if (ln->nsm_users) { -		ln->nsm_users++; -		clnt = ln->nsm_clnt; -		spin_unlock(&ln->nsm_clnt_lock); +	clnt = nsm_client_set(ln, NULL); +	if (clnt != NULL)  		goto out; -	} -	spin_unlock(&ln->nsm_clnt_lock); -	mutex_lock(&nsm_create_mutex); -	clnt = nsm_create(net); -	if (!IS_ERR(clnt)) { -		ln->nsm_clnt = clnt; -		smp_wmb(); -		ln->nsm_users = 1; -	} -	mutex_unlock(&nsm_create_mutex); +	clnt = new = nsm_create(net); +	if (IS_ERR(clnt)) +		goto out; + +	clnt = nsm_client_set(ln, new); +	if (clnt != new) +		rpc_shutdown_client(new);  out:  	return clnt;  } @@ -115,18 +124,16 @@ out:  static void nsm_client_put(struct net *net)  {  	struct lockd_net *ln = net_generic(net, lockd_net_id); -	struct rpc_clnt	*clnt = ln->nsm_clnt; -	int shutdown = 0; +	struct rpc_clnt	*clnt = NULL;  	spin_lock(&ln->nsm_clnt_lock); -	if (ln->nsm_users) { -		if (--ln->nsm_users) -			ln->nsm_clnt = NULL; -		shutdown = !ln->nsm_users; +	ln->nsm_users--; +	if (ln->nsm_users == 0) { +		clnt = ln->nsm_clnt; +		ln->nsm_clnt = NULL;  	}  	spin_unlock(&ln->nsm_clnt_lock); - -	if (shutdown) +	if (clnt != NULL)  		rpc_shutdown_client(clnt);  } diff --git a/fs/namei.c b/fs/namei.c index d1895f30815..937f9d50c84 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -705,8 +705,8 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki  	path_put(link);  } -int sysctl_protected_symlinks __read_mostly = 1; -int sysctl_protected_hardlinks __read_mostly = 1; +int sysctl_protected_symlinks __read_mostly = 0; +int sysctl_protected_hardlinks __read_mostly = 0;  /**   * may_follow_link - Check symlink following for unsafe situations diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index 31c26c4dcc2..ca4b11ec87a 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c @@ -217,7 +217,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)  {  	char buf1[NFS_DNS_HOSTNAME_MAXLEN+1];  	struct nfs_dns_ent key, *item; -	unsigned long ttl; +	unsigned int ttl;  	ssize_t len;  	int ret = -EINVAL; @@ -240,7 +240,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)  	key.namelen = len;  	memset(&key.h, 0, sizeof(key.h)); -	ttl = get_expiry(&buf); +	if (get_uint(&buf, &ttl) < 0) +		goto out;  	if (ttl == 0)  		goto out;  	key.h.expiry_time = ttl + seconds_since_boot(); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 5c7325c5c5e..6fa01aea248 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -685,7 +685,10 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)  	if (ctx->cred != NULL)  		put_rpccred(ctx->cred);  	dput(ctx->dentry); -	nfs_sb_deactive(sb); +	if (is_sync) +		nfs_sb_deactive(sb); +	else +		nfs_sb_deactive_async(sb);  	kfree(ctx->mdsthreshold);  	kfree(ctx);  } diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 59b133c5d65..05521cadac2 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -351,10 +351,12 @@ extern int __init register_nfs_fs(void);  extern void __exit unregister_nfs_fs(void);  extern void nfs_sb_active(struct super_block *sb);  extern void nfs_sb_deactive(struct super_block *sb); +extern void nfs_sb_deactive_async(struct super_block *sb);  /* namespace.c */ +#define NFS_PATH_CANONICAL 1  extern char *nfs_path(char **p, struct dentry *dentry, -		      char *buffer, ssize_t buflen); +		      char *buffer, ssize_t buflen, unsigned flags);  extern struct vfsmount *nfs_d_automount(struct path *path);  struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *,  			      struct nfs_fh *, struct nfs_fattr *); @@ -498,7 +500,7 @@ static inline char *nfs_devname(struct dentry *dentry,  				char *buffer, ssize_t buflen)  {  	char *dummy; -	return nfs_path(&dummy, dentry, buffer, buflen); +	return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL);  }  /* diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 8e65c7f1f87..015f71f8f62 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c @@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info)  	else  		msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT]; -	status = rpc_call_sync(mnt_clnt, &msg, 0); +	status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT);  	rpc_shutdown_client(mnt_clnt);  	if (status < 0) diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 655925373b9..dd057bc6b65 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -33,6 +33,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;   * @dentry - pointer to dentry   * @buffer - result buffer   * @buflen - length of buffer + * @flags - options (see below)   *   * Helper function for constructing the server pathname   * by arbitrary hashed dentry. @@ -40,8 +41,14 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;   * This is mainly for use in figuring out the path on the   * server side when automounting on top of an existing partition   * and in generating /proc/mounts and friends. + * + * Supported flags: + * NFS_PATH_CANONICAL: ensure there is exactly one slash after + *		       the original device (export) name + *		       (if unset, the original name is returned verbatim)   */ -char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) +char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen, +	       unsigned flags)  {  	char *end;  	int namelen; @@ -74,7 +81,7 @@ rename_retry:  		rcu_read_unlock();  		goto rename_retry;  	} -	if (*end != '/') { +	if ((flags & NFS_PATH_CANONICAL) && *end != '/') {  		if (--buflen < 0) {  			spin_unlock(&dentry->d_lock);  			rcu_read_unlock(); @@ -91,9 +98,11 @@ rename_retry:  		return end;  	}  	namelen = strlen(base); -	/* Strip off excess slashes in base string */ -	while (namelen > 0 && base[namelen - 1] == '/') -		namelen--; +	if (flags & NFS_PATH_CANONICAL) { +		/* Strip off excess slashes in base string */ +		while (namelen > 0 && base[namelen - 1] == '/') +			namelen--; +	}  	buflen -= namelen;  	if (buflen < 0) {  		spin_unlock(&dentry->d_lock); diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 79fbb61ce20..1e09eb78543 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c @@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end)  static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)  {  	char *limit; -	char *path = nfs_path(&limit, dentry, buffer, buflen); +	char *path = nfs_path(&limit, dentry, buffer, buflen, +			      NFS_PATH_CANONICAL);  	if (!IS_ERR(path)) {  		char *path_component = nfs_path_component(path, limit);  		if (path_component) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 68b21d81b7a..5eec4429970 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -339,8 +339,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc  			dprintk("%s ERROR: %d Reset session\n", __func__,  				errorcode);  			nfs4_schedule_session_recovery(clp->cl_session, errorcode); -			exception->retry = 1; -			break; +			goto wait_on_recovery;  #endif /* defined(CONFIG_NFS_V4_1) */  		case -NFS4ERR_FILE_OPEN:  			if (exception->timeout > HZ) { @@ -1572,9 +1571,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)  	data->timestamp = jiffies;  	if (nfs4_setup_sequence(data->o_arg.server,  				&data->o_arg.seq_args, -				&data->o_res.seq_res, task)) -		return; -	rpc_call_start(task); +				&data->o_res.seq_res, +				task) != 0) +		nfs_release_seqid(data->o_arg.seqid); +	else +		rpc_call_start(task);  	return;  unlock_no_action:  	rcu_read_unlock(); @@ -1748,7 +1749,7 @@ static int nfs4_opendata_access(struct rpc_cred *cred,  	/* even though OPEN succeeded, access is denied. Close the file */  	nfs4_close_state(state, fmode); -	return -NFS4ERR_ACCESS; +	return -EACCES;  }  /* @@ -2196,7 +2197,7 @@ static void nfs4_free_closedata(void *data)  	nfs4_put_open_state(calldata->state);  	nfs_free_seqid(calldata->arg.seqid);  	nfs4_put_state_owner(sp); -	nfs_sb_deactive(sb); +	nfs_sb_deactive_async(sb);  	kfree(calldata);  } @@ -2296,9 +2297,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)  	if (nfs4_setup_sequence(NFS_SERVER(inode),  				&calldata->arg.seq_args,  				&calldata->res.seq_res, -				task)) -		goto out; -	rpc_call_start(task); +				task) != 0) +		nfs_release_seqid(calldata->arg.seqid); +	else +		rpc_call_start(task);  out:  	dprintk("%s: done!\n", __func__);  } @@ -4529,6 +4531,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)  			if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)  				rpc_restart_call_prepare(task);  	} +	nfs_release_seqid(calldata->arg.seqid);  }  static void nfs4_locku_prepare(struct rpc_task *task, void *data) @@ -4545,9 +4548,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)  	calldata->timestamp = jiffies;  	if (nfs4_setup_sequence(calldata->server,  				&calldata->arg.seq_args, -				&calldata->res.seq_res, task)) -		return; -	rpc_call_start(task); +				&calldata->res.seq_res, +				task) != 0) +		nfs_release_seqid(calldata->arg.seqid); +	else +		rpc_call_start(task);  }  static const struct rpc_call_ops nfs4_locku_ops = { @@ -4692,7 +4697,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)  	/* Do we need to do an open_to_lock_owner? */  	if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {  		if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) -			return; +			goto out_release_lock_seqid;  		data->arg.open_stateid = &state->stateid;  		data->arg.new_lock_owner = 1;  		data->res.open_seqid = data->arg.open_seqid; @@ -4701,10 +4706,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)  	data->timestamp = jiffies;  	if (nfs4_setup_sequence(data->server,  				&data->arg.seq_args, -				&data->res.seq_res, task)) +				&data->res.seq_res, +				task) == 0) { +		rpc_call_start(task);  		return; -	rpc_call_start(task); -	dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); +	} +	nfs_release_seqid(data->arg.open_seqid); +out_release_lock_seqid: +	nfs_release_seqid(data->arg.lock_seqid); +	dprintk("%s: done!, ret = %d\n", __func__, task->tk_status);  }  static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) @@ -5667,7 +5677,7 @@ static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,  		tbl->slots = new;  		tbl->max_slots = max_slots;  	} -	tbl->highest_used_slotid = -1;	/* no slot is currently used */ +	tbl->highest_used_slotid = NFS4_NO_SLOT;  	for (i = 0; i < tbl->max_slots; i++)  		tbl->slots[i].seq_nr = ivalue;  	spin_unlock(&tbl->slot_tbl_lock); diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index fe624c91bd0..2878f97bd78 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -925,8 +925,8 @@ pnfs_find_alloc_layout(struct inode *ino,  	if (likely(nfsi->layout == NULL)) {	/* Won the race? */  		nfsi->layout = new;  		return new; -	} -	pnfs_free_layout_hdr(new); +	} else if (new != NULL) +		pnfs_free_layout_hdr(new);  out_existing:  	pnfs_get_layout_hdr(nfsi->layout);  	return nfsi->layout; diff --git a/fs/nfs/super.c b/fs/nfs/super.c index e831bce4976..652d3f7176a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -54,6 +54,7 @@  #include <linux/parser.h>  #include <linux/nsproxy.h>  #include <linux/rcupdate.h> +#include <linux/kthread.h>  #include <asm/uaccess.h> @@ -415,6 +416,54 @@ void nfs_sb_deactive(struct super_block *sb)  }  EXPORT_SYMBOL_GPL(nfs_sb_deactive); +static int nfs_deactivate_super_async_work(void *ptr) +{ +	struct super_block *sb = ptr; + +	deactivate_super(sb); +	module_put_and_exit(0); +	return 0; +} + +/* + * same effect as deactivate_super, but will do final unmount in kthread + * context + */ +static void nfs_deactivate_super_async(struct super_block *sb) +{ +	struct task_struct *task; +	char buf[INET6_ADDRSTRLEN + 1]; +	struct nfs_server *server = NFS_SB(sb); +	struct nfs_client *clp = server->nfs_client; + +	if (!atomic_add_unless(&sb->s_active, -1, 1)) { +		rcu_read_lock(); +		snprintf(buf, sizeof(buf), +			rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); +		rcu_read_unlock(); + +		__module_get(THIS_MODULE); +		task = kthread_run(nfs_deactivate_super_async_work, sb, +				"%s-deactivate-super", buf); +		if (IS_ERR(task)) { +			pr_err("%s: kthread_run: %ld\n", +				__func__, PTR_ERR(task)); +			/* make synchronous call and hope for the best */ +			deactivate_super(sb); +			module_put(THIS_MODULE); +		} +	} +} + +void nfs_sb_deactive_async(struct super_block *sb) +{ +	struct nfs_server *server = NFS_SB(sb); + +	if (atomic_dec_and_test(&server->active)) +		nfs_deactivate_super_async(sb); +} +EXPORT_SYMBOL_GPL(nfs_sb_deactive_async); +  /*   * Deliver file system statistics to userspace   */ @@ -771,7 +820,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root)  	int err = 0;  	if (!page)  		return -ENOMEM; -	devname = nfs_path(&dummy, root, page, PAGE_SIZE); +	devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0);  	if (IS_ERR(devname))  		err = PTR_ERR(devname);  	else diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 13cea637eff..3f79c77153b 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -95,7 +95,7 @@ static void nfs_async_unlink_release(void *calldata)  	nfs_dec_sillycount(data->dir);  	nfs_free_unlinkdata(data); -	nfs_sb_deactive(sb); +	nfs_sb_deactive_async(sb);  }  static void nfs_unlink_prepare(struct rpc_task *task, void *calldata) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index f35794b97e8..a5063602536 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)  			if ((old->path.mnt == new->path.mnt) &&  			    (old->path.dentry == new->path.dentry))  				return true; +			break;  		case (FSNOTIFY_EVENT_NONE):  			return true;  		default: diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 6b0bb00d4d2..2fbdff6be25 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -485,20 +485,18 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)  /**   *	sysfs_pathname - return full path to sysfs dirent   *	@sd: sysfs_dirent whose path we want - *	@path: caller allocated buffer + *	@path: caller allocated buffer of size PATH_MAX   *   *	Gives the name "/" to the sysfs_root entry; any path returned   *	is relative to wherever sysfs is mounted. - * - *	XXX: does no error checking on @path size   */  static char *sysfs_pathname(struct sysfs_dirent *sd, char *path)  {  	if (sd->s_parent) {  		sysfs_pathname(sd->s_parent, path); -		strcat(path, "/"); +		strlcat(path, "/", PATH_MAX);  	} -	strcat(path, sd->s_name); +	strlcat(path, sd->s_name, PATH_MAX);  	return path;  } @@ -531,9 +529,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)  		char *path = kzalloc(PATH_MAX, GFP_KERNEL);  		WARN(1, KERN_WARNING  		     "sysfs: cannot create duplicate filename '%s'\n", -		     (path == NULL) ? sd->s_name : -		     strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"), -		            sd->s_name)); +		     (path == NULL) ? sd->s_name +				    : (sysfs_pathname(acxt->parent_sd, path), +				       strlcat(path, "/", PATH_MAX), +				       strlcat(path, sd->s_name, PATH_MAX), +				       path));  		kfree(path);  	} diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 4f33c32affe..335206a9c69 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -1866,6 +1866,7 @@ xfs_alloc_fix_freelist(  	/*  	 * Initialize the args structure.  	 */ +	memset(&targs, 0, sizeof(targs));  	targs.tp = tp;  	targs.mp = mp;  	targs.agbp = agbp; @@ -2207,7 +2208,7 @@ xfs_alloc_read_agf(   * group or loop over the allocation groups to find the result.   */  int				/* error */ -__xfs_alloc_vextent( +xfs_alloc_vextent(  	xfs_alloc_arg_t	*args)	/* allocation argument structure */  {  	xfs_agblock_t	agsize;	/* allocation group size */ @@ -2417,46 +2418,6 @@ error0:  	return error;  } -static void -xfs_alloc_vextent_worker( -	struct work_struct	*work) -{ -	struct xfs_alloc_arg	*args = container_of(work, -						struct xfs_alloc_arg, work); -	unsigned long		pflags; - -	/* we are in a transaction context here */ -	current_set_flags_nested(&pflags, PF_FSTRANS); - -	args->result = __xfs_alloc_vextent(args); -	complete(args->done); - -	current_restore_flags_nested(&pflags, PF_FSTRANS); -} - -/* - * Data allocation requests often come in with little stack to work on. Push - * them off to a worker thread so there is lots of stack to use. Metadata - * requests, OTOH, are generally from low stack usage paths, so avoid the - * context switch overhead here. - */ -int -xfs_alloc_vextent( -	struct xfs_alloc_arg	*args) -{ -	DECLARE_COMPLETION_ONSTACK(done); - -	if (!args->userdata) -		return __xfs_alloc_vextent(args); - - -	args->done = &done; -	INIT_WORK_ONSTACK(&args->work, xfs_alloc_vextent_worker); -	queue_work(xfs_alloc_wq, &args->work); -	wait_for_completion(&done); -	return args->result; -} -  /*   * Free an extent.   * Just break up the extent address and hand off to xfs_free_ag_extent diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index 93be4a667ca..feacb061bab 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h @@ -120,9 +120,6 @@ typedef struct xfs_alloc_arg {  	char		isfl;		/* set if is freelist blocks - !acctg */  	char		userdata;	/* set if this is user data */  	xfs_fsblock_t	firstblock;	/* io first block allocated */ -	struct completion *done; -	struct work_struct work; -	int		result;  } xfs_alloc_arg_t;  /* diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index f1647caace8..f7876c6d616 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c @@ -121,6 +121,8 @@ xfs_allocbt_free_block(  	xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1,  			      XFS_EXTENT_BUSY_SKIP_DISCARD);  	xfs_trans_agbtree_delta(cur->bc_tp, -1); + +	xfs_trans_binval(cur->bc_tp, bp);  	return 0;  } diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 848ffa77707..83d0cf3df93 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2437,6 +2437,7 @@ xfs_bmap_btalloc(  	 * Normal allocation, done through xfs_alloc_vextent.  	 */  	tryagain = isaligned = 0; +	memset(&args, 0, sizeof(args));  	args.tp = ap->tp;  	args.mp = mp;  	args.fsbno = ap->blkno; @@ -3082,6 +3083,7 @@ xfs_bmap_extents_to_btree(  	 * Convert to a btree with two levels, one record in root.  	 */  	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE); +	memset(&args, 0, sizeof(args));  	args.tp = tp;  	args.mp = mp;  	args.firstblock = *firstblock; @@ -3237,6 +3239,7 @@ xfs_bmap_local_to_extents(  		xfs_buf_t	*bp;	/* buffer for extent block */  		xfs_bmbt_rec_host_t *ep;/* extent record pointer */ +		memset(&args, 0, sizeof(args));  		args.tp = tp;  		args.mp = ip->i_mount;  		args.firstblock = *firstblock; @@ -4616,12 +4619,11 @@ xfs_bmapi_delay(  STATIC int -xfs_bmapi_allocate( -	struct xfs_bmalloca	*bma, -	int			flags) +__xfs_bmapi_allocate( +	struct xfs_bmalloca	*bma)  {  	struct xfs_mount	*mp = bma->ip->i_mount; -	int			whichfork = (flags & XFS_BMAPI_ATTRFORK) ? +	int			whichfork = (bma->flags & XFS_BMAPI_ATTRFORK) ?  						XFS_ATTR_FORK : XFS_DATA_FORK;  	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork);  	int			tmp_logflags = 0; @@ -4654,24 +4656,27 @@ xfs_bmapi_allocate(  	 * Indicate if this is the first user data in the file, or just any  	 * user data.  	 */ -	if (!(flags & XFS_BMAPI_METADATA)) { +	if (!(bma->flags & XFS_BMAPI_METADATA)) {  		bma->userdata = (bma->offset == 0) ?  			XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA;  	} -	bma->minlen = (flags & XFS_BMAPI_CONTIG) ? bma->length : 1; +	bma->minlen = (bma->flags & XFS_BMAPI_CONTIG) ? bma->length : 1;  	/*  	 * Only want to do the alignment at the eof if it is userdata and  	 * allocation length is larger than a stripe unit.  	 */  	if (mp->m_dalign && bma->length >= mp->m_dalign && -	    !(flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) { +	    !(bma->flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {  		error = xfs_bmap_isaeof(bma, whichfork);  		if (error)  			return error;  	} +	if (bma->flags & XFS_BMAPI_STACK_SWITCH) +		bma->stack_switch = 1; +  	error = xfs_bmap_alloc(bma);  	if (error)  		return error; @@ -4706,7 +4711,7 @@ xfs_bmapi_allocate(  	 * A wasdelay extent has been initialized, so shouldn't be flagged  	 * as unwritten.  	 */ -	if (!bma->wasdel && (flags & XFS_BMAPI_PREALLOC) && +	if (!bma->wasdel && (bma->flags & XFS_BMAPI_PREALLOC) &&  	    xfs_sb_version_hasextflgbit(&mp->m_sb))  		bma->got.br_state = XFS_EXT_UNWRITTEN; @@ -4734,6 +4739,45 @@ xfs_bmapi_allocate(  	return 0;  } +static void +xfs_bmapi_allocate_worker( +	struct work_struct	*work) +{ +	struct xfs_bmalloca	*args = container_of(work, +						struct xfs_bmalloca, work); +	unsigned long		pflags; + +	/* we are in a transaction context here */ +	current_set_flags_nested(&pflags, PF_FSTRANS); + +	args->result = __xfs_bmapi_allocate(args); +	complete(args->done); + +	current_restore_flags_nested(&pflags, PF_FSTRANS); +} + +/* + * Some allocation requests often come in with little stack to work on. Push + * them off to a worker thread so there is lots of stack to use. Otherwise just + * call directly to avoid the context switch overhead here. + */ +int +xfs_bmapi_allocate( +	struct xfs_bmalloca	*args) +{ +	DECLARE_COMPLETION_ONSTACK(done); + +	if (!args->stack_switch) +		return __xfs_bmapi_allocate(args); + + +	args->done = &done; +	INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker); +	queue_work(xfs_alloc_wq, &args->work); +	wait_for_completion(&done); +	return args->result; +} +  STATIC int  xfs_bmapi_convert_unwritten(  	struct xfs_bmalloca	*bma, @@ -4919,6 +4963,7 @@ xfs_bmapi_write(  			bma.conv = !!(flags & XFS_BMAPI_CONVERT);  			bma.wasdel = wasdelay;  			bma.offset = bno; +			bma.flags = flags;  			/*  			 * There's a 32/64 bit type mismatch between the @@ -4934,7 +4979,7 @@ xfs_bmapi_write(  			ASSERT(len > 0);  			ASSERT(bma.length > 0); -			error = xfs_bmapi_allocate(&bma, flags); +			error = xfs_bmapi_allocate(&bma);  			if (error)  				goto error0;  			if (bma.blkno == NULLFSBLOCK) diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 803b56d7ce1..5f469c3516e 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h @@ -77,6 +77,7 @@ typedef	struct xfs_bmap_free   * from written to unwritten, otherwise convert from unwritten to written.   */  #define XFS_BMAPI_CONVERT	0x040 +#define XFS_BMAPI_STACK_SWITCH	0x080  #define XFS_BMAPI_FLAGS \  	{ XFS_BMAPI_ENTIRE,	"ENTIRE" }, \ @@ -85,7 +86,8 @@ typedef	struct xfs_bmap_free  	{ XFS_BMAPI_PREALLOC,	"PREALLOC" }, \  	{ XFS_BMAPI_IGSTATE,	"IGSTATE" }, \  	{ XFS_BMAPI_CONTIG,	"CONTIG" }, \ -	{ XFS_BMAPI_CONVERT,	"CONVERT" } +	{ XFS_BMAPI_CONVERT,	"CONVERT" }, \ +	{ XFS_BMAPI_STACK_SWITCH, "STACK_SWITCH" }  static inline int xfs_bmapi_aflag(int w) @@ -133,6 +135,11 @@ typedef struct xfs_bmalloca {  	char			userdata;/* set if is user data */  	char			aeof;	/* allocated space at eof */  	char			conv;	/* overwriting unwritten extents */ +	char			stack_switch; +	int			flags; +	struct completion	*done; +	struct work_struct	work; +	int			result;  } xfs_bmalloca_t;  /* diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index a8d0ed91119..becf4a97efc 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -526,7 +526,25 @@ xfs_buf_item_unpin(  		}  		xfs_buf_relse(bp);  	} else if (freed && remove) { +		/* +		 * There are currently two references to the buffer - the active +		 * LRU reference and the buf log item. What we are about to do +		 * here - simulate a failed IO completion - requires 3 +		 * references. +		 * +		 * The LRU reference is removed by the xfs_buf_stale() call. The +		 * buf item reference is removed by the xfs_buf_iodone() +		 * callback that is run by xfs_buf_do_callbacks() during ioend +		 * processing (via the bp->b_iodone callback), and then finally +		 * the ioend processing will drop the IO reference if the buffer +		 * is marked XBF_ASYNC. +		 * +		 * Hence we need to take an additional reference here so that IO +		 * completion processing doesn't free the buffer prematurely. +		 */  		xfs_buf_lock(bp); +		xfs_buf_hold(bp); +		bp->b_flags |= XBF_ASYNC;  		xfs_buf_ioerror(bp, EIO);  		XFS_BUF_UNDONE(bp);  		xfs_buf_stale(bp); diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index c25b094efbf..4beaede4327 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -399,9 +399,26 @@ xfs_growfs_data_private(  	/* update secondary superblocks. */  	for (agno = 1; agno < nagcount; agno++) { -		error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, +		error = 0; +		/* +		 * new secondary superblocks need to be zeroed, not read from +		 * disk as the contents of the new area we are growing into is +		 * completely unknown. +		 */ +		if (agno < oagcount) { +			error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,  				  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),  				  XFS_FSS_TO_BB(mp, 1), 0, &bp); +		} else { +			bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp, +				  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), +				  XFS_FSS_TO_BB(mp, 1), 0); +			if (bp) +				xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); +			else +				error = ENOMEM; +		} +  		if (error) {  			xfs_warn(mp,  		"error %d reading secondary superblock for ag %d", @@ -423,7 +440,7 @@ xfs_growfs_data_private(  			break; /* no point in continuing */  		}  	} -	return 0; +	return error;   error0:  	xfs_trans_cancel(tp, XFS_TRANS_ABORT); diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 445bf1aef31..c5c4ef4f2bd 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -250,6 +250,7 @@ xfs_ialloc_ag_alloc(  					/* boundary */  	struct xfs_perag *pag; +	memset(&args, 0, sizeof(args));  	args.tp = tp;  	args.mp = tp->t_mountp; diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 2778258fcfa..1938b41ee9f 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1509,7 +1509,8 @@ xfs_ifree_cluster(  		 * to mark all the active inodes on the buffer stale.  		 */  		bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno, -					mp->m_bsize * blks_per_cluster, 0); +					mp->m_bsize * blks_per_cluster, +					XBF_UNMAPPED);  		if (!bp)  			return ENOMEM; diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 8305f2ac677..c1df3c623de 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -70,7 +70,7 @@ xfs_find_handle(  	int			hsize;  	xfs_handle_t		handle;  	struct inode		*inode; -	struct fd		f; +	struct fd		f = {0};  	struct path		path;  	int			error;  	struct xfs_inode	*ip; diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 973dff6ad93..7f537663365 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -584,7 +584,9 @@ xfs_iomap_write_allocate(  			 * pointer that the caller gave to us.  			 */  			error = xfs_bmapi_write(tp, ip, map_start_fsb, -						count_fsb, 0, &first_block, 1, +						count_fsb, +						XFS_BMAPI_STACK_SWITCH, +						&first_block, 1,  						imap, &nimaps, &free_list);  			if (error)  				goto trans_cancel; diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 7f4f9370d0e..4dad756962d 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -2387,14 +2387,27 @@ xlog_state_do_callback(  				/* -				 * update the last_sync_lsn before we drop the +				 * Completion of a iclog IO does not imply that +				 * a transaction has completed, as transactions +				 * can be large enough to span many iclogs. We +				 * cannot change the tail of the log half way +				 * through a transaction as this may be the only +				 * transaction in the log and moving th etail to +				 * point to the middle of it will prevent +				 * recovery from finding the start of the +				 * transaction. Hence we should only update the +				 * last_sync_lsn if this iclog contains +				 * transaction completion callbacks on it. +				 * +				 * We have to do this before we drop the  				 * icloglock to ensure we are the only one that  				 * can update it.  				 */  				ASSERT(XFS_LSN_CMP(atomic64_read(&log->l_last_sync_lsn),  					be64_to_cpu(iclog->ic_header.h_lsn)) <= 0); -				atomic64_set(&log->l_last_sync_lsn, -					be64_to_cpu(iclog->ic_header.h_lsn)); +				if (iclog->ic_callback) +					atomic64_set(&log->l_last_sync_lsn, +						be64_to_cpu(iclog->ic_header.h_lsn));  			} else  				ioerrors++; diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 5da3ace352b..d308749fabf 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3541,7 +3541,7 @@ xlog_do_recovery_pass(  				 *   - order is important.  				 */  				error = xlog_bread_offset(log, 0, -						bblks - split_bblks, hbp, +						bblks - split_bblks, dbp,  						offset + BBTOB(split_bblks));  				if (error)  					goto bread_err2; diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index c78bb997e2c..af1cbaf535e 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -205,6 +205,8 @@  	{0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ @@ -217,6 +219,7 @@  	{0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index c18257b0fa7..6dd4787a798 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -61,7 +61,7 @@ int __dynamic_netdev_dbg(struct _ddebug *descriptor,  			 const char *fmt, ...);  #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\ -	static struct _ddebug __used __aligned(8)		\ +	static struct _ddebug  __aligned(8)			\  	__attribute__((section("__verbose"))) name = {		\  		.modname = KBUILD_MODNAME,			\  		.function = __func__,				\ diff --git a/include/linux/extcon.h b/include/linux/extcon.h index 7443a560c9d..2c26c14cd71 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -68,7 +68,7 @@ enum extcon_cable_name {  	EXTCON_VIDEO_OUT,  	EXTCON_MECHANICAL,  }; -extern const char *extcon_cable_name[]; +extern const char extcon_cable_name[][CABLE_NAME_MAX + 1];  struct extcon_cable; diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h new file mode 100644 index 00000000000..227c62424f3 --- /dev/null +++ b/include/linux/hashtable.h @@ -0,0 +1,192 @@ +/* + * Statically sized hash table implementation + * (C) 2012  Sasha Levin <levinsasha928@gmail.com> + */ + +#ifndef _LINUX_HASHTABLE_H +#define _LINUX_HASHTABLE_H + +#include <linux/list.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/hash.h> +#include <linux/rculist.h> + +#define DEFINE_HASHTABLE(name, bits)						\ +	struct hlist_head name[1 << (bits)] =					\ +			{ [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT } + +#define DECLARE_HASHTABLE(name, bits)                                   	\ +	struct hlist_head name[1 << (bits)] + +#define HASH_SIZE(name) (ARRAY_SIZE(name)) +#define HASH_BITS(name) ilog2(HASH_SIZE(name)) + +/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */ +#define hash_min(val, bits)							\ +	(sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits)) + +static inline void __hash_init(struct hlist_head *ht, unsigned int sz) +{ +	unsigned int i; + +	for (i = 0; i < sz; i++) +		INIT_HLIST_HEAD(&ht[i]); +} + +/** + * hash_init - initialize a hash table + * @hashtable: hashtable to be initialized + * + * Calculates the size of the hashtable from the given parameter, otherwise + * same as hash_init_size. + * + * This has to be a macro since HASH_BITS() will not work on pointers since + * it calculates the size during preprocessing. + */ +#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable)) + +/** + * hash_add - add an object to a hashtable + * @hashtable: hashtable to add to + * @node: the &struct hlist_node of the object to be added + * @key: the key of the object to be added + */ +#define hash_add(hashtable, node, key)						\ +	hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))]) + +/** + * hash_add_rcu - add an object to a rcu enabled hashtable + * @hashtable: hashtable to add to + * @node: the &struct hlist_node of the object to be added + * @key: the key of the object to be added + */ +#define hash_add_rcu(hashtable, node, key)					\ +	hlist_add_head_rcu(node, &hashtable[hash_min(key, HASH_BITS(hashtable))]) + +/** + * hash_hashed - check whether an object is in any hashtable + * @node: the &struct hlist_node of the object to be checked + */ +static inline bool hash_hashed(struct hlist_node *node) +{ +	return !hlist_unhashed(node); +} + +static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz) +{ +	unsigned int i; + +	for (i = 0; i < sz; i++) +		if (!hlist_empty(&ht[i])) +			return false; + +	return true; +} + +/** + * hash_empty - check whether a hashtable is empty + * @hashtable: hashtable to check + * + * This has to be a macro since HASH_BITS() will not work on pointers since + * it calculates the size during preprocessing. + */ +#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable)) + +/** + * hash_del - remove an object from a hashtable + * @node: &struct hlist_node of the object to remove + */ +static inline void hash_del(struct hlist_node *node) +{ +	hlist_del_init(node); +} + +/** + * hash_del_rcu - remove an object from a rcu enabled hashtable + * @node: &struct hlist_node of the object to remove + */ +static inline void hash_del_rcu(struct hlist_node *node) +{ +	hlist_del_init_rcu(node); +} + +/** + * hash_for_each - iterate over a hashtable + * @name: hashtable to iterate + * @bkt: integer to use as bucket loop cursor + * @node: the &struct list_head to use as a loop cursor for each entry + * @obj: the type * to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + */ +#define hash_for_each(name, bkt, node, obj, member)				\ +	for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ +		hlist_for_each_entry(obj, node, &name[bkt], member) + +/** + * hash_for_each_rcu - iterate over a rcu enabled hashtable + * @name: hashtable to iterate + * @bkt: integer to use as bucket loop cursor + * @node: the &struct list_head to use as a loop cursor for each entry + * @obj: the type * to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + */ +#define hash_for_each_rcu(name, bkt, node, obj, member)				\ +	for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ +		hlist_for_each_entry_rcu(obj, node, &name[bkt], member) + +/** + * hash_for_each_safe - iterate over a hashtable safe against removal of + * hash entry + * @name: hashtable to iterate + * @bkt: integer to use as bucket loop cursor + * @node: the &struct list_head to use as a loop cursor for each entry + * @tmp: a &struct used for temporary storage + * @obj: the type * to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + */ +#define hash_for_each_safe(name, bkt, node, tmp, obj, member)			\ +	for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ +		hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member) + +/** + * hash_for_each_possible - iterate over all possible objects hashing to the + * same bucket + * @name: hashtable to iterate + * @obj: the type * to use as a loop cursor for each entry + * @node: the &struct list_head to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + * @key: the key of the objects to iterate over + */ +#define hash_for_each_possible(name, obj, node, member, key)			\ +	hlist_for_each_entry(obj, node,	&name[hash_min(key, HASH_BITS(name))], member) + +/** + * hash_for_each_possible_rcu - iterate over all possible objects hashing to the + * same bucket in an rcu enabled hashtable + * in a rcu enabled hashtable + * @name: hashtable to iterate + * @obj: the type * to use as a loop cursor for each entry + * @node: the &struct list_head to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + * @key: the key of the objects to iterate over + */ +#define hash_for_each_possible_rcu(name, obj, node, member, key)		\ +	hlist_for_each_entry_rcu(obj, node, &name[hash_min(key, HASH_BITS(name))], member) + +/** + * hash_for_each_possible_safe - iterate over all possible objects hashing to the + * same bucket safe against removals + * @name: hashtable to iterate + * @obj: the type * to use as a loop cursor for each entry + * @node: the &struct list_head to use as a loop cursor for each entry + * @tmp: a &struct used for temporary storage + * @member: the name of the hlist_node within the struct + * @key: the key of the objects to iterate over + */ +#define hash_for_each_possible_safe(name, obj, node, tmp, member, key)		\ +	hlist_for_each_entry_safe(obj, node, tmp,				\ +		&name[hash_min(key, HASH_BITS(name))], member) + + +#endif diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index c0ae76ac4e0..7806c24e5bc 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -618,4 +618,20 @@ static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)  };  #endif +/** + * IIO_DEGREE_TO_RAD() - Convert degree to rad + * @deg: A value in degree + * + * Returns the given value converted from degree to rad + */ +#define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL) + +/** + * IIO_G_TO_M_S_2() - Convert g to meter / second**2 + * @g: A value in g + * + * Returns the given value converted from g to meter / second**2 + */ +#define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL) +  #endif /* _INDUSTRIAL_IO_H_ */ diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 0e2212fe478..3738c260dde 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -42,19 +42,8 @@   */  #define KVM_MEMSLOT_INVALID	(1UL << 16) -/* - * If we support unaligned MMIO, at most one fragment will be split into two: - */ -#ifdef KVM_UNALIGNED_MMIO -#  define KVM_EXTRA_MMIO_FRAGMENTS 1 -#else -#  define KVM_EXTRA_MMIO_FRAGMENTS 0 -#endif - -#define KVM_USER_MMIO_SIZE 8 - -#define KVM_MAX_MMIO_FRAGMENTS \ -	(KVM_MMIO_SIZE / KVM_USER_MMIO_SIZE + KVM_EXTRA_MMIO_FRAGMENTS) +/* Two fragments for cross MMIO pages. */ +#define KVM_MAX_MMIO_FRAGMENTS	2  /*   * For the normal pfn, the highest 12 bits should be zero, diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 569d67d4243..d452ee19106 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size);  int memblock_remove(phys_addr_t base, phys_addr_t size);  int memblock_free(phys_addr_t base, phys_addr_t size);  int memblock_reserve(phys_addr_t base, phys_addr_t size); +void memblock_trim_memory(phys_addr_t align);  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP  void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, diff --git a/include/linux/mfd/max77693.h b/include/linux/mfd/max77693.h index 1d28ae90384..fe03b2d35d4 100644 --- a/include/linux/mfd/max77693.h +++ b/include/linux/mfd/max77693.h @@ -30,7 +30,20 @@  #ifndef __LINUX_MFD_MAX77693_H  #define __LINUX_MFD_MAX77693_H +struct max77693_reg_data { +	u8 addr; +	u8 data; +}; + +struct max77693_muic_platform_data { +	struct max77693_reg_data *init_data; +	int num_init_data; +}; +  struct max77693_platform_data {  	int wakeup; + +	/* muic data */ +	struct max77693_muic_platform_data *muic_data;  };  #endif	/* __LINUX_MFD_MAX77693_H */ diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 7c6a1139d8f..96531664a06 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -137,7 +137,7 @@ struct dw_mci {  	dma_addr_t		sg_dma;  	void			*sg_cpu; -	struct dw_mci_dma_ops	*dma_ops; +	const struct dw_mci_dma_ops	*dma_ops;  #ifdef CONFIG_MMC_DW_IDMAC  	unsigned int		ring_size;  #else @@ -162,7 +162,7 @@ struct dw_mci {  	u16			data_offset;  	struct device		*dev;  	struct dw_mci_board	*pdata; -	struct dw_mci_drv_data	*drv_data; +	const struct dw_mci_drv_data	*drv_data;  	void			*priv;  	struct clk		*biu_clk;  	struct clk		*ciu_clk; @@ -186,7 +186,7 @@ struct dw_mci {  	struct regulator	*vmmc;	/* Power regulator */  	unsigned long		irq_flags; /* IRQ flags */ -	unsigned int		irq; +	int			irq;  };  /* DMA ops for Internal/External DMAC interface */ diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index fa8529a859b..1edcb4dad8c 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -91,6 +91,7 @@ struct sdhci_host {  	unsigned int quirks2;	/* More deviations from spec. */  #define SDHCI_QUIRK2_HOST_OFF_CARD_ON			(1<<0) +#define SDHCI_QUIRK2_HOST_NO_CMD23			(1<<1)  	int irq;		/* Device IRQ */  	void __iomem *ioaddr;	/* Mapped address */ diff --git a/include/linux/of_address.h b/include/linux/of_address.h index a1984dd037d..e20e3af68fb 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -28,11 +28,13 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }  #endif  #else /* CONFIG_OF_ADDRESS */ +#ifndef of_address_to_resource  static inline int of_address_to_resource(struct device_node *dev, int index,  					 struct resource *r)  {  	return -EINVAL;  } +#endif  static inline struct device_node *of_find_matching_node_by_address(  					struct device_node *from,  					const struct of_device_id *matches, diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h index cf80f7e5277..250a4acddb2 100644 --- a/include/linux/percpu-rwsem.h +++ b/include/linux/percpu-rwsem.h @@ -12,34 +12,27 @@ struct percpu_rw_semaphore {  	struct mutex mtx;  }; +#define light_mb()	barrier() +#define heavy_mb()	synchronize_sched() +  static inline void percpu_down_read(struct percpu_rw_semaphore *p)  { -	rcu_read_lock(); +	rcu_read_lock_sched();  	if (unlikely(p->locked)) { -		rcu_read_unlock(); +		rcu_read_unlock_sched();  		mutex_lock(&p->mtx);  		this_cpu_inc(*p->counters);  		mutex_unlock(&p->mtx);  		return;  	}  	this_cpu_inc(*p->counters); -	rcu_read_unlock(); +	rcu_read_unlock_sched(); +	light_mb(); /* A, between read of p->locked and read of data, paired with D */  }  static inline void percpu_up_read(struct percpu_rw_semaphore *p)  { -	/* -	 * On X86, write operation in this_cpu_dec serves as a memory unlock -	 * barrier (i.e. memory accesses may be moved before the write, but -	 * no memory accesses are moved past the write). -	 * On other architectures this may not be the case, so we need smp_mb() -	 * there. -	 */ -#if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE)) -	barrier(); -#else -	smp_mb(); -#endif +	light_mb(); /* B, between read of the data and write to p->counter, paired with C */  	this_cpu_dec(*p->counters);  } @@ -58,14 +51,15 @@ static inline void percpu_down_write(struct percpu_rw_semaphore *p)  {  	mutex_lock(&p->mtx);  	p->locked = true; -	synchronize_rcu(); +	synchronize_sched(); /* make sure that all readers exit the rcu_read_lock_sched region */  	while (__percpu_count(p->counters))  		msleep(1); -	smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */ +	heavy_mb(); /* C, between read of p->counter and write to data, paired with B */  }  static inline void percpu_up_write(struct percpu_rw_semaphore *p)  { +	heavy_mb(); /* D, between write to data and write to p->locked, paired with A */  	p->locked = false;  	mutex_unlock(&p->mtx);  } diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 2e902359aee..6bfb2faa0b1 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -803,12 +803,16 @@ static inline void perf_event_task_tick(void)				{ }  do {									\  	static struct notifier_block fn##_nb __cpuinitdata =		\  		{ .notifier_call = fn, .priority = CPU_PRI_PERF };	\ +	unsigned long cpu = smp_processor_id();				\ +	unsigned long flags;						\  	fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE,			\ -		(void *)(unsigned long)smp_processor_id());		\ +		(void *)(unsigned long)cpu);				\ +	local_irq_save(flags);						\  	fn(&fn##_nb, (unsigned long)CPU_STARTING,			\ -		(void *)(unsigned long)smp_processor_id());		\ +		(void *)(unsigned long)cpu);				\ +	local_irq_restore(flags);					\  	fn(&fn##_nb, (unsigned long)CPU_ONLINE,				\ -		(void *)(unsigned long)smp_processor_id());		\ +		(void *)(unsigned long)cpu);				\  	register_cpu_notifier(&fn##_nb);				\  } while (0) diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h index f2dc6d8fc68..38a99350832 100644 --- a/include/linux/ptp_clock_kernel.h +++ b/include/linux/ptp_clock_kernel.h @@ -54,7 +54,8 @@ struct ptp_clock_request {   * clock operations   *   * @adjfreq:  Adjusts the frequency of the hardware clock. - *            parameter delta: Desired period change in parts per billion. + *            parameter delta: Desired frequency offset from nominal frequency + *            in parts per billion   *   * @adjtime:  Shifts the time of the hardware clock.   *            parameter delta: Desired change in nanoseconds. diff --git a/include/linux/raid/Kbuild b/include/linux/raid/Kbuild index 2415a64c5e5..e69de29bb2d 100644 --- a/include/linux/raid/Kbuild +++ b/include/linux/raid/Kbuild @@ -1,2 +0,0 @@ -header-y += md_p.h -header-y += md_u.h diff --git a/include/linux/raid/md_u.h b/include/linux/raid/md_u.h index fb1abb3367e..358c04bfbe2 100644 --- a/include/linux/raid/md_u.h +++ b/include/linux/raid/md_u.h @@ -11,149 +11,10 @@     (for example /usr/src/linux/COPYING); if not, write to the Free     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    */ -  #ifndef _MD_U_H  #define _MD_U_H -/* - * Different major versions are not compatible. - * Different minor versions are only downward compatible. - * Different patchlevel versions are downward and upward compatible. - */ -#define MD_MAJOR_VERSION                0 -#define MD_MINOR_VERSION                90 -/* - * MD_PATCHLEVEL_VERSION indicates kernel functionality. - * >=1 means different superblock formats are selectable using SET_ARRAY_INFO - *     and major_version/minor_version accordingly - * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT - *     in the super status byte - * >=3 means that bitmap superblock version 4 is supported, which uses - *     little-ending representation rather than host-endian - */ -#define MD_PATCHLEVEL_VERSION           3 - -/* ioctls */ - -/* status */ -#define RAID_VERSION		_IOR (MD_MAJOR, 0x10, mdu_version_t) -#define GET_ARRAY_INFO		_IOR (MD_MAJOR, 0x11, mdu_array_info_t) -#define GET_DISK_INFO		_IOR (MD_MAJOR, 0x12, mdu_disk_info_t) -#define PRINT_RAID_DEBUG	_IO (MD_MAJOR, 0x13) -#define RAID_AUTORUN		_IO (MD_MAJOR, 0x14) -#define GET_BITMAP_FILE		_IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t) - -/* configuration */ -#define CLEAR_ARRAY		_IO (MD_MAJOR, 0x20) -#define ADD_NEW_DISK		_IOW (MD_MAJOR, 0x21, mdu_disk_info_t) -#define HOT_REMOVE_DISK		_IO (MD_MAJOR, 0x22) -#define SET_ARRAY_INFO		_IOW (MD_MAJOR, 0x23, mdu_array_info_t) -#define SET_DISK_INFO		_IO (MD_MAJOR, 0x24) -#define WRITE_RAID_INFO		_IO (MD_MAJOR, 0x25) -#define UNPROTECT_ARRAY		_IO (MD_MAJOR, 0x26) -#define PROTECT_ARRAY		_IO (MD_MAJOR, 0x27) -#define HOT_ADD_DISK		_IO (MD_MAJOR, 0x28) -#define SET_DISK_FAULTY		_IO (MD_MAJOR, 0x29) -#define HOT_GENERATE_ERROR	_IO (MD_MAJOR, 0x2a) -#define SET_BITMAP_FILE		_IOW (MD_MAJOR, 0x2b, int) +#include <uapi/linux/raid/md_u.h> -/* usage */ -#define RUN_ARRAY		_IOW (MD_MAJOR, 0x30, mdu_param_t) -/*  0x31 was START_ARRAY  */ -#define STOP_ARRAY		_IO (MD_MAJOR, 0x32) -#define STOP_ARRAY_RO		_IO (MD_MAJOR, 0x33) -#define RESTART_ARRAY_RW	_IO (MD_MAJOR, 0x34) - -/* 63 partitions with the alternate major number (mdp) */ -#define MdpMinorShift 6 -#ifdef __KERNEL__  extern int mdp_major; -#endif - -typedef struct mdu_version_s { -	int major; -	int minor; -	int patchlevel; -} mdu_version_t; - -typedef struct mdu_array_info_s { -	/* -	 * Generic constant information -	 */ -	int major_version; -	int minor_version; -	int patch_version; -	int ctime; -	int level; -	int size; -	int nr_disks; -	int raid_disks; -	int md_minor; -	int not_persistent; - -	/* -	 * Generic state information -	 */ -	int utime;		/*  0 Superblock update time		      */ -	int state;		/*  1 State bits (clean, ...)		      */ -	int active_disks;	/*  2 Number of currently active disks	      */ -	int working_disks;	/*  3 Number of working disks		      */ -	int failed_disks;	/*  4 Number of failed disks		      */ -	int spare_disks;	/*  5 Number of spare disks		      */ - -	/* -	 * Personality information -	 */ -	int layout;		/*  0 the array's physical layout	      */ -	int chunk_size;	/*  1 chunk size in bytes		      */ - -} mdu_array_info_t; - -/* non-obvious values for 'level' */ -#define	LEVEL_MULTIPATH		(-4) -#define	LEVEL_LINEAR		(-1) -#define	LEVEL_FAULTY		(-5) - -/* we need a value for 'no level specified' and 0 - * means 'raid0', so we need something else.  This is - * for internal use only - */ -#define	LEVEL_NONE		(-1000000) - -typedef struct mdu_disk_info_s { -	/* -	 * configuration/status of one particular disk -	 */ -	int number; -	int major; -	int minor; -	int raid_disk; -	int state; - -} mdu_disk_info_t; - -typedef struct mdu_start_info_s { -	/* -	 * configuration/status of one particular disk -	 */ -	int major; -	int minor; -	int raid_disk; -	int state; - -} mdu_start_info_t; - -typedef struct mdu_bitmap_file_s -{ -	char pathname[4096]; -} mdu_bitmap_file_t; - -typedef struct mdu_param_s -{ -	int			personality;	/* 1,2,3,4 */ -	int			chunk_size;	/* in bytes */ -	int			max_fault;	/* unused for now */ -} mdu_param_t; -  #endif  - diff --git a/include/linux/rbtree_augmented.h b/include/linux/rbtree_augmented.h index 214caa33433..2ac60c9cf64 100644 --- a/include/linux/rbtree_augmented.h +++ b/include/linux/rbtree_augmented.h @@ -24,6 +24,7 @@  #ifndef _LINUX_RBTREE_AUGMENTED_H  #define _LINUX_RBTREE_AUGMENTED_H +#include <linux/compiler.h>  #include <linux/rbtree.h>  /* diff --git a/include/linux/spi/tsc2005.h b/include/linux/spi/tsc2005.h index d9b0c84220c..8f721e465e0 100644 --- a/include/linux/spi/tsc2005.h +++ b/include/linux/spi/tsc2005.h @@ -3,8 +3,6 @@   *   * Copyright (C) 2009-2010 Nokia Corporation   * - * Contact: Aaro Koskinen <aaro.koskinen@nokia.com> - *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by   * the Free Software Foundation; either version 2 of the License, or diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 8a7fc4be2d7..60b7aac15e0 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -191,7 +191,8 @@ struct tcp_sock {  	u8	do_early_retrans:1,/* Enable RFC5827 early-retransmit  */  		early_retrans_delayed:1, /* Delayed ER timer installed */  		syn_data:1,	/* SYN includes data */ -		syn_fastopen:1;	/* SYN includes Fast Open option */ +		syn_fastopen:1,	/* SYN includes Fast Open option */ +		syn_data_acked:1;/* data in SYN is acked by SYN-ACK */  /* RTT measurement */  	u32	srtt;		/* smoothed round trip time << 3	*/ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1b498908224..7d5b6000378 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1218,6 +1218,7 @@ struct cfg80211_deauth_request {  	const u8 *ie;  	size_t ie_len;  	u16 reason_code; +	bool local_state_change;  };  /** @@ -2651,6 +2652,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);  unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);  /** + * ieee80211_get_mesh_hdrlen - get mesh extension header length + * @meshhdr: the mesh extension header, only the flags field + *	(first byte) will be accessed + * Returns the length of the extension header, which is always at + * least 6 bytes and at most 18 if address 5 and 6 are present. + */ +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); + +/**   * DOC: Data path helpers   *   * In addition to generic utilities, cfg80211 also offers diff --git a/include/sound/core.h b/include/sound/core.h index bc056687f64..93896ad1fcd 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -132,6 +132,7 @@ struct snd_card {  	int shutdown;			/* this card is going down */  	int free_on_last_close;		/* free in context of file_release */  	wait_queue_head_t shutdown_sleep; +	atomic_t refcount;		/* refcount for disconnection */  	struct device *dev;		/* device assigned to this card */  	struct device *card_dev;	/* cardX object for sysfs */ @@ -189,6 +190,7 @@ struct snd_minor {  	const struct file_operations *f_ops;	/* file operations */  	void *private_data;		/* private data for f_ops->open */  	struct device *dev;		/* device for sysfs */ +	struct snd_card *card_ptr;	/* assigned card instance */  };  /* return a device pointer linked to each sound device as a parent */ @@ -295,6 +297,7 @@ int snd_card_info_done(void);  int snd_component_add(struct snd_card *card, const char *component);  int snd_card_file_add(struct snd_card *card, struct file *file);  int snd_card_file_remove(struct snd_card *card, struct file *file); +void snd_card_unref(struct snd_card *card);  #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr)) diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h index 15ba03bdd7c..d06b6da5c1e 100644 --- a/include/trace/events/xen.h +++ b/include/trace/events/xen.h @@ -377,6 +377,14 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd,  DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin);  DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); +TRACE_EVENT(xen_mmu_flush_tlb_all, +	    TP_PROTO(int x), +	    TP_ARGS(x), +	    TP_STRUCT__entry(__array(char, x, 0)), +	    TP_fast_assign((void)x), +	    TP_printk("%s", "") +	); +  TRACE_EVENT(xen_mmu_flush_tlb,  	    TP_PROTO(int x),  	    TP_ARGS(x), diff --git a/include/uapi/linux/eventpoll.h b/include/uapi/linux/eventpoll.h index 8c99ce7202c..2c267bcbb85 100644 --- a/include/uapi/linux/eventpoll.h +++ b/include/uapi/linux/eventpoll.h @@ -25,7 +25,6 @@  #define EPOLL_CTL_ADD 1  #define EPOLL_CTL_DEL 2  #define EPOLL_CTL_MOD 3 -#define EPOLL_CTL_DISABLE 4  /*   * Request the handling of system wakeup events so as to prevent system suspends diff --git a/include/uapi/linux/raid/Kbuild b/include/uapi/linux/raid/Kbuild index aafaa5aa54d..e2c3d25405d 100644 --- a/include/uapi/linux/raid/Kbuild +++ b/include/uapi/linux/raid/Kbuild @@ -1 +1,3 @@  # UAPI Header export list +header-y += md_p.h +header-y += md_u.h diff --git a/include/linux/raid/md_p.h b/include/uapi/linux/raid/md_p.h index ee753536ab7..ee753536ab7 100644 --- a/include/linux/raid/md_p.h +++ b/include/uapi/linux/raid/md_p.h diff --git a/include/uapi/linux/raid/md_u.h b/include/uapi/linux/raid/md_u.h new file mode 100644 index 00000000000..4133e744e4e --- /dev/null +++ b/include/uapi/linux/raid/md_u.h @@ -0,0 +1,155 @@ +/* +   md_u.h : user <=> kernel API between Linux raidtools and RAID drivers +          Copyright (C) 1998 Ingo Molnar +	   +   This program is free software; you can redistribute it and/or modify +   it under the terms of the GNU General Public License as published by +   the Free Software Foundation; either version 2, or (at your option) +   any later version. +    +   You should have received a copy of the GNU General Public License +   (for example /usr/src/linux/COPYING); if not, write to the Free +   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   +*/ + +#ifndef _UAPI_MD_U_H +#define _UAPI_MD_U_H + +/* + * Different major versions are not compatible. + * Different minor versions are only downward compatible. + * Different patchlevel versions are downward and upward compatible. + */ +#define MD_MAJOR_VERSION                0 +#define MD_MINOR_VERSION                90 +/* + * MD_PATCHLEVEL_VERSION indicates kernel functionality. + * >=1 means different superblock formats are selectable using SET_ARRAY_INFO + *     and major_version/minor_version accordingly + * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT + *     in the super status byte + * >=3 means that bitmap superblock version 4 is supported, which uses + *     little-ending representation rather than host-endian + */ +#define MD_PATCHLEVEL_VERSION           3 + +/* ioctls */ + +/* status */ +#define RAID_VERSION		_IOR (MD_MAJOR, 0x10, mdu_version_t) +#define GET_ARRAY_INFO		_IOR (MD_MAJOR, 0x11, mdu_array_info_t) +#define GET_DISK_INFO		_IOR (MD_MAJOR, 0x12, mdu_disk_info_t) +#define PRINT_RAID_DEBUG	_IO (MD_MAJOR, 0x13) +#define RAID_AUTORUN		_IO (MD_MAJOR, 0x14) +#define GET_BITMAP_FILE		_IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t) + +/* configuration */ +#define CLEAR_ARRAY		_IO (MD_MAJOR, 0x20) +#define ADD_NEW_DISK		_IOW (MD_MAJOR, 0x21, mdu_disk_info_t) +#define HOT_REMOVE_DISK		_IO (MD_MAJOR, 0x22) +#define SET_ARRAY_INFO		_IOW (MD_MAJOR, 0x23, mdu_array_info_t) +#define SET_DISK_INFO		_IO (MD_MAJOR, 0x24) +#define WRITE_RAID_INFO		_IO (MD_MAJOR, 0x25) +#define UNPROTECT_ARRAY		_IO (MD_MAJOR, 0x26) +#define PROTECT_ARRAY		_IO (MD_MAJOR, 0x27) +#define HOT_ADD_DISK		_IO (MD_MAJOR, 0x28) +#define SET_DISK_FAULTY		_IO (MD_MAJOR, 0x29) +#define HOT_GENERATE_ERROR	_IO (MD_MAJOR, 0x2a) +#define SET_BITMAP_FILE		_IOW (MD_MAJOR, 0x2b, int) + +/* usage */ +#define RUN_ARRAY		_IOW (MD_MAJOR, 0x30, mdu_param_t) +/*  0x31 was START_ARRAY  */ +#define STOP_ARRAY		_IO (MD_MAJOR, 0x32) +#define STOP_ARRAY_RO		_IO (MD_MAJOR, 0x33) +#define RESTART_ARRAY_RW	_IO (MD_MAJOR, 0x34) + +/* 63 partitions with the alternate major number (mdp) */ +#define MdpMinorShift 6 + +typedef struct mdu_version_s { +	int major; +	int minor; +	int patchlevel; +} mdu_version_t; + +typedef struct mdu_array_info_s { +	/* +	 * Generic constant information +	 */ +	int major_version; +	int minor_version; +	int patch_version; +	int ctime; +	int level; +	int size; +	int nr_disks; +	int raid_disks; +	int md_minor; +	int not_persistent; + +	/* +	 * Generic state information +	 */ +	int utime;		/*  0 Superblock update time		      */ +	int state;		/*  1 State bits (clean, ...)		      */ +	int active_disks;	/*  2 Number of currently active disks	      */ +	int working_disks;	/*  3 Number of working disks		      */ +	int failed_disks;	/*  4 Number of failed disks		      */ +	int spare_disks;	/*  5 Number of spare disks		      */ + +	/* +	 * Personality information +	 */ +	int layout;		/*  0 the array's physical layout	      */ +	int chunk_size;	/*  1 chunk size in bytes		      */ + +} mdu_array_info_t; + +/* non-obvious values for 'level' */ +#define	LEVEL_MULTIPATH		(-4) +#define	LEVEL_LINEAR		(-1) +#define	LEVEL_FAULTY		(-5) + +/* we need a value for 'no level specified' and 0 + * means 'raid0', so we need something else.  This is + * for internal use only + */ +#define	LEVEL_NONE		(-1000000) + +typedef struct mdu_disk_info_s { +	/* +	 * configuration/status of one particular disk +	 */ +	int number; +	int major; +	int minor; +	int raid_disk; +	int state; + +} mdu_disk_info_t; + +typedef struct mdu_start_info_s { +	/* +	 * configuration/status of one particular disk +	 */ +	int major; +	int minor; +	int raid_disk; +	int state; + +} mdu_start_info_t; + +typedef struct mdu_bitmap_file_s +{ +	char pathname[4096]; +} mdu_bitmap_file_t; + +typedef struct mdu_param_s +{ +	int			personality;	/* 1,2,3,4 */ +	int			chunk_size;	/* in bytes */ +	int			max_fault;	/* unused for now */ +} mdu_param_t; + +#endif /* _UAPI_MD_U_H */ diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h index c4b89a5cb7d..e962faa5ab0 100644 --- a/include/uapi/linux/tcp.h +++ b/include/uapi/linux/tcp.h @@ -130,6 +130,7 @@ enum {  #define TCPI_OPT_WSCALE		4  #define TCPI_OPT_ECN		8 /* ECN was negociated at TCP session init */  #define TCPI_OPT_ECN_SEEN	16 /* we received at least one packet with ECT */ +#define TCPI_OPT_SYN_DATA	32 /* SYN-ACK acked data in SYN sent or rcvd */  enum tcp_ca_state {  	TCP_CA_Open = 0, diff --git a/include/xen/hvm.h b/include/xen/hvm.h index b193fa2f9fd..13e43e41637 100644 --- a/include/xen/hvm.h +++ b/include/xen/hvm.h @@ -5,6 +5,36 @@  #include <xen/interface/hvm/params.h>  #include <asm/xen/hypercall.h> +static const char *param_name(int op) +{ +#define PARAM(x) [HVM_PARAM_##x] = #x +	static const char *const names[] = { +		PARAM(CALLBACK_IRQ), +		PARAM(STORE_PFN), +		PARAM(STORE_EVTCHN), +		PARAM(PAE_ENABLED), +		PARAM(IOREQ_PFN), +		PARAM(BUFIOREQ_PFN), +		PARAM(TIMER_MODE), +		PARAM(HPET_ENABLED), +		PARAM(IDENT_PT), +		PARAM(DM_DOMAIN), +		PARAM(ACPI_S_STATE), +		PARAM(VM86_TSS), +		PARAM(VPT_ALIGN), +		PARAM(CONSOLE_PFN), +		PARAM(CONSOLE_EVTCHN), +	}; +#undef PARAM + +	if (op >= ARRAY_SIZE(names)) +		return "unknown"; + +	if (!names[op]) +		return "reserved"; + +	return names[op]; +}  static inline int hvm_get_parameter(int idx, uint64_t *value)  {  	struct xen_hvm_param xhv; @@ -14,8 +44,8 @@ static inline int hvm_get_parameter(int idx, uint64_t *value)  	xhv.index = idx;  	r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);  	if (r < 0) { -		printk(KERN_ERR "Cannot get hvm parameter %d: %d!\n", -			idx, r); +		printk(KERN_ERR "Cannot get hvm parameter %s (%d): %d!\n", +			param_name(idx), idx, r);  		return r;  	}  	*value = xhv.value; diff --git a/init/main.c b/init/main.c index 9cf77ab138a..e33e09df3cb 100644 --- a/init/main.c +++ b/init/main.c @@ -442,9 +442,11 @@ void __init __weak smp_setup_processor_id(void)  {  } +# if THREAD_SIZE >= PAGE_SIZE  void __init __weak thread_info_cache_init(void)  {  } +#endif  /*   * Set up kernel memory allocators diff --git a/kernel/Makefile b/kernel/Makefile index 0dfeca4324e..86e3285ae7e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -174,10 +174,8 @@ signing_key.priv signing_key.x509: x509.genkey  	@echo "###"  	@echo "### If this takes a long time, you might wish to run rngd in the"  	@echo "### background to keep the supply of entropy topped up.  It" -	@echo "### needs to be run as root, and should use a hardware random" -	@echo "### number generator if one is available, eg:" -	@echo "###" -	@echo "###     rngd -r /dev/hwrandom" +	@echo "### needs to be run as root, and uses a hardware random" +	@echo "### number generator if one is available."  	@echo "###"  	openssl req -new -nodes -utf8 $(sign_key_with_hash) -days 36500 -batch \  		-x509 -config x509.genkey \ diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 13774b3b39a..f24f724620d 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1962,9 +1962,8 @@ static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp,  	 * trading it for newcg is protected by cgroup_mutex, we're safe to drop  	 * it here; it will be freed under RCU.  	 */ -	put_css_set(oldcg); -  	set_bit(CGRP_RELEASABLE, &oldcgrp->flags); +	put_css_set(oldcg);  }  /** @@ -4815,31 +4814,20 @@ static const struct file_operations proc_cgroupstats_operations = {   *   * A pointer to the shared css_set was automatically copied in   * fork.c by dup_task_struct().  However, we ignore that copy, since - * it was not made under the protection of RCU, cgroup_mutex or - * threadgroup_change_begin(), so it might no longer be a valid - * cgroup pointer.  cgroup_attach_task() might have already changed - * current->cgroups, allowing the previously referenced cgroup - * group to be removed and freed. - * - * Outside the pointer validity we also need to process the css_set - * inheritance between threadgoup_change_begin() and - * threadgoup_change_end(), this way there is no leak in any process - * wide migration performed by cgroup_attach_proc() that could otherwise - * miss a thread because it is too early or too late in the fork stage. + * it was not made under the protection of RCU or cgroup_mutex, so + * might no longer be a valid cgroup pointer.  cgroup_attach_task() might + * have already changed current->cgroups, allowing the previously + * referenced cgroup group to be removed and freed.   *   * At the point that cgroup_fork() is called, 'current' is the parent   * task, and the passed argument 'child' points to the child task.   */  void cgroup_fork(struct task_struct *child)  { -	/* -	 * We don't need to task_lock() current because current->cgroups -	 * can't be changed concurrently here. The parent obviously hasn't -	 * exited and called cgroup_exit(), and we are synchronized against -	 * cgroup migration through threadgroup_change_begin(). -	 */ +	task_lock(current);  	child->cgroups = current->cgroups;  	get_css_set(child->cgroups); +	task_unlock(current);  	INIT_LIST_HEAD(&child->cg_list);  } @@ -4895,19 +4883,10 @@ void cgroup_post_fork(struct task_struct *child)  	 */  	if (use_task_css_set_links) {  		write_lock(&css_set_lock); -		if (list_empty(&child->cg_list)) { -			/* -			 * It's safe to use child->cgroups without task_lock() -			 * here because we are protected through -			 * threadgroup_change_begin() against concurrent -			 * css_set change in cgroup_task_migrate(). Also -			 * the task can't exit at that point until -			 * wake_up_new_task() is called, so we are protected -			 * against cgroup_exit() setting child->cgroup to -			 * init_css_set. -			 */ +		task_lock(child); +		if (list_empty(&child->cg_list))  			list_add(&child->cg_list, &child->cgroups->tasks); -		} +		task_unlock(child);  		write_unlock(&css_set_lock);  	}  } diff --git a/kernel/module.c b/kernel/module.c index 6085f5ef88e..6e48c3a4359 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2293,12 +2293,17 @@ static void layout_symtab(struct module *mod, struct load_info *info)  	src = (void *)info->hdr + symsect->sh_offset;  	nsrc = symsect->sh_size / sizeof(*src); +	/* strtab always starts with a nul, so offset 0 is the empty string. */ +	strtab_size = 1; +  	/* Compute total space required for the core symbols' strtab. */ -	for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src) -		if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) { -			strtab_size += strlen(&info->strtab[src->st_name]) + 1; +	for (ndst = i = 0; i < nsrc; i++) { +		if (i == 0 || +		    is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { +			strtab_size += strlen(&info->strtab[src[i].st_name])+1;  			ndst++;  		} +	}  	/* Append room for core symbols at end of core part. */  	info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); @@ -2332,15 +2337,15 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)  	mod->core_symtab = dst = mod->module_core + info->symoffs;  	mod->core_strtab = s = mod->module_core + info->stroffs;  	src = mod->symtab; -	*dst = *src;  	*s++ = 0; -	for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { -		if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) -			continue; - -		dst[ndst] = *src; -		dst[ndst++].st_name = s - mod->core_strtab; -		s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1; +	for (ndst = i = 0; i < mod->num_symtab; i++) { +		if (i == 0 || +		    is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { +			dst[ndst] = src[i]; +			dst[ndst++].st_name = s - mod->core_strtab; +			s += strlcpy(s, &mod->strtab[src[i].st_name], +				     KSYM_NAME_LEN) + 1; +		}  	}  	mod->core_num_syms = ndst;  } diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index eb00be20581..7b07cc0dfb7 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -71,12 +71,22 @@ err_alloc:  	return NULL;  } +/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */ +#define MAX_PID_NS_LEVEL 32 +  static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns)  {  	struct pid_namespace *ns;  	unsigned int level = parent_pid_ns->level + 1; -	int i, err = -ENOMEM; +	int i; +	int err; + +	if (level > MAX_PID_NS_LEVEL) { +		err = -EINVAL; +		goto out; +	} +	err = -ENOMEM;  	ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL);  	if (ns == NULL)  		goto out; diff --git a/kernel/workqueue.c b/kernel/workqueue.c index d951daa0ca9..042d221d33c 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -2982,7 +2982,7 @@ bool cancel_delayed_work(struct delayed_work *dwork)  	set_work_cpu_and_clear_pending(&dwork->work, work_cpu(&dwork->work));  	local_irq_restore(flags); -	return true; +	return ret;  }  EXPORT_SYMBOL(cancel_delayed_work); diff --git a/lib/genalloc.c b/lib/genalloc.c index ca208a92628..54920433705 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -178,7 +178,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy  	struct gen_pool_chunk *chunk;  	int nbits = size >> pool->min_alloc_order;  	int nbytes = sizeof(struct gen_pool_chunk) + -				(nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE; +				BITS_TO_LONGS(nbits) * sizeof(long);  	chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid);  	if (unlikely(chunk == NULL)) diff --git a/mm/memblock.c b/mm/memblock.c index 931eef145af..625905523c2 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -930,6 +930,30 @@ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t si  	return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;  } +void __init_memblock memblock_trim_memory(phys_addr_t align) +{ +	int i; +	phys_addr_t start, end, orig_start, orig_end; +	struct memblock_type *mem = &memblock.memory; + +	for (i = 0; i < mem->cnt; i++) { +		orig_start = mem->regions[i].base; +		orig_end = mem->regions[i].base + mem->regions[i].size; +		start = round_up(orig_start, align); +		end = round_down(orig_end, align); + +		if (start == orig_start && end == orig_end) +			continue; + +		if (start < end) { +			mem->regions[i].base = start; +			mem->regions[i].size = end - start; +		} else { +			memblock_remove_region(mem, i); +			i--; +		} +	} +}  void __init_memblock memblock_set_current_limit(phys_addr_t limit)  { diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c index 479a1e751a7..8a5ac8c686b 100644 --- a/mm/mmu_notifier.c +++ b/mm/mmu_notifier.c @@ -196,28 +196,28 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,  	BUG_ON(atomic_read(&mm->mm_users) <= 0);  	/* -	* Verify that mmu_notifier_init() already run and the global srcu is -	* initialized. -	*/ +	 * Verify that mmu_notifier_init() already run and the global srcu is +	 * initialized. +	 */  	BUG_ON(!srcu.per_cpu_ref); +	ret = -ENOMEM; +	mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), GFP_KERNEL); +	if (unlikely(!mmu_notifier_mm)) +		goto out; +  	if (take_mmap_sem)  		down_write(&mm->mmap_sem);  	ret = mm_take_all_locks(mm);  	if (unlikely(ret)) -		goto out; +		goto out_clean;  	if (!mm_has_notifiers(mm)) { -		mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), -					GFP_KERNEL); -		if (unlikely(!mmu_notifier_mm)) { -			ret = -ENOMEM; -			goto out_of_mem; -		}  		INIT_HLIST_HEAD(&mmu_notifier_mm->list);  		spin_lock_init(&mmu_notifier_mm->lock);  		mm->mmu_notifier_mm = mmu_notifier_mm; +		mmu_notifier_mm = NULL;  	}  	atomic_inc(&mm->mm_count); @@ -233,12 +233,12 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,  	hlist_add_head(&mn->hlist, &mm->mmu_notifier_mm->list);  	spin_unlock(&mm->mmu_notifier_mm->lock); -out_of_mem:  	mm_drop_all_locks(mm); -out: +out_clean:  	if (take_mmap_sem)  		up_write(&mm->mmap_sem); - +	kfree(mmu_notifier_mm); +out:  	BUG_ON(atomic_read(&mm->mm_users) <= 0);  	return ret;  } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index bb90971182b..5b74de6702e 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1809,10 +1809,10 @@ static void __paginginit init_zone_allows_reclaim(int nid)  	int i;  	for_each_online_node(i) -		if (node_distance(nid, i) <= RECLAIM_DISTANCE) { +		if (node_distance(nid, i) <= RECLAIM_DISTANCE)  			node_set(i, NODE_DATA(nid)->reclaim_nodes); +		else  			zone_reclaim_mode = 1; -		}  }  #else	/* CONFIG_NUMA */ @@ -5825,7 +5825,7 @@ int alloc_contig_range(unsigned long start, unsigned long end,  	ret = start_isolate_page_range(pfn_max_align_down(start),  				       pfn_max_align_up(end), migratetype);  	if (ret) -		goto done; +		return ret;  	ret = __alloc_contig_migrate_range(&cc, start, end);  	if (ret) diff --git a/mm/rmap.c b/mm/rmap.c index 7df7984d476..2ee1ef0f317 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -56,6 +56,7 @@  #include <linux/mmu_notifier.h>  #include <linux/migrate.h>  #include <linux/hugetlb.h> +#include <linux/backing-dev.h>  #include <asm/tlbflush.h> @@ -926,11 +927,8 @@ int page_mkclean(struct page *page)  	if (page_mapped(page)) {  		struct address_space *mapping = page_mapping(page); -		if (mapping) { +		if (mapping)  			ret = page_mkclean_file(mapping, page); -			if (page_test_and_clear_dirty(page_to_pfn(page), 1)) -				ret = 1; -		}  	}  	return ret; @@ -1116,6 +1114,7 @@ void page_add_file_rmap(struct page *page)   */  void page_remove_rmap(struct page *page)  { +	struct address_space *mapping = page_mapping(page);  	bool anon = PageAnon(page);  	bool locked;  	unsigned long flags; @@ -1138,8 +1137,19 @@ void page_remove_rmap(struct page *page)  	 * this if the page is anon, so about to be freed; but perhaps  	 * not if it's in swapcache - there might be another pte slot  	 * containing the swap entry, but page not yet written to swap. +	 * +	 * And we can skip it on file pages, so long as the filesystem +	 * participates in dirty tracking; but need to catch shm and tmpfs +	 * and ramfs pages which have been modified since creation by read +	 * fault. +	 * +	 * Note that mapping must be decided above, before decrementing +	 * mapcount (which luckily provides a barrier): once page is unmapped, +	 * it could be truncated and page->mapping reset to NULL at any moment. +	 * Note also that we are relying on page_mapping(page) to set mapping +	 * to &swapper_space when PageSwapCache(page).  	 */ -	if ((!anon || PageSwapCache(page)) && +	if (mapping && !mapping_cap_account_dirty(mapping) &&  	    page_test_and_clear_dirty(page_to_pfn(page), 1))  		set_page_dirty(page);  	/* diff --git a/mm/vmscan.c b/mm/vmscan.c index 2624edcfb42..8b055e9379b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -3017,6 +3017,8 @@ static int kswapd(void *p)  						&balanced_classzone_idx);  		}  	} + +	current->reclaim_state = NULL;  	return 0;  } diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 9096bcb0813..ee070722a3a 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -463,7 +463,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,  	case NETDEV_PRE_TYPE_CHANGE:  		/* Forbid underlaying device to change its type. */ -		return NOTIFY_BAD; +		if (vlan_uses_dev(dev)) +			return NOTIFY_BAD; +		break;  	case NETDEV_NOTIFY_PEERS:  	case NETDEV_BONDING_FAILOVER: diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 0a9084ad19a..fd8d5afec0d 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -1167,6 +1167,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv)  	uint16_t crc;  	unsigned long entrytime; +	spin_lock_init(&bat_priv->bla.bcast_duplist_lock); +  	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");  	/* setting claim destination address */ @@ -1210,8 +1212,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv)  /**   * batadv_bla_check_bcast_duplist   * @bat_priv: the bat priv with all the soft interface information - * @bcast_packet: originator mac address - * @hdr_size: maximum length of the frame + * @bcast_packet: encapsulated broadcast frame plus batman header + * @bcast_packet_len: length of encapsulated broadcast frame plus batman header   *   * check if it is on our broadcast list. Another gateway might   * have sent the same packet because it is connected to the same backbone, @@ -1224,20 +1226,22 @@ int batadv_bla_init(struct batadv_priv *bat_priv)   */  int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,  				   struct batadv_bcast_packet *bcast_packet, -				   int hdr_size) +				   int bcast_packet_len)  { -	int i, length, curr; +	int i, length, curr, ret = 0;  	uint8_t *content;  	uint16_t crc;  	struct batadv_bcast_duplist_entry *entry; -	length = hdr_size - sizeof(*bcast_packet); +	length = bcast_packet_len - sizeof(*bcast_packet);  	content = (uint8_t *)bcast_packet;  	content += sizeof(*bcast_packet);  	/* calculate the crc ... */  	crc = crc16(0, content, length); +	spin_lock_bh(&bat_priv->bla.bcast_duplist_lock); +  	for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {  		curr = (bat_priv->bla.bcast_duplist_curr + i);  		curr %= BATADV_DUPLIST_SIZE; @@ -1259,9 +1263,12 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,  		/* this entry seems to match: same crc, not too old,  		 * and from another gw. therefore return 1 to forbid it.  		 */ -		return 1; +		ret = 1; +		goto out;  	} -	/* not found, add a new entry (overwrite the oldest entry) */ +	/* not found, add a new entry (overwrite the oldest entry) +	 * and allow it, its the first occurence. +	 */  	curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);  	curr %= BATADV_DUPLIST_SIZE;  	entry = &bat_priv->bla.bcast_duplist[curr]; @@ -1270,8 +1277,10 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,  	memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);  	bat_priv->bla.bcast_duplist_curr = curr; -	/* allow it, its the first occurence. */ -	return 0; +out: +	spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock); + +	return ret;  } diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 939fc01371d..376b4cc6ca8 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1124,8 +1124,14 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,  	spin_unlock_bh(&orig_node->bcast_seqno_lock); +	/* keep skb linear for crc calculation */ +	if (skb_linearize(skb) < 0) +		goto out; + +	bcast_packet = (struct batadv_bcast_packet *)skb->data; +  	/* check whether this has been sent by another originator before */ -	if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size)) +	if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len))  		goto out;  	/* rebroadcast packet */ diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 2ed82caacdc..ac1e07a8045 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -205,6 +205,8 @@ struct batadv_priv_bla {  	struct batadv_hashtable *backbone_hash;  	struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];  	int bcast_duplist_curr; +	/* protects bcast_duplist and bcast_duplist_curr */ +	spinlock_t bcast_duplist_lock;  	struct batadv_bla_claim_dst claim_dest;  	struct delayed_work work;  }; diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 8c225ef349c..2ac8d50861e 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -32,6 +32,8 @@  #define SMP_TIMEOUT	msecs_to_jiffies(30000) +#define AUTH_REQ_MASK   0x07 +  static inline void swap128(u8 src[16], u8 dst[16])  {  	int i; @@ -230,7 +232,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,  		req->max_key_size = SMP_MAX_ENC_KEY_SIZE;  		req->init_key_dist = 0;  		req->resp_key_dist = dist_keys; -		req->auth_req = authreq; +		req->auth_req = (authreq & AUTH_REQ_MASK);  		return;  	} @@ -239,7 +241,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,  	rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;  	rsp->init_key_dist = 0;  	rsp->resp_key_dist = req->resp_key_dist & dist_keys; -	rsp->auth_req = authreq; +	rsp->auth_req = (authreq & AUTH_REQ_MASK);  }  static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 159aa8bef9e..3ef1759403b 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2300,10 +2300,11 @@ restart:  			mutex_unlock(&con->mutex);  			return;  		} else { -			con->ops->put(con);  			dout("con_work %p FAILED to back off %lu\n", con,  			     con->delay); +			set_bit(CON_FLAG_BACKOFF, &con->flags);  		} +		goto done;  	}  	if (con->state == CON_STATE_STANDBY) { @@ -2749,7 +2750,8 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip)  		msg = con->ops->alloc_msg(con, hdr, skip);  		mutex_lock(&con->mutex);  		if (con->state != CON_STATE_OPEN) { -			ceph_msg_put(msg); +			if (msg) +				ceph_msg_put(msg);  			return -EAGAIN;  		}  		con->in_msg = msg; diff --git a/net/core/dev.c b/net/core/dev.c index 09cb3f6dc40..bda6d004f9f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1666,7 +1666,7 @@ static inline int deliver_skb(struct sk_buff *skb,  static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb)  { -	if (ptype->af_packet_priv == NULL) +	if (!ptype->af_packet_priv || !skb->sk)  		return false;  	if (ptype->id_match) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 76d4c2c3c89..fad649ae4de 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -2192,7 +2192,8 @@ static int nlmsg_populate_fdb(struct sk_buff *skb,  			goto skip;  		err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, -					      portid, seq, 0, NTF_SELF); +					      portid, seq, +					      RTM_NEWNEIGH, NTF_SELF);  		if (err < 0)  			return err;  skip: diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 6e04b1fa11f..4007c1437fd 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3379,10 +3379,12 @@ EXPORT_SYMBOL(__skb_warn_lro_forwarding);  void kfree_skb_partial(struct sk_buff *skb, bool head_stolen)  { -	if (head_stolen) +	if (head_stolen) { +		skb_release_head_state(skb);  		kmem_cache_free(skbuff_head_cache, skb); -	else +	} else {  		__kfree_skb(skb); +	}  }  EXPORT_SYMBOL(kfree_skb_partial); diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 535584c00f9..0c34bfabc11 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -892,13 +892,16 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,  		struct inet_diag_req_v2 *r, struct nlattr *bc)  {  	const struct inet_diag_handler *handler; +	int err = 0;  	handler = inet_diag_lock_handler(r->sdiag_protocol);  	if (!IS_ERR(handler))  		handler->dump(skb, cb, r, bc); +	else +		err = PTR_ERR(handler);  	inet_diag_unlock_handler(handler); -	return skb->len; +	return err ? : skb->len;  }  static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c index 9e0ffaf1d94..a82047282db 100644 --- a/net/ipv4/netfilter/iptable_nat.c +++ b/net/ipv4/netfilter/iptable_nat.c @@ -184,7 +184,8 @@ nf_nat_ipv4_out(unsigned int hooknum,  		if ((ct->tuplehash[dir].tuple.src.u3.ip !=  		     ct->tuplehash[!dir].tuple.dst.u3.ip) || -		    (ct->tuplehash[dir].tuple.src.u.all != +		    (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && +		     ct->tuplehash[dir].tuple.src.u.all !=  		     ct->tuplehash[!dir].tuple.dst.u.all))  			if (nf_xfrm_me_harder(skb, AF_INET) < 0)  				ret = NF_DROP; @@ -221,6 +222,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,  		}  #ifdef CONFIG_XFRM  		else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && +			 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&  			 ct->tuplehash[dir].tuple.dst.u.all !=  			 ct->tuplehash[!dir].tuple.src.u.all)  			if (nf_xfrm_me_harder(skb, AF_INET) < 0) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 432f4bb7723..a8c651216fa 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1163,8 +1163,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,  	spin_lock_bh(&fnhe_lock);  	if (daddr == fnhe->fnhe_daddr) { -		struct rtable *orig; - +		struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); +		if (orig && rt_is_expired(orig)) { +			fnhe->fnhe_gw = 0; +			fnhe->fnhe_pmtu = 0; +			fnhe->fnhe_expires = 0; +		}  		if (fnhe->fnhe_pmtu) {  			unsigned long expires = fnhe->fnhe_expires;  			unsigned long diff = expires - jiffies; @@ -1181,7 +1185,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,  		} else if (!rt->rt_gateway)  			rt->rt_gateway = daddr; -		orig = rcu_dereference(fnhe->fnhe_rth);  		rcu_assign_pointer(fnhe->fnhe_rth, rt);  		if (orig)  			rt_free(orig); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f32c02e2a54..197c0008503 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -549,14 +549,12 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)  			 !tp->urg_data ||  			 before(tp->urg_seq, tp->copied_seq) ||  			 !before(tp->urg_seq, tp->rcv_nxt)) { -			struct sk_buff *skb;  			answ = tp->rcv_nxt - tp->copied_seq; -			/* Subtract 1, if FIN is in queue. */ -			skb = skb_peek_tail(&sk->sk_receive_queue); -			if (answ && skb) -				answ -= tcp_hdr(skb)->fin; +			/* Subtract 1, if FIN was received */ +			if (answ && sock_flag(sk, SOCK_DONE)) +				answ--;  		} else  			answ = tp->urg_seq - tp->copied_seq;  		release_sock(sk); @@ -2766,6 +2764,8 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info)  		info->tcpi_options |= TCPI_OPT_ECN;  	if (tp->ecn_flags & TCP_ECN_SEEN)  		info->tcpi_options |= TCPI_OPT_ECN_SEEN; +	if (tp->syn_data_acked) +		info->tcpi_options |= TCPI_OPT_SYN_DATA;  	info->tcpi_rto = jiffies_to_usecs(icsk->icsk_rto);  	info->tcpi_ato = jiffies_to_usecs(icsk->icsk_ack.ato); diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index 813b43a76fe..834857f3c87 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c @@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext,  			.tcpv_rttcnt = ca->cnt_rtt,  			.tcpv_minrtt = ca->base_rtt,  		}; -		u64 t = ca->sum_rtt; -		do_div(t, ca->cnt_rtt); -		info.tcpv_rtt = t; +		if (info.tcpv_rttcnt > 0) { +			u64 t = ca->sum_rtt; +			do_div(t, info.tcpv_rttcnt); +			info.tcpv_rtt = t; +		}  		nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);  	}  } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 432c36649db..2c2b13a999e 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4529,6 +4529,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size)  	struct tcphdr *th;  	bool fragstolen; +	if (size == 0) +		return 0; +  	skb = alloc_skb(size + sizeof(*th), sk->sk_allocation);  	if (!skb)  		goto err; @@ -5646,6 +5649,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,  		tcp_rearm_rto(sk);  		return true;  	} +	tp->syn_data_acked = tp->syn_data;  	return false;  } @@ -5963,7 +5967,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,  	req = tp->fastopen_rsk;  	if (req != NULL) { -		BUG_ON(sk->sk_state != TCP_SYN_RECV && +		WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&  		    sk->sk_state != TCP_FIN_WAIT1);  		if (tcp_check_req(sk, skb, req, NULL, true) == NULL) @@ -6052,7 +6056,15 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,  			 * ACK we have received, this would have acknowledged  			 * our SYNACK so stop the SYNACK timer.  			 */ -			if (acceptable && req != NULL) { +			if (req != NULL) { +				/* Return RST if ack_seq is invalid. +				 * Note that RFC793 only says to generate a +				 * DUPACK for it but for TCP Fast Open it seems +				 * better to treat this case like TCP_SYN_RECV +				 * above. +				 */ +				if (!acceptable) +					return 1;  				/* We no longer need the request sock. */  				reqsk_fastopen_remove(sk, req, false);  				tcp_rearm_rto(sk); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ef998b008a5..0c4a6435560 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1461,6 +1461,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk,  		skb_set_owner_r(skb, child);  		__skb_queue_tail(&child->sk_receive_queue, skb);  		tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; +		tp->syn_data_acked = 1;  	}  	sk->sk_data_ready(sk, 0);  	bh_unlock_sock(child); diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 4c752a6e0bc..53bc5847bfa 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -864,7 +864,7 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,  	}  	a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6];  	if (a) { -		if (nla_len(a) != sizeof(sizeof(struct in6_addr))) +		if (nla_len(a) != sizeof(struct in6_addr))  			return -EINVAL;  		addr->family = AF_INET6;  		memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6)); diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 27536ba16c9..a7302d974f3 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -510,6 +510,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,  		newtp->rx_opt.mss_clamp = req->mss;  		TCP_ECN_openreq_child(newtp, req);  		newtp->fastopen_rsk = NULL; +		newtp->syn_data_acked = 0;  		TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS);  	} diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index fc04711e80c..d47c1b4421a 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -347,8 +347,8 @@ void tcp_retransmit_timer(struct sock *sk)  		return;  	}  	if (tp->fastopen_rsk) { -		BUG_ON(sk->sk_state != TCP_SYN_RECV && -		    sk->sk_state != TCP_FIN_WAIT1); +		WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV && +			     sk->sk_state != TCP_FIN_WAIT1);  		tcp_fastopen_synack_timer(sk);  		/* Before we receive ACK to our SYN-ACK don't retransmit  		 * anything else (e.g., data or FIN segments). diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 0185679c5f5..d5cb3c4e66f 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -1633,9 +1633,9 @@ static size_t ip6gre_get_size(const struct net_device *dev)  		/* IFLA_GRE_OKEY */  		nla_total_size(4) +  		/* IFLA_GRE_LOCAL */ -		nla_total_size(4) + +		nla_total_size(sizeof(struct in6_addr)) +  		/* IFLA_GRE_REMOTE */ -		nla_total_size(4) + +		nla_total_size(sizeof(struct in6_addr)) +  		/* IFLA_GRE_TTL */  		nla_total_size(1) +  		/* IFLA_GRE_TOS */ @@ -1659,8 +1659,8 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)  	    nla_put_be16(skb, IFLA_GRE_OFLAGS, p->o_flags) ||  	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||  	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || -	    nla_put(skb, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &p->raddr) || -	    nla_put(skb, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &p->laddr) || +	    nla_put(skb, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &p->laddr) || +	    nla_put(skb, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &p->raddr) ||  	    nla_put_u8(skb, IFLA_GRE_TTL, p->hop_limit) ||  	    /*nla_put_u8(skb, IFLA_GRE_TOS, t->priority) ||*/  	    nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) || diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index ff36194a71a..2edce30ef73 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -535,7 +535,7 @@ static void ndisc_send_unsol_na(struct net_device *dev)  {  	struct inet6_dev *idev;  	struct inet6_ifaddr *ifa; -	struct in6_addr mcaddr; +	struct in6_addr mcaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT;  	idev = in6_dev_get(dev);  	if (!idev) @@ -543,7 +543,6 @@ static void ndisc_send_unsol_na(struct net_device *dev)  	read_lock_bh(&idev->lock);  	list_for_each_entry(ifa, &idev->addr_list, if_list) { -		addrconf_addr_solict_mult(&ifa->addr, &mcaddr);  		ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr,  			      /*router=*/ !!idev->cnf.forwarding,  			      /*solicited=*/ false, /*override=*/ true, diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c index e418bd6350a..d57dab17a18 100644 --- a/net/ipv6/netfilter/ip6table_nat.c +++ b/net/ipv6/netfilter/ip6table_nat.c @@ -186,7 +186,8 @@ nf_nat_ipv6_out(unsigned int hooknum,  		if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,  				      &ct->tuplehash[!dir].tuple.dst.u3) || -		    (ct->tuplehash[dir].tuple.src.u.all != +		    (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && +		     ct->tuplehash[dir].tuple.src.u.all !=  		     ct->tuplehash[!dir].tuple.dst.u.all))  			if (nf_xfrm_me_harder(skb, AF_INET6) < 0)  				ret = NF_DROP; @@ -222,6 +223,7 @@ nf_nat_ipv6_local_fn(unsigned int hooknum,  		}  #ifdef CONFIG_XFRM  		else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && +			 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&  			 ct->tuplehash[dir].tuple.dst.u.all !=  			 ct->tuplehash[!dir].tuple.src.u.all)  			if (nf_xfrm_me_harder(skb, AF_INET6)) diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 18bd9bbbd1c..22c8ea95118 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -85,7 +85,7 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {  	{ }  }; -static int __net_init nf_ct_frag6_sysctl_register(struct net *net) +static int nf_ct_frag6_sysctl_register(struct net *net)  {  	struct ctl_table *table;  	struct ctl_table_header *hdr; @@ -127,7 +127,7 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)  }  #else -static int __net_init nf_ct_frag6_sysctl_register(struct net *net) +static int nf_ct_frag6_sysctl_register(struct net *net)  {  	return 0;  } diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7c7e963260e..b1e6cf0b95f 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -219,7 +219,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {  };  static const u32 ip6_template_metrics[RTAX_MAX] = { -	[RTAX_HOPLIMIT - 1] = 255, +	[RTAX_HOPLIMIT - 1] = 0,  };  static const struct rt6_info ip6_null_entry_template = { @@ -1232,7 +1232,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,  	rt->rt6i_dst.addr = fl6->daddr;  	rt->rt6i_dst.plen = 128;  	rt->rt6i_idev     = idev; -	dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); +	dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0);  	spin_lock_bh(&icmp6_dst_lock);  	rt->dst.next = icmp6_dst_gc_list; diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 37b8b8ba31f..76125c57ee6 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -291,6 +291,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p  out_del_dev:  	free_netdev(dev); +	spriv->dev = NULL;  out_del_session:  	l2tp_session_delete(session);  out: diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 5f3620f0bc0..bf87c70ac6c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -1108,7 +1108,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,  	sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;  	sdata->u.ibss.ibss_join_req = jiffies; -	memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); +	memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);  	sdata->u.ibss.ssid_len = params->ssid_len;  	mutex_unlock(&sdata->u.ibss.mtx); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6f8a73c64fb..7de7717ad67 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -853,7 +853,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,  			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);  			if (info->control.vif == &sdata->vif) {  				__skb_unlink(skb, &local->pending[i]); -				dev_kfree_skb_irq(skb); +				ieee80211_free_txskb(&local->hw, skb);  			}  		}  	} diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e714ed8bb19..1b7eed252fe 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3099,22 +3099,32 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,  				   ht_cfreq, ht_oper->primary_chan,  				   cbss->channel->band);  			ht_oper = NULL; +		} else { +			channel_type = NL80211_CHAN_HT20;  		}  	} -	if (ht_oper) { -		channel_type = NL80211_CHAN_HT20; +	if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { +		/* +		 * cfg80211 already verified that the channel itself can +		 * be used, but it didn't check that we can do the right +		 * HT type, so do that here as well. If HT40 isn't allowed +		 * on this channel, disable 40 MHz operation. +		 */ -		if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { -			switch (ht_oper->ht_param & -					IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { -			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: +		switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { +		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: +			if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) +				ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; +			else  				channel_type = NL80211_CHAN_HT40PLUS; -				break; -			case IEEE80211_HT_PARAM_CHA_SEC_BELOW: +			break; +		case IEEE80211_HT_PARAM_CHA_SEC_BELOW: +			if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) +				ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; +			else  				channel_type = NL80211_CHAN_HT40MINUS; -				break; -			} +			break;  		}  	} @@ -3549,6 +3559,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,  {  	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;  	u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; +	bool tx = !req->local_state_change;  	mutex_lock(&ifmgd->mtx); @@ -3565,12 +3576,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,  	if (ifmgd->associated &&  	    ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {  		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, -				       req->reason_code, true, frame_buf); +				       req->reason_code, tx, frame_buf);  	} else {  		drv_mgd_prepare_tx(sdata->local, sdata);  		ieee80211_send_deauth_disassoc(sdata, req->bssid,  					       IEEE80211_STYPE_DEAUTH, -					       req->reason_code, true, +					       req->reason_code, tx,  					       frame_buf);  	} diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 61c621e9273..00ade7feb2e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)  		if (ieee80211_is_action(hdr->frame_control)) {  			u8 category; + +			/* make sure category field is present */ +			if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE) +				return RX_DROP_MONITOR; +  			mgmt = (struct ieee80211_mgmt *)hdr;  			category = mgmt->u.action.category;  			if (category != WLAN_CATEGORY_MESH_ACTION && @@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)  		 */  		if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&  		    ieee80211_is_data_present(hdr->frame_control)) { -			u16 ethertype; -			u8 *payload; +			unsigned int hdrlen; +			__be16 ethertype; -			payload = rx->skb->data + -				ieee80211_hdrlen(hdr->frame_control); -			ethertype = (payload[6] << 8) | payload[7]; -			if (cpu_to_be16(ethertype) == -			    rx->sdata->control_port_protocol) +			hdrlen = ieee80211_hdrlen(hdr->frame_control); + +			if (rx->skb->len < hdrlen + 8) +				return RX_DROP_MONITOR; + +			skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2); +			if (ethertype == rx->sdata->control_port_protocol)  				return RX_CONTINUE;  		} @@ -1462,11 +1469,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)  	hdr = (struct ieee80211_hdr *)rx->skb->data;  	fc = hdr->frame_control; + +	if (ieee80211_is_ctl(fc)) +		return RX_CONTINUE; +  	sc = le16_to_cpu(hdr->seq_ctrl);  	frag = sc & IEEE80211_SCTL_FRAG;  	if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || -		   (rx->skb)->len < 24 ||  		   is_multicast_ether_addr(hdr->addr1))) {  		/* not fragmented */  		goto out; @@ -1889,6 +1899,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)  	hdr = (struct ieee80211_hdr *) skb->data;  	hdrlen = ieee80211_hdrlen(hdr->frame_control); + +	/* make sure fixed part of mesh header is there, also checks skb len */ +	if (!pskb_may_pull(rx->skb, hdrlen + 6)) +		return RX_DROP_MONITOR; + +	mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + +	/* make sure full mesh header is there, also checks skb len */ +	if (!pskb_may_pull(rx->skb, +			   hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr))) +		return RX_DROP_MONITOR; + +	/* reload pointers */ +	hdr = (struct ieee80211_hdr *) skb->data;  	mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);  	/* frame is in RMC, don't forward */ @@ -1897,7 +1921,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)  	    mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))  		return RX_DROP_MONITOR; -	if (!ieee80211_is_data(hdr->frame_control)) +	if (!ieee80211_is_data(hdr->frame_control) || +	    !(status->rx_flags & IEEE80211_RX_RA_MATCH))  		return RX_CONTINUE;  	if (!mesh_hdr->ttl) @@ -1911,9 +1936,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)  		if (is_multicast_ether_addr(hdr->addr1)) {  			mpp_addr = hdr->addr3;  			proxied_addr = mesh_hdr->eaddr1; -		} else { +		} else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { +			/* has_a4 already checked in ieee80211_rx_mesh_check */  			mpp_addr = hdr->addr4;  			proxied_addr = mesh_hdr->eaddr2; +		} else { +			return RX_DROP_MONITOR;  		}  		rcu_read_lock(); @@ -1941,12 +1969,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)  	}  	skb_set_queue_mapping(skb, q); -	if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) -		goto out; -  	if (!--mesh_hdr->ttl) {  		IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); -		return RX_DROP_MONITOR; +		goto out;  	}  	if (!ifmsh->mshcfg.dot11MeshForwarding) @@ -2353,6 +2378,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)  		}  		break;  	case WLAN_CATEGORY_SELF_PROTECTED: +		if (len < (IEEE80211_MIN_ACTION_SIZE + +			   sizeof(mgmt->u.action.u.self_prot.action_code))) +			break; +  		switch (mgmt->u.action.u.self_prot.action_code) {  		case WLAN_SP_MESH_PEERING_OPEN:  		case WLAN_SP_MESH_PEERING_CLOSE: @@ -2371,6 +2400,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)  		}  		break;  	case WLAN_CATEGORY_MESH_ACTION: +		if (len < (IEEE80211_MIN_ACTION_SIZE + +			   sizeof(mgmt->u.action.u.mesh_action.action_code))) +			break; +  		if (!ieee80211_vif_is_mesh(&sdata->vif))  			break;  		if (mesh_action_is_path_sel(mgmt) && @@ -2913,10 +2946,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,  	if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))  		local->dot11ReceivedFragmentCount++; -	if (ieee80211_is_mgmt(fc)) -		err = skb_linearize(skb); -	else +	if (ieee80211_is_mgmt(fc)) { +		/* drop frame if too short for header */ +		if (skb->len < ieee80211_hdrlen(fc)) +			err = -ENOBUFS; +		else +			err = skb_linearize(skb); +	} else {  		err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); +	}  	if (err) {  		dev_kfree_skb(skb); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 797dd36a220..0a4e4c04db8 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -650,7 +650,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,  		 */  		if (!skb)  			break; -		dev_kfree_skb(skb); +		ieee80211_free_txskb(&local->hw, skb);  	}  	/* @@ -679,7 +679,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,  		local->total_ps_buffered--;  		ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n",  		       sta->sta.addr); -		dev_kfree_skb(skb); +		ieee80211_free_txskb(&local->hw, skb);  	}  	/* diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 22ca35054dd..239391807ca 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -406,7 +406,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,  	int queue = info->hw_queue;  	if (WARN_ON(!info->control.vif)) { -		kfree_skb(skb); +		ieee80211_free_txskb(&local->hw, skb);  		return;  	} @@ -431,7 +431,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,  		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);  		if (WARN_ON(!info->control.vif)) { -			kfree_skb(skb); +			ieee80211_free_txskb(&local->hw, skb);  			continue;  		} @@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,  			break;  		} -		if (id != WLAN_EID_VENDOR_SPECIFIC && -		    id != WLAN_EID_QUIET && -		    test_bit(id, seen_elems)) { -			elems->parse_error = true; -			left -= elen; -			pos += elen; -			continue; +		switch (id) { +		case WLAN_EID_SSID: +		case WLAN_EID_SUPP_RATES: +		case WLAN_EID_FH_PARAMS: +		case WLAN_EID_DS_PARAMS: +		case WLAN_EID_CF_PARAMS: +		case WLAN_EID_TIM: +		case WLAN_EID_IBSS_PARAMS: +		case WLAN_EID_CHALLENGE: +		case WLAN_EID_RSN: +		case WLAN_EID_ERP_INFO: +		case WLAN_EID_EXT_SUPP_RATES: +		case WLAN_EID_HT_CAPABILITY: +		case WLAN_EID_HT_OPERATION: +		case WLAN_EID_VHT_CAPABILITY: +		case WLAN_EID_VHT_OPERATION: +		case WLAN_EID_MESH_ID: +		case WLAN_EID_MESH_CONFIG: +		case WLAN_EID_PEER_MGMT: +		case WLAN_EID_PREQ: +		case WLAN_EID_PREP: +		case WLAN_EID_PERR: +		case WLAN_EID_RANN: +		case WLAN_EID_CHANNEL_SWITCH: +		case WLAN_EID_EXT_CHANSWITCH_ANN: +		case WLAN_EID_COUNTRY: +		case WLAN_EID_PWR_CONSTRAINT: +		case WLAN_EID_TIMEOUT_INTERVAL: +			if (test_bit(id, seen_elems)) { +				elems->parse_error = true; +				left -= elen; +				pos += elen; +				continue; +			} +			break;  		}  		if (calc_crc && id < 64 && (filter & (1ULL << id))) diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index bdb53aba888..8bd2f5c6a56 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)  		if (status->flag & RX_FLAG_MMIC_ERROR)  			goto mic_fail; -		if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) +		if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key && +		    rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)  			goto update_iv;  		return RX_CONTINUE; @@ -545,14 +546,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)  static void bip_aad(struct sk_buff *skb, u8 *aad)  { +	__le16 mask_fc; +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; +  	/* BIP AAD: FC(masked) || A1 || A2 || A3 */  	/* FC type/subtype */ -	aad[0] = skb->data[0];  	/* Mask FC Retry, PwrMgt, MoreData flags to zero */ -	aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6)); +	mask_fc = hdr->frame_control; +	mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM | +				IEEE80211_FCTL_MOREDATA); +	put_unaligned(mask_fc, (__le16 *) &aad[0]);  	/* A1 || A2 || A3 */ -	memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN); +	memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN);  } diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 7e7198b51c0..c4ee43710aa 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2589,6 +2589,8 @@ __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u)  	struct ip_vs_proto_data *pd;  #endif +	memset(u, 0, sizeof (*u)); +  #ifdef CONFIG_IP_VS_PROTO_TCP  	pd = ip_vs_proto_data_get(net, IPPROTO_TCP);  	u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ; @@ -2766,7 +2768,6 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)  	{  		struct ip_vs_timeout_user t; -		memset(&t, 0, sizeof(t));  		__ip_vs_get_timeouts(net, &t);  		if (copy_to_user(user, &t, sizeof(t)) != 0)  			ret = -EFAULT; diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 1b30b0dee70..962795e839a 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -753,7 +753,8 @@ static int callforward_do_filter(const union nf_inet_addr *src,  				   flowi4_to_flowi(&fl1), false)) {  			if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,  					   flowi4_to_flowi(&fl2), false)) { -				if (rt1->rt_gateway == rt2->rt_gateway && +				if (rt_nexthop(rt1, fl1.daddr) == +				    rt_nexthop(rt2, fl2.daddr) &&  				    rt1->dst.dev  == rt2->dst.dev)  					ret = 1;  				dst_release(&rt2->dst); diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 16c71256386..ae7f5daeee4 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c @@ -180,9 +180,9 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,  	typeof(nf_ct_timeout_find_get_hook) timeout_find_get;  	struct ctnl_timeout *timeout;  	struct nf_conn_timeout *timeout_ext; -	const struct ipt_entry *e = par->entryinfo;  	struct nf_conntrack_l4proto *l4proto;  	int ret = 0; +	u8 proto;  	rcu_read_lock();  	timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); @@ -192,9 +192,11 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,  		goto out;  	} -	if (e->ip.invflags & IPT_INV_PROTO) { +	proto = xt_ct_find_proto(par); +	if (!proto) {  		ret = -EINVAL; -		pr_info("You cannot use inversion on L4 protocol\n"); +		pr_info("You must specify a L4 protocol, and not use " +			"inversions on it.\n");  		goto out;  	} @@ -214,7 +216,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,  	/* Make sure the timeout policy matches any existing protocol tracker,  	 * otherwise default to generic.  	 */ -	l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto); +	l4proto = __nf_ct_l4proto_find(par->family, proto);  	if (timeout->l4proto->l4proto != l4proto->l4proto) {  		ret = -EINVAL;  		pr_info("Timeout policy `%s' can only be used by L4 protocol " diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c index ee2e5bc5a8c..bd93e51d30a 100644 --- a/net/netfilter/xt_TEE.c +++ b/net/netfilter/xt_TEE.c @@ -70,6 +70,7 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info)  	fl4.daddr = info->gw.ip;  	fl4.flowi4_tos = RT_TOS(iph->tos);  	fl4.flowi4_scope = RT_SCOPE_UNIVERSE; +	fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH;  	rt = ip_route_output_key(net, &fl4);  	if (IS_ERR(rt))  		return false; diff --git a/net/netfilter/xt_nat.c b/net/netfilter/xt_nat.c index 81aafa8e4fe..bea7464cc43 100644 --- a/net/netfilter/xt_nat.c +++ b/net/netfilter/xt_nat.c @@ -111,7 +111,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {  		.family		= NFPROTO_IPV4,  		.table		= "nat",  		.hooks		= (1 << NF_INET_POST_ROUTING) | -				  (1 << NF_INET_LOCAL_OUT), +				  (1 << NF_INET_LOCAL_IN),  		.me		= THIS_MODULE,  	},  	{ @@ -123,7 +123,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {  		.family		= NFPROTO_IPV4,  		.table		= "nat",  		.hooks		= (1 << NF_INET_PRE_ROUTING) | -				  (1 << NF_INET_LOCAL_IN), +				  (1 << NF_INET_LOCAL_OUT),  		.me		= THIS_MODULE,  	},  	{ @@ -133,7 +133,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {  		.targetsize	= sizeof(struct nf_nat_range),  		.table		= "nat",  		.hooks		= (1 << NF_INET_POST_ROUTING) | -				  (1 << NF_INET_LOCAL_OUT), +				  (1 << NF_INET_LOCAL_IN),  		.me		= THIS_MODULE,  	},  	{ @@ -143,7 +143,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {  		.targetsize	= sizeof(struct nf_nat_range),  		.table		= "nat",  		.hooks		= (1 << NF_INET_PRE_ROUTING) | -				  (1 << NF_INET_LOCAL_IN), +				  (1 << NF_INET_LOCAL_OUT),  		.me		= THIS_MODULE,  	},  }; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 01e944a017a..4da797fa5ec 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -138,6 +138,8 @@ static int netlink_dump(struct sock *sk);  static DEFINE_RWLOCK(nl_table_lock);  static atomic_t nl_table_users = ATOMIC_INIT(0); +#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); +  static ATOMIC_NOTIFIER_HEAD(netlink_chain);  static inline u32 netlink_group_mask(u32 group) @@ -345,6 +347,11 @@ netlink_update_listeners(struct sock *sk)  	struct hlist_node *node;  	unsigned long mask;  	unsigned int i; +	struct listeners *listeners; + +	listeners = nl_deref_protected(tbl->listeners); +	if (!listeners) +		return;  	for (i = 0; i < NLGRPLONGS(tbl->groups); i++) {  		mask = 0; @@ -352,7 +359,7 @@ netlink_update_listeners(struct sock *sk)  			if (i < NLGRPLONGS(nlk_sk(sk)->ngroups))  				mask |= nlk_sk(sk)->groups[i];  		} -		tbl->listeners->masks[i] = mask; +		listeners->masks[i] = mask;  	}  	/* this function is only called with the netlink table "grabbed", which  	 * makes sure updates are visible before bind or setsockopt return. */ @@ -536,7 +543,11 @@ static int netlink_release(struct socket *sock)  	if (netlink_is_kernel(sk)) {  		BUG_ON(nl_table[sk->sk_protocol].registered == 0);  		if (--nl_table[sk->sk_protocol].registered == 0) { -			kfree(nl_table[sk->sk_protocol].listeners); +			struct listeners *old; + +			old = nl_deref_protected(nl_table[sk->sk_protocol].listeners); +			RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL); +			kfree_rcu(old, rcu);  			nl_table[sk->sk_protocol].module = NULL;  			nl_table[sk->sk_protocol].bind = NULL;  			nl_table[sk->sk_protocol].flags = 0; @@ -982,7 +993,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group)  	rcu_read_lock();  	listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); -	if (group - 1 < nl_table[sk->sk_protocol].groups) +	if (listeners && group - 1 < nl_table[sk->sk_protocol].groups)  		res = test_bit(group - 1, listeners->masks);  	rcu_read_unlock(); @@ -1625,7 +1636,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups)  		new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC);  		if (!new)  			return -ENOMEM; -		old = rcu_dereference_protected(tbl->listeners, 1); +		old = nl_deref_protected(tbl->listeners);  		memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups));  		rcu_assign_pointer(tbl->listeners, new); diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index f0dd83cff90..9687fa1c227 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -84,18 +84,19 @@   * grp->index is the index of the group; and grp->slot_shift   * is the shift for the corresponding (scaled) sigma_i.   */ -#define QFQ_MAX_INDEX		19 -#define QFQ_MAX_WSHIFT		16 +#define QFQ_MAX_INDEX		24 +#define QFQ_MAX_WSHIFT		12  #define	QFQ_MAX_WEIGHT		(1<<QFQ_MAX_WSHIFT) -#define QFQ_MAX_WSUM		(2*QFQ_MAX_WEIGHT) +#define QFQ_MAX_WSUM		(16*QFQ_MAX_WEIGHT)  #define FRAC_BITS		30	/* fixed point arithmetic */  #define ONE_FP			(1UL << FRAC_BITS)  #define IWSUM			(ONE_FP/QFQ_MAX_WSUM) -#define QFQ_MTU_SHIFT		11 +#define QFQ_MTU_SHIFT		16	/* to support TSO/GSO */  #define QFQ_MIN_SLOT_SHIFT	(FRAC_BITS + QFQ_MTU_SHIFT - QFQ_MAX_INDEX) +#define QFQ_MIN_LMAX		256	/* min possible lmax for a class */  /*   * Possible group states.  These values are used as indexes for the bitmaps @@ -231,6 +232,32 @@ static void qfq_update_class_params(struct qfq_sched *q, struct qfq_class *cl,  	q->wsum += delta_w;  } +static void qfq_update_reactivate_class(struct qfq_sched *q, +					struct qfq_class *cl, +					u32 inv_w, u32 lmax, int delta_w) +{ +	bool need_reactivation = false; +	int i = qfq_calc_index(inv_w, lmax); + +	if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) { +		/* +		 * shift cl->F back, to not charge the +		 * class for the not-yet-served head +		 * packet +		 */ +		cl->F = cl->S; +		/* remove class from its slot in the old group */ +		qfq_deactivate_class(q, cl); +		need_reactivation = true; +	} + +	qfq_update_class_params(q, cl, lmax, inv_w, delta_w); + +	if (need_reactivation) /* activate in new group */ +		qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc)); +} + +  static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,  			    struct nlattr **tca, unsigned long *arg)  { @@ -238,7 +265,7 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,  	struct qfq_class *cl = (struct qfq_class *)*arg;  	struct nlattr *tb[TCA_QFQ_MAX + 1];  	u32 weight, lmax, inv_w; -	int i, err; +	int err;  	int delta_w;  	if (tca[TCA_OPTIONS] == NULL) { @@ -270,16 +297,14 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,  	if (tb[TCA_QFQ_LMAX]) {  		lmax = nla_get_u32(tb[TCA_QFQ_LMAX]); -		if (!lmax || lmax > (1UL << QFQ_MTU_SHIFT)) { +		if (lmax < QFQ_MIN_LMAX || lmax > (1UL << QFQ_MTU_SHIFT)) {  			pr_notice("qfq: invalid max length %u\n", lmax);  			return -EINVAL;  		}  	} else -		lmax = 1UL << QFQ_MTU_SHIFT; +		lmax = psched_mtu(qdisc_dev(sch));  	if (cl != NULL) { -		bool need_reactivation = false; -  		if (tca[TCA_RATE]) {  			err = gen_replace_estimator(&cl->bstats, &cl->rate_est,  						    qdisc_root_sleeping_lock(sch), @@ -291,24 +316,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,  		if (lmax == cl->lmax && inv_w == cl->inv_w)  			return 0; /* nothing to update */ -		i = qfq_calc_index(inv_w, lmax);  		sch_tree_lock(sch); -		if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) { -			/* -			 * shift cl->F back, to not charge the -			 * class for the not-yet-served head -			 * packet -			 */ -			cl->F = cl->S; -			/* remove class from its slot in the old group */ -			qfq_deactivate_class(q, cl); -			need_reactivation = true; -		} - -		qfq_update_class_params(q, cl, lmax, inv_w, delta_w); - -		if (need_reactivation) /* activate in new group */ -			qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc)); +		qfq_update_reactivate_class(q, cl, inv_w, lmax, delta_w);  		sch_tree_unlock(sch);  		return 0; @@ -663,15 +672,48 @@ static void qfq_make_eligible(struct qfq_sched *q, u64 old_V)  /* - * XXX we should make sure that slot becomes less than 32. - * This is guaranteed by the input values. - * roundedS is always cl->S rounded on grp->slot_shift bits. + * If the weight and lmax (max_pkt_size) of the classes do not change, + * then QFQ guarantees that the slot index is never higher than + * 2 + ((1<<QFQ_MTU_SHIFT)/QFQ_MIN_LMAX) * (QFQ_MAX_WEIGHT/QFQ_MAX_WSUM). + * + * With the current values of the above constants, the index is + * then guaranteed to never be higher than 2 + 256 * (1 / 16) = 18. + * + * When the weight of a class is increased or the lmax of the class is + * decreased, a new class with smaller slot size may happen to be + * activated. The activation of this class should be properly delayed + * to when the service of the class has finished in the ideal system + * tracked by QFQ. If the activation of the class is not delayed to + * this reference time instant, then this class may be unjustly served + * before other classes waiting for service. This may cause + * (unfrequently) the above bound to the slot index to be violated for + * some of these unlucky classes. + * + * Instead of delaying the activation of the new class, which is quite + * complex, the following inaccurate but simple solution is used: if + * the slot index is higher than QFQ_MAX_SLOTS-2, then the timestamps + * of the class are shifted backward so as to let the slot index + * become equal to QFQ_MAX_SLOTS-2. This threshold is used because, if + * the slot index is above it, then the data structure implementing + * the bucket list either gets immediately corrupted or may get + * corrupted on a possible next packet arrival that causes the start + * time of the group to be shifted backward.   */  static void qfq_slot_insert(struct qfq_group *grp, struct qfq_class *cl,  			    u64 roundedS)  {  	u64 slot = (roundedS - grp->S) >> grp->slot_shift; -	unsigned int i = (grp->front + slot) % QFQ_MAX_SLOTS; +	unsigned int i; /* slot index in the bucket list */ + +	if (unlikely(slot > QFQ_MAX_SLOTS - 2)) { +		u64 deltaS = roundedS - grp->S - +			((u64)(QFQ_MAX_SLOTS - 2)<<grp->slot_shift); +		cl->S -= deltaS; +		cl->F -= deltaS; +		slot = QFQ_MAX_SLOTS - 2; +	} + +	i = (grp->front + slot) % QFQ_MAX_SLOTS;  	hlist_add_head(&cl->next, &grp->slots[i]);  	__set_bit(slot, &grp->full_slots); @@ -892,6 +934,13 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)  	}  	pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid); +	if (unlikely(cl->lmax < qdisc_pkt_len(skb))) { +		pr_debug("qfq: increasing maxpkt from %u to %u for class %u", +			  cl->lmax, qdisc_pkt_len(skb), cl->common.classid); +		qfq_update_reactivate_class(q, cl, cl->inv_w, +					    qdisc_pkt_len(skb), 0); +	} +  	err = qdisc_enqueue(skb, cl->qdisc);  	if (unlikely(err != NET_XMIT_SUCCESS)) {  		pr_debug("qfq_enqueue: enqueue failed %d\n", err); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 59d16ea927f..a60d1f8b41c 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -974,7 +974,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,  	void *addr_buf;  	struct sctp_af *af; -	SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p" +	SCTP_DEBUG_PRINTK("sctp_setsockopt_bindx: sk %p addrs %p"  			  " addrs_size %d opt %d\n", sk, addrs, addrs_size, op);  	if (unlikely(addrs_size <= 0)) diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 5a3d675d2f2..a9c0bbccad6 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c @@ -172,7 +172,7 @@ out_free:  		xprt_free_allocation(req);  	dprintk("RPC:       setup backchannel transport failed\n"); -	return -1; +	return -ENOMEM;  }  EXPORT_SYMBOL_GPL(xprt_setup_backchannel); diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index aaaadfbe36e..75853cabf4c 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -254,7 +254,6 @@ struct sock_xprt {  	void			(*old_data_ready)(struct sock *, int);  	void			(*old_state_change)(struct sock *);  	void			(*old_write_space)(struct sock *); -	void			(*old_error_report)(struct sock *);  };  /* @@ -737,10 +736,10 @@ static int xs_tcp_send_request(struct rpc_task *task)  		dprintk("RPC:       sendmsg returned unrecognized error %d\n",  			-status);  	case -ECONNRESET: -	case -EPIPE:  		xs_tcp_shutdown(xprt);  	case -ECONNREFUSED:  	case -ENOTCONN: +	case -EPIPE:  		clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);  	} @@ -781,7 +780,6 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk)  	transport->old_data_ready = sk->sk_data_ready;  	transport->old_state_change = sk->sk_state_change;  	transport->old_write_space = sk->sk_write_space; -	transport->old_error_report = sk->sk_error_report;  }  static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) @@ -789,7 +787,6 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s  	sk->sk_data_ready = transport->old_data_ready;  	sk->sk_state_change = transport->old_state_change;  	sk->sk_write_space = transport->old_write_space; -	sk->sk_error_report = transport->old_error_report;  }  static void xs_reset_transport(struct sock_xprt *transport) @@ -1453,7 +1450,7 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt)  	xprt_clear_connecting(xprt);  } -static void xs_sock_mark_closed(struct rpc_xprt *xprt) +static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt)  {  	smp_mb__before_clear_bit();  	clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); @@ -1461,6 +1458,11 @@ static void xs_sock_mark_closed(struct rpc_xprt *xprt)  	clear_bit(XPRT_CLOSE_WAIT, &xprt->state);  	clear_bit(XPRT_CLOSING, &xprt->state);  	smp_mb__after_clear_bit(); +} + +static void xs_sock_mark_closed(struct rpc_xprt *xprt) +{ +	xs_sock_reset_connection_flags(xprt);  	/* Mark transport as closed and wake up all pending tasks */  	xprt_disconnect_done(xprt);  } @@ -1516,6 +1518,7 @@ static void xs_tcp_state_change(struct sock *sk)  	case TCP_CLOSE_WAIT:  		/* The server initiated a shutdown of the socket */  		xprt->connect_cookie++; +		clear_bit(XPRT_CONNECTED, &xprt->state);  		xs_tcp_force_close(xprt);  	case TCP_CLOSING:  		/* @@ -1540,25 +1543,6 @@ static void xs_tcp_state_change(struct sock *sk)  	read_unlock_bh(&sk->sk_callback_lock);  } -/** - * xs_error_report - callback mainly for catching socket errors - * @sk: socket - */ -static void xs_error_report(struct sock *sk) -{ -	struct rpc_xprt *xprt; - -	read_lock_bh(&sk->sk_callback_lock); -	if (!(xprt = xprt_from_sock(sk))) -		goto out; -	dprintk("RPC:       %s client %p...\n" -			"RPC:       error %d\n", -			__func__, xprt, sk->sk_err); -	xprt_wake_pending_tasks(xprt, -EAGAIN); -out: -	read_unlock_bh(&sk->sk_callback_lock); -} -  static void xs_write_space(struct sock *sk)  {  	struct socket *sock; @@ -1858,7 +1842,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt,  		sk->sk_user_data = xprt;  		sk->sk_data_ready = xs_local_data_ready;  		sk->sk_write_space = xs_udp_write_space; -		sk->sk_error_report = xs_error_report;  		sk->sk_allocation = GFP_ATOMIC;  		xprt_clear_connected(xprt); @@ -1983,7 +1966,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)  		sk->sk_user_data = xprt;  		sk->sk_data_ready = xs_udp_data_ready;  		sk->sk_write_space = xs_udp_write_space; -		sk->sk_error_report = xs_error_report;  		sk->sk_no_check = UDP_CSUM_NORCV;  		sk->sk_allocation = GFP_ATOMIC; @@ -2050,10 +2032,8 @@ static void xs_abort_connection(struct sock_xprt *transport)  	any.sa_family = AF_UNSPEC;  	result = kernel_connect(transport->sock, &any, sizeof(any), 0);  	if (!result) -		xs_sock_mark_closed(&transport->xprt); -	else -		dprintk("RPC:       AF_UNSPEC connect return code %d\n", -				result); +		xs_sock_reset_connection_flags(&transport->xprt); +	dprintk("RPC:       AF_UNSPEC connect return code %d\n", result);  }  static void xs_tcp_reuse_connection(struct sock_xprt *transport) @@ -2098,7 +2078,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)  		sk->sk_data_ready = xs_tcp_data_ready;  		sk->sk_state_change = xs_tcp_state_change;  		sk->sk_write_space = xs_tcp_write_space; -		sk->sk_error_report = xs_error_report;  		sk->sk_allocation = GFP_ATOMIC;  		/* socket options */ diff --git a/net/tipc/handler.c b/net/tipc/handler.c index 111ff8300ae..b36f0fcd9bd 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c @@ -116,7 +116,6 @@ void tipc_handler_stop(void)  		return;  	handler_enabled = 0; -	tasklet_disable(&tipc_tasklet);  	tasklet_kill(&tipc_tasklet);  	spin_lock_bh(&qitem_lock); diff --git a/net/wireless/core.c b/net/wireless/core.c index 443d4d7deea..3f725305208 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -526,8 +526,7 @@ int wiphy_register(struct wiphy *wiphy)  		for (i = 0; i < sband->n_channels; i++) {  			sband->channels[i].orig_flags =  				sband->channels[i].flags; -			sband->channels[i].orig_mag = -				sband->channels[i].max_antenna_gain; +			sband->channels[i].orig_mag = INT_MAX;  			sband->channels[i].orig_mpwr =  				sband->channels[i].max_power;  			sband->channels[i].band = band; diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 8016fee0752..904a7f36832 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,  		.reason_code = reason,  		.ie = ie,  		.ie_len = ie_len, +		.local_state_change = local_state_change,  	};  	ASSERT_WDEV_LOCK(wdev); -	if (local_state_change) { -		if (wdev->current_bss && -		    ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { -			cfg80211_unhold_bss(wdev->current_bss); -			cfg80211_put_bss(&wdev->current_bss->pub); -			wdev->current_bss = NULL; -		} - +	if (local_state_change && (!wdev->current_bss || +	    !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))  		return 0; -	}  	return rdev->ops->deauth(&rdev->wiphy, dev, &req);  } diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3b8cbbc214d..bcc7d7ee5a5 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -908,7 +908,7 @@ static void handle_channel(struct wiphy *wiphy,  			map_regdom_flags(reg_rule->flags) | bw_flags;  		chan->max_antenna_gain = chan->orig_mag =  			(int) MBI_TO_DBI(power_rule->max_antenna_gain); -		chan->max_power = chan->orig_mpwr = +		chan->max_reg_power = chan->max_power = chan->orig_mpwr =  			(int) MBM_TO_DBM(power_rule->max_eirp);  		return;  	} @@ -1331,7 +1331,8 @@ static void handle_channel_custom(struct wiphy *wiphy,  	chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;  	chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); -	chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); +	chan->max_reg_power = chan->max_power = +		(int) MBM_TO_DBM(power_rule->max_eirp);  }  static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, diff --git a/net/wireless/util.c b/net/wireless/util.c index ef35f4ef2aa..2762e832998 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -309,23 +309,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)  }  EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); -static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)  {  	int ae = meshhdr->flags & MESH_FLAGS_AE; -	/* 7.1.3.5a.2 */ +	/* 802.11-2012, 8.2.4.7.3 */  	switch (ae) { +	default:  	case 0:  		return 6;  	case MESH_FLAGS_AE_A4:  		return 12;  	case MESH_FLAGS_AE_A5_A6:  		return 18; -	case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6): -		return 24; -	default: -		return 6;  	}  } +EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);  int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,  			   enum nl80211_iftype iftype) @@ -373,6 +371,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,  			/* make sure meshdr->flags is on the linear part */  			if (!pskb_may_pull(skb, hdrlen + 1))  				return -1; +			if (meshdr->flags & MESH_FLAGS_AE_A4) +				return -1;  			if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {  				skb_copy_bits(skb, hdrlen +  					offsetof(struct ieee80211s_hdr, eaddr1), @@ -397,6 +397,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,  			/* make sure meshdr->flags is on the linear part */  			if (!pskb_may_pull(skb, hdrlen + 1))  				return -1; +			if (meshdr->flags & MESH_FLAGS_AE_A5_A6) +				return -1;  			if (meshdr->flags & MESH_FLAGS_AE_A4)  				skb_copy_bits(skb, hdrlen +  					offsetof(struct ieee80211s_hdr, eaddr1), diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst index dda4b2b6192..ecbb44797e2 100644 --- a/scripts/Makefile.modinst +++ b/scripts/Makefile.modinst @@ -16,8 +16,9 @@ PHONY += $(modules)  __modinst: $(modules)  	@: +# Don't stop modules_install if we can't sign external modules.  quiet_cmd_modules_install = INSTALL $@ -      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) +      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD))  # Modules built outside the kernel source tree go into extra by default  INSTALL_MOD_DIR ?= extra diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 21a9f5de0a2..f18750e3bd6 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1890,8 +1890,10 @@ sub process {  		}  		if ($realfile =~ m@^(drivers/net/|net/)@ && -		    $rawline !~ m@^\+[ \t]*(\/\*|\*\/)@ && -		    $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { +		    $rawline !~ m@^\+[ \t]*\*/[ \t]*$@ &&	#trailing */ +		    $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ &&	#inline /*...*/ +		    $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ &&	#trailing **/ +		    $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {	#non blank */  			WARN("NETWORKING_BLOCK_COMMENT_STYLE",  			     "networking block comments put the trailing */ on a separate line\n" . $herecurr);  		} diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index cf5fd220309..813200384d9 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -724,6 +724,8 @@ fail:   */  static void free_profile(struct aa_profile *profile)  { +	struct aa_profile *p; +  	AA_DEBUG("%s(%p)\n", __func__, profile);  	if (!profile) @@ -751,7 +753,27 @@ static void free_profile(struct aa_profile *profile)  	aa_put_dfa(profile->xmatch);  	aa_put_dfa(profile->policy.dfa); -	aa_put_profile(profile->replacedby); +	/* put the profile reference for replacedby, but not via +	 * put_profile(kref_put). +	 * replacedby can form a long chain that can result in cascading +	 * frees that blows the stack because kref_put makes a nested fn +	 * call (it looks like recursion, with free_profile calling +	 * free_profile) for each profile in the chain lp#1056078. +	 */ +	for (p = profile->replacedby; p; ) { +		if (atomic_dec_and_test(&p->base.count.refcount)) { +			/* no more refs on p, grab its replacedby */ +			struct aa_profile *next = p->replacedby; +			/* break the chain */ +			p->replacedby = NULL; +			/* now free p, chain is broken */ +			free_profile(p); + +			/* follow up with next profile in the chain */ +			p = next; +		} else +			break; +	}  	kzfree(profile);  } diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 44dfc415a37..842c254396d 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -42,7 +42,10 @@ struct dev_exception_item {  struct dev_cgroup {  	struct cgroup_subsys_state css;  	struct list_head exceptions; -	bool deny_all; +	enum { +		DEVCG_DEFAULT_ALLOW, +		DEVCG_DEFAULT_DENY, +	} behavior;  };  static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s) @@ -182,13 +185,13 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup *cgroup)  	parent_cgroup = cgroup->parent;  	if (parent_cgroup == NULL) -		dev_cgroup->deny_all = false; +		dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW;  	else {  		parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);  		mutex_lock(&devcgroup_mutex);  		ret = dev_exceptions_copy(&dev_cgroup->exceptions,  					  &parent_dev_cgroup->exceptions); -		dev_cgroup->deny_all = parent_dev_cgroup->deny_all; +		dev_cgroup->behavior = parent_dev_cgroup->behavior;  		mutex_unlock(&devcgroup_mutex);  		if (ret) {  			kfree(dev_cgroup); @@ -260,7 +263,7 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,  	 * - List the exceptions in case the default policy is to deny  	 * This way, the file remains as a "whitelist of devices"  	 */ -	if (devcgroup->deny_all == false) { +	if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {  		set_access(acc, ACC_MASK);  		set_majmin(maj, ~0);  		set_majmin(min, ~0); @@ -314,12 +317,12 @@ static int may_access(struct dev_cgroup *dev_cgroup,  	 * In two cases we'll consider this new exception valid:  	 * - the dev cgroup has its default policy to allow + exception list:  	 *   the new exception should *not* match any of the exceptions -	 *   (!deny_all, !match) +	 *   (behavior == DEVCG_DEFAULT_ALLOW, !match)  	 * - the dev cgroup has its default policy to deny + exception list:  	 *   the new exception *should* match the exceptions -	 *   (deny_all, match) +	 *   (behavior == DEVCG_DEFAULT_DENY, match)  	 */ -	if (dev_cgroup->deny_all == match) +	if ((dev_cgroup->behavior == DEVCG_DEFAULT_DENY) == match)  		return 1;  	return 0;  } @@ -341,6 +344,17 @@ static int parent_has_perm(struct dev_cgroup *childcg,  	return may_access(parent, ex);  } +/** + * may_allow_all - checks if it's possible to change the behavior to + *		   allow based on parent's rules. + * @parent: device cgroup's parent + * returns: != 0 in case it's allowed, 0 otherwise + */ +static inline int may_allow_all(struct dev_cgroup *parent) +{ +	return parent->behavior == DEVCG_DEFAULT_ALLOW; +} +  /*   * Modify the exception list using allow/deny rules.   * CAP_SYS_ADMIN is needed for this.  It's at least separate from CAP_MKNOD @@ -358,9 +372,11 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,  				   int filetype, const char *buffer)  {  	const char *b; -	char *endp; -	int count; +	char temp[12];		/* 11 + 1 characters needed for a u32 */ +	int count, rc;  	struct dev_exception_item ex; +	struct cgroup *p = devcgroup->css.cgroup; +	struct dev_cgroup *parent = cgroup_to_devcgroup(p->parent);  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; @@ -372,14 +388,18 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,  	case 'a':  		switch (filetype) {  		case DEVCG_ALLOW: -			if (!parent_has_perm(devcgroup, &ex)) +			if (!may_allow_all(parent))  				return -EPERM;  			dev_exception_clean(devcgroup); -			devcgroup->deny_all = false; +			rc = dev_exceptions_copy(&devcgroup->exceptions, +						 &parent->exceptions); +			if (rc) +				return rc; +			devcgroup->behavior = DEVCG_DEFAULT_ALLOW;  			break;  		case DEVCG_DENY:  			dev_exception_clean(devcgroup); -			devcgroup->deny_all = true; +			devcgroup->behavior = DEVCG_DEFAULT_DENY;  			break;  		default:  			return -EINVAL; @@ -402,8 +422,16 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,  		ex.major = ~0;  		b++;  	} else if (isdigit(*b)) { -		ex.major = simple_strtoul(b, &endp, 10); -		b = endp; +		memset(temp, 0, sizeof(temp)); +		for (count = 0; count < sizeof(temp) - 1; count++) { +			temp[count] = *b; +			b++; +			if (!isdigit(*b)) +				break; +		} +		rc = kstrtou32(temp, 10, &ex.major); +		if (rc) +			return -EINVAL;  	} else {  		return -EINVAL;  	} @@ -416,8 +444,16 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,  		ex.minor = ~0;  		b++;  	} else if (isdigit(*b)) { -		ex.minor = simple_strtoul(b, &endp, 10); -		b = endp; +		memset(temp, 0, sizeof(temp)); +		for (count = 0; count < sizeof(temp) - 1; count++) { +			temp[count] = *b; +			b++; +			if (!isdigit(*b)) +				break; +		} +		rc = kstrtou32(temp, 10, &ex.minor); +		if (rc) +			return -EINVAL;  	} else {  		return -EINVAL;  	} @@ -452,7 +488,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,  		 * an matching exception instead. And be silent about it: we  		 * don't want to break compatibility  		 */ -		if (devcgroup->deny_all == false) { +		if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {  			dev_exception_rm(devcgroup, &ex);  			return 0;  		} @@ -463,7 +499,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,  		 * an matching exception instead. And be silent about it: we  		 * don't want to break compatibility  		 */ -		if (devcgroup->deny_all == true) { +		if (devcgroup->behavior == DEVCG_DEFAULT_DENY) {  			dev_exception_rm(devcgroup, &ex);  			return 0;  		} @@ -533,10 +569,10 @@ struct cgroup_subsys devices_subsys = {   *   * returns 0 on success, -EPERM case the operation is not permitted   */ -static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup, -					short type, u32 major, u32 minor, +static int __devcgroup_check_permission(short type, u32 major, u32 minor,  				        short access)  { +	struct dev_cgroup *dev_cgroup;  	struct dev_exception_item ex;  	int rc; @@ -547,6 +583,7 @@ static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,  	ex.access = access;  	rcu_read_lock(); +	dev_cgroup = task_devcgroup(current);  	rc = may_access(dev_cgroup, &ex);  	rcu_read_unlock(); @@ -558,7 +595,6 @@ static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,  int __devcgroup_inode_permission(struct inode *inode, int mask)  { -	struct dev_cgroup *dev_cgroup = task_devcgroup(current);  	short type, access = 0;  	if (S_ISBLK(inode->i_mode)) @@ -570,13 +606,12 @@ int __devcgroup_inode_permission(struct inode *inode, int mask)  	if (mask & MAY_READ)  		access |= ACC_READ; -	return __devcgroup_check_permission(dev_cgroup, type, imajor(inode), -					    iminor(inode), access); +	return __devcgroup_check_permission(type, imajor(inode), iminor(inode), +			access);  }  int devcgroup_inode_mknod(int mode, dev_t dev)  { -	struct dev_cgroup *dev_cgroup = task_devcgroup(current);  	short type;  	if (!S_ISBLK(mode) && !S_ISCHR(mode)) @@ -587,7 +622,7 @@ int devcgroup_inode_mknod(int mode, dev_t dev)  	else  		type = DEV_CHAR; -	return __devcgroup_check_permission(dev_cgroup, type, MAJOR(dev), -					    MINOR(dev), ACC_MKNOD); +	return __devcgroup_check_permission(type, MAJOR(dev), MINOR(dev), +			ACC_MKNOD);  } diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index c40ae573346..ad11dc99479 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f)  	if (dirn != compr->direction) {  		pr_err("this device doesn't support this direction\n"); +		snd_card_unref(compr->card);  		return -EINVAL;  	}  	data = kzalloc(sizeof(*data), GFP_KERNEL); -	if (!data) +	if (!data) { +		snd_card_unref(compr->card);  		return -ENOMEM; +	}  	data->stream.ops = compr->ops;  	data->stream.direction = dirn;  	data->stream.private_data = compr->private_data; @@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f)  	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);  	if (!runtime) {  		kfree(data); +		snd_card_unref(compr->card);  		return -ENOMEM;  	}  	runtime->state = SNDRV_PCM_STATE_OPEN; @@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f)  		kfree(runtime);  		kfree(data);  	} -	return ret; +	snd_card_unref(compr->card); +	return 0;  }  static int snd_compr_free(struct inode *inode, struct file *f) diff --git a/sound/core/control.c b/sound/core/control.c index 7e86a5b9f3b..8c7c2c9bba6 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)  	write_lock_irqsave(&card->ctl_files_rwlock, flags);  	list_add_tail(&ctl->list, &card->ctl_files);  	write_unlock_irqrestore(&card->ctl_files_rwlock, flags); +	snd_card_unref(card);  	return 0;        __error: @@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file)        __error2:  	snd_card_file_remove(card, file);        __error1: +	if (card) +		snd_card_unref(card);        	return err;  } @@ -1434,6 +1437,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer,  			spin_unlock_irq(&ctl->read_lock);  			schedule();  			remove_wait_queue(&ctl->change_sleep, &wait); +			if (ctl->card->shutdown) +				return -ENODEV;  			if (signal_pending(current))  				return -ERESTARTSYS;  			spin_lock_irq(&ctl->read_lock); diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 75ea16f35b1..3f7f6628cf7 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -100,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)  	if (hw == NULL)  		return -ENODEV; -	if (!try_module_get(hw->card->module)) +	if (!try_module_get(hw->card->module)) { +		snd_card_unref(hw->card);  		return -EFAULT; +	}  	init_waitqueue_entry(&wait, current);  	add_wait_queue(&hw->open_wait, &wait); @@ -129,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)  		mutex_unlock(&hw->open_mutex);  		schedule();  		mutex_lock(&hw->open_mutex); +		if (hw->card->shutdown) { +			err = -ENODEV; +			break; +		}  		if (signal_pending(current)) {  			err = -ERESTARTSYS;  			break; @@ -148,6 +154,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)  	mutex_unlock(&hw->open_mutex);  	if (err < 0)  		module_put(hw->card->module); +	snd_card_unref(hw->card);  	return err;  } @@ -459,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device)  		mutex_unlock(®ister_mutex);  		return -EINVAL;  	} +	mutex_lock(&hwdep->open_mutex); +	wake_up(&hwdep->open_wait);  #ifdef CONFIG_SND_OSSEMUL  	if (hwdep->ossreg)  		snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);  #endif  	snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);  	list_del_init(&hwdep->list); +	mutex_unlock(&hwdep->open_mutex);  	mutex_unlock(®ister_mutex);  	return 0;  } diff --git a/sound/core/init.c b/sound/core/init.c index d8ec849af12..7b012d15c2c 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid,  	spin_lock_init(&card->files_lock);  	INIT_LIST_HEAD(&card->files_list);  	init_waitqueue_head(&card->shutdown_sleep); +	atomic_set(&card->refcount, 0);  #ifdef CONFIG_PM  	mutex_init(&card->power_lock);  	init_waitqueue_head(&card->power_sleep); @@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *card)  	return 0;  } +/** + * snd_card_unref - release the reference counter + * @card: the card instance + * + * Decrements the reference counter.  When it reaches to zero, wake up + * the sleeper and call the destructor if needed. + */ +void snd_card_unref(struct snd_card *card) +{ +	if (atomic_dec_and_test(&card->refcount)) { +		wake_up(&card->shutdown_sleep); +		if (card->free_on_last_close) +			snd_card_do_free(card); +	} +} +EXPORT_SYMBOL(snd_card_unref); +  int snd_card_free_when_closed(struct snd_card *card)  { -	int free_now = 0; -	int ret = snd_card_disconnect(card); -	if (ret) -		return ret; +	int ret; -	spin_lock(&card->files_lock); -	if (list_empty(&card->files_list)) -		free_now = 1; -	else -		card->free_on_last_close = 1; -	spin_unlock(&card->files_lock); +	atomic_inc(&card->refcount); +	ret = snd_card_disconnect(card); +	if (ret) { +		atomic_dec(&card->refcount); +		return ret; +	} -	if (free_now) +	card->free_on_last_close = 1; +	if (atomic_dec_and_test(&card->refcount))  		snd_card_do_free(card);  	return 0;  } @@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card)  		return ret;  	/* wait, until all devices are ready for the free operation */ -	wait_event(card->shutdown_sleep, list_empty(&card->files_list)); +	wait_event(card->shutdown_sleep, !atomic_read(&card->refcount));  	snd_card_do_free(card);  	return 0;  } @@ -886,6 +902,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)  		return -ENODEV;  	}  	list_add(&mfile->list, &card->files_list); +	atomic_inc(&card->refcount);  	spin_unlock(&card->files_lock);  	return 0;  } @@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add);  int snd_card_file_remove(struct snd_card *card, struct file *file)  {  	struct snd_monitor_file *mfile, *found = NULL; -	int last_close = 0;  	spin_lock(&card->files_lock);  	list_for_each_entry(mfile, &card->files_list, list) { @@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)  			break;  		}  	} -	if (list_empty(&card->files_list)) -		last_close = 1;  	spin_unlock(&card->files_lock); -	if (last_close) { -		wake_up(&card->shutdown_sleep); -		if (card->free_on_last_close) -			snd_card_do_free(card); -	}  	if (!found) {  		snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);  		return -ENOENT;  	}  	kfree(found); +	snd_card_unref(card);  	return 0;  } diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 29f6ded0255..e8a1d18774b 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)  					 SNDRV_OSS_DEVICE_TYPE_MIXER);  	if (card == NULL)  		return -ENODEV; -	if (card->mixer_oss == NULL) +	if (card->mixer_oss == NULL) { +		snd_card_unref(card);  		return -ENODEV; +	}  	err = snd_card_file_add(card, file); -	if (err < 0) +	if (err < 0) { +		snd_card_unref(card);  		return err; +	}  	fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);  	if (fmixer == NULL) {  		snd_card_file_remove(card, file); +		snd_card_unref(card);  		return -ENOMEM;  	}  	fmixer->card = card; @@ -68,8 +73,10 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)  	if (!try_module_get(card->module)) {  		kfree(fmixer);  		snd_card_file_remove(card, file); +		snd_card_unref(card);  		return -EFAULT;  	} +	snd_card_unref(card);  	return 0;  } diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 08fde0060fd..4c1cc51772e 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)  		mutex_unlock(&pcm->open_mutex);  		schedule();  		mutex_lock(&pcm->open_mutex); +		if (pcm->card->shutdown) { +			err = -ENODEV; +			break; +		}  		if (signal_pending(current)) {  			err = -ERESTARTSYS;  			break; @@ -2450,6 +2454,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)  	mutex_unlock(&pcm->open_mutex);  	if (err < 0)  		goto __error; +	snd_card_unref(pcm->card);  	return err;        __error: @@ -2457,6 +2462,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)        __error2:        	snd_card_file_remove(pcm->card, file);        __error1: +	if (pcm) +		snd_card_unref(pcm->card);  	return err;  } diff --git a/sound/core/pcm.c b/sound/core/pcm.c index f2991940b27..030102caeee 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1086,11 +1086,19 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)  	if (list_empty(&pcm->list))  		goto unlock; +	mutex_lock(&pcm->open_mutex); +	wake_up(&pcm->open_wait);  	list_del_init(&pcm->list);  	for (cidx = 0; cidx < 2; cidx++) -		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) -			if (substream->runtime) +		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { +			snd_pcm_stream_lock_irq(substream); +			if (substream->runtime) {  				substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; +				wake_up(&substream->runtime->sleep); +				wake_up(&substream->runtime->tsleep); +			} +			snd_pcm_stream_unlock_irq(substream); +		}  	list_for_each_entry(notify, &snd_pcm_notify_list, list) {  		notify->n_disconnect(pcm);  	} @@ -1110,6 +1118,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)  			pcm->streams[cidx].chmap_kctl = NULL;  		}  	} +	mutex_unlock(&pcm->open_mutex);   unlock:  	mutex_unlock(®ister_mutex);  	return 0; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 5e12e5bacbb..f9ddecf2f4c 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)  	return usecs;  } +static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state) +{ +	snd_pcm_stream_lock_irq(substream); +	if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) +		substream->runtime->status->state = state; +	snd_pcm_stream_unlock_irq(substream); +} +  static int snd_pcm_hw_params(struct snd_pcm_substream *substream,  			     struct snd_pcm_hw_params *params)  { @@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,  		runtime->boundary *= 2;  	snd_pcm_timer_resolution_change(substream); -	runtime->status->state = SNDRV_PCM_STATE_SETUP; +	snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);  	if (pm_qos_request_active(&substream->latency_pm_qos_req))  		pm_qos_remove_request(&substream->latency_pm_qos_req); @@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,  	/* hardware might be unusable from this time,  	   so we force application to retry to set  	   the correct hardware parameter settings */ -	runtime->status->state = SNDRV_PCM_STATE_OPEN; +	snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);  	if (substream->ops->hw_free != NULL)  		substream->ops->hw_free(substream);  	return err; @@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)  		return -EBADFD;  	if (substream->ops->hw_free)  		result = substream->ops->hw_free(substream); -	runtime->status->state = SNDRV_PCM_STATE_OPEN; +	snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);  	pm_qos_remove_request(&substream->latency_pm_qos_req);  	return result;  } @@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	runtime->control->appl_ptr = runtime->status->hw_ptr; -	runtime->status->state = SNDRV_PCM_STATE_PREPARED; +	snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);  }  static struct action_ops snd_pcm_action_prepare = { @@ -1510,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,  		down_read(&snd_pcm_link_rwsem);  		snd_pcm_stream_lock_irq(substream);  		remove_wait_queue(&to_check->sleep, &wait); +		if (card->shutdown) { +			result = -ENODEV; +			break; +		}  		if (tout == 0) {  			if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)  				result = -ESTRPIPE; @@ -1634,6 +1646,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)  	write_unlock_irq(&snd_pcm_link_rwlock);  	up_write(&snd_pcm_link_rwsem);   _nolock: +	snd_card_unref(substream1->pcm->card);  	fput_light(file, fput_needed);  	if (res < 0)  		kfree(group); @@ -2108,7 +2121,10 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file)  		return err;  	pcm = snd_lookup_minor_data(iminor(inode),  				    SNDRV_DEVICE_TYPE_PCM_PLAYBACK); -	return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); +	err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); +	if (pcm) +		snd_card_unref(pcm->card); +	return err;  }  static int snd_pcm_capture_open(struct inode *inode, struct file *file) @@ -2119,7 +2135,10 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file)  		return err;  	pcm = snd_lookup_minor_data(iminor(inode),  				    SNDRV_DEVICE_TYPE_PCM_CAPTURE); -	return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); +	err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); +	if (pcm) +		snd_card_unref(pcm->card); +	return err;  }  static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) @@ -2156,6 +2175,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)  		mutex_unlock(&pcm->open_mutex);  		schedule();  		mutex_lock(&pcm->open_mutex); +		if (pcm->card->shutdown) { +			err = -ENODEV; +			break; +		}  		if (signal_pending(current)) {  			err = -ERESTARTSYS;  			break; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index ebf6e49ad3d..1bb95aeea08 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)  	if (rmidi == NULL)  		return -ENODEV; -	if (!try_module_get(rmidi->card->module)) +	if (!try_module_get(rmidi->card->module)) { +		snd_card_unref(rmidi->card);  		return -ENXIO; +	}  	mutex_lock(&rmidi->open_mutex);  	card = rmidi->card; @@ -422,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)  		mutex_unlock(&rmidi->open_mutex);  		schedule();  		mutex_lock(&rmidi->open_mutex); +		if (rmidi->card->shutdown) { +			err = -ENODEV; +			break; +		}  		if (signal_pending(current)) {  			err = -ERESTARTSYS;  			break; @@ -440,6 +446,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)  #endif  	file->private_data = rawmidi_file;  	mutex_unlock(&rmidi->open_mutex); +	snd_card_unref(rmidi->card);  	return 0;   __error: @@ -447,6 +454,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)   __error_card:  	mutex_unlock(&rmidi->open_mutex);  	module_put(rmidi->card->module); +	snd_card_unref(rmidi->card);  	return err;  } @@ -991,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun  			spin_unlock_irq(&runtime->lock);  			schedule();  			remove_wait_queue(&runtime->sleep, &wait); +			if (rfile->rmidi->card->shutdown) +				return -ENODEV;  			if (signal_pending(current))  				return result > 0 ? result : -ERESTARTSYS;  			if (!runtime->avail) @@ -1234,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,  			spin_unlock_irq(&runtime->lock);  			timeout = schedule_timeout(30 * HZ);  			remove_wait_queue(&runtime->sleep, &wait); +			if (rfile->rmidi->card->shutdown) +				return -ENODEV;  			if (signal_pending(current))  				return result > 0 ? result : -ERESTARTSYS;  			if (!runtime->avail && !timeout) @@ -1609,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)  static int snd_rawmidi_dev_disconnect(struct snd_device *device)  {  	struct snd_rawmidi *rmidi = device->device_data; +	int dir;  	mutex_lock(®ister_mutex); +	mutex_lock(&rmidi->open_mutex); +	wake_up(&rmidi->open_wait);  	list_del_init(&rmidi->list); +	for (dir = 0; dir < 2; dir++) { +		struct snd_rawmidi_substream *s; +		list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { +			if (s->runtime) +				wake_up(&s->runtime->sleep); +		} +	} +  #ifdef CONFIG_SND_OSSEMUL  	if (rmidi->ossreg) {  		if ((int)rmidi->device == midi_map[rmidi->card->number]) { @@ -1626,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)  	}  #endif /* CONFIG_SND_OSSEMUL */  	snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); +	mutex_unlock(&rmidi->open_mutex);  	mutex_unlock(®ister_mutex);  	return 0;  } diff --git a/sound/core/sound.c b/sound/core/sound.c index 643976000ce..70ccdab7415 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -98,6 +98,10 @@ static void snd_request_other(int minor)   *   * Checks that a minor device with the specified type is registered, and returns   * its user data pointer. + * + * This function increments the reference counter of the card instance + * if an associated instance with the given minor number and type is found. + * The caller must call snd_card_unref() appropriately later.   */  void *snd_lookup_minor_data(unsigned int minor, int type)  { @@ -108,9 +112,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type)  		return NULL;  	mutex_lock(&sound_mutex);  	mreg = snd_minors[minor]; -	if (mreg && mreg->type == type) +	if (mreg && mreg->type == type) {  		private_data = mreg->private_data; -	else +		if (private_data && mreg->card_ptr) +			atomic_inc(&mreg->card_ptr->refcount); +	} else  		private_data = NULL;  	mutex_unlock(&sound_mutex);  	return private_data; @@ -275,6 +281,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,  	preg->device = dev;  	preg->f_ops = f_ops;  	preg->private_data = private_data; +	preg->card_ptr = card;  	mutex_lock(&sound_mutex);  #ifdef CONFIG_SND_DYNAMIC_MINORS  	minor = snd_find_free_minor(type); diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index e9528333e36..726a49ac972 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -40,6 +40,9 @@  static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];  static DEFINE_MUTEX(sound_oss_mutex); +/* NOTE: This function increments the refcount of the associated card like + * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately + */  void *snd_lookup_oss_minor_data(unsigned int minor, int type)  {  	struct snd_minor *mreg; @@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type)  		return NULL;  	mutex_lock(&sound_oss_mutex);  	mreg = snd_oss_minors[minor]; -	if (mreg && mreg->type == type) +	if (mreg && mreg->type == type) {  		private_data = mreg->private_data; -	else +		if (private_data && mreg->card_ptr) +			atomic_inc(&mreg->card_ptr->refcount); +	} else  		private_data = NULL;  	mutex_unlock(&sound_oss_mutex);  	return private_data; @@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,  	preg->device = dev;  	preg->f_ops = f_ops;  	preg->private_data = private_data; +	preg->card_ptr = card;  	mutex_lock(&sound_oss_mutex);  	snd_oss_minors[minor] = preg;  	minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c index ef68d710d08..e04e750a77e 100644 --- a/sound/i2c/other/ak4113.c +++ b/sound/i2c/other/ak4113.c @@ -426,7 +426,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {  },  {  	.iface =	SNDRV_CTL_ELEM_IFACE_PCM, -	.name =		"IEC958 Preample Capture Default", +	.name =		"IEC958 Preamble Capture Default",  	.access =	SNDRV_CTL_ELEM_ACCESS_READ |  		SNDRV_CTL_ELEM_ACCESS_VOLATILE,  	.info =		snd_ak4113_spdif_pinfo, diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index 816e7d225fb..5bf4fca19e4 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c @@ -401,7 +401,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {  },  {  	.iface =	SNDRV_CTL_ELEM_IFACE_PCM, -	.name =		"IEC958 Preample Capture Default", +	.name =		"IEC958 Preamble Capture Default",  	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,  	.info =		snd_ak4114_spdif_pinfo,  	.get =		snd_ak4114_spdif_pget, diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index b4b2a51fc11..40e33c9f2b0 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c @@ -380,7 +380,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = {  },  {  	.iface =	SNDRV_CTL_ELEM_IFACE_PCM, -	.name =		"IEC958 Preample Capture Default", +	.name =		"IEC958 Preamble Capture Default",  	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,  	.info =		snd_ak4117_spdif_pinfo,  	.get =		snd_ak4117_spdif_pget, diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 3d1afb612b3..4a7ff4e8985 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -1286,7 +1286,6 @@ static int __devinit snd_miro_probe(struct snd_card *card)  	error = snd_card_miro_aci_detect(card, miro);  	if (error < 0) { -		snd_card_free(card);  		snd_printk(KERN_ERR "unable to detect aci chip\n");  		return -ENODEV;  	} diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 00f157a2cf6..5af3cb6b0c1 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -394,6 +394,8 @@ static int snd_als300_playback_open(struct snd_pcm_substream *substream)  	struct snd_als300_substream_data *data = kzalloc(sizeof(*data),  								GFP_KERNEL); +	if (!data) +		return -ENOMEM;  	snd_als300_dbgcallenter();  	chip->playback_substream = substream;  	runtime->hw = snd_als300_playback_hw; @@ -425,6 +427,8 @@ static int snd_als300_capture_open(struct snd_pcm_substream *substream)  	struct snd_als300_substream_data *data = kzalloc(sizeof(*data),  								GFP_KERNEL); +	if (!data) +		return -ENOMEM;  	snd_als300_dbgcallenter();  	chip->capture_substream = substream;  	runtime->hw = snd_als300_capture_hw; diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 5d0e568fdea..50169bcfd90 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -2655,6 +2655,8 @@ static struct ess_device_list pm_whitelist[] __devinitdata = {  	{ TYPE_MAESTRO2E, 0x1179 },  	{ TYPE_MAESTRO2E, 0x14c0 },	/* HP omnibook 4150 */  	{ TYPE_MAESTRO2E, 0x1558 }, +	{ TYPE_MAESTRO2E, 0x125d },	/* a PCI card, e.g. Terratec DMX */ +	{ TYPE_MAESTRO2, 0x125d },	/* a PCI card, e.g. SF64-PCE2 */  };  static struct ess_device_list mpu_blacklist[] __devinitdata = { diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 72b085ae7d4..cd2dbaf1be7 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -3563,6 +3563,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {  	/* Teradici */  	{ PCI_DEVICE(0x6549, 0x1200),  	  .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT }, +	{ PCI_DEVICE(0x6549, 0x2200), +	  .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },  	/* Creative X-Fi (CA0110-IBG) */  	/* CTHDA chips */  	{ PCI_DEVICE(0x1102, 0x0010), diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index cdd43eadbc6..1eeba738666 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -545,6 +545,7 @@ static int ad198x_build_pcms(struct hda_codec *codec)  	if (spec->multiout.dig_out_nid) {  		info++;  		codec->num_pcms++; +		codec->spdif_status_reset = 1;  		info->name = "AD198x Digital";  		info->pcm_type = HDA_PCM_TYPE_SPDIF;  		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 61a71131711..d5f3a26d608 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -101,8 +101,8 @@ enum {  #define CS420X_VENDOR_NID	0x11  #define CS_DIG_OUT1_PIN_NID	0x10  #define CS_DIG_OUT2_PIN_NID	0x15 -#define CS_DMIC1_PIN_NID	0x12 -#define CS_DMIC2_PIN_NID	0x0e +#define CS_DMIC1_PIN_NID	0x0e +#define CS_DMIC2_PIN_NID	0x12  /* coef indices */  #define IDX_SPDIF_STAT		0x0000 @@ -1079,14 +1079,18 @@ static void init_input(struct hda_codec *codec)  			cs_automic(codec, NULL);  		coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ +		cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); + +		coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG);  		if (is_active_pin(codec, CS_DMIC2_PIN_NID)) -			coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */ +			coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */  		if (is_active_pin(codec, CS_DMIC1_PIN_NID)) -			coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off +			coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off  					 * No effect if SPDIF_OUT2 is  					 * selected in IDX_SPDIF_CTL.  					*/ -		cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); + +		cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef);  	} else {  		if (spec->mic_detect)  			cs_automic(codec, NULL); @@ -1107,7 +1111,7 @@ static const struct hda_verb cs_coef_init_verbs[] = {  	  | 0x0400 /* Disable Coefficient Auto increment */  	  )},  	/* Beep */ -	{0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG}, +	{0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG},  	{0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */  	{} /* terminator */ @@ -1728,8 +1732,7 @@ static int cs421x_mux_enum_put(struct snd_kcontrol *kcontrol,  } -static struct snd_kcontrol_new cs421x_capture_source = { - +static const struct snd_kcontrol_new cs421x_capture_source = {  	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,  	.name = "Capture Source",  	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -1946,7 +1949,7 @@ static int cs421x_suspend(struct hda_codec *codec)  }  #endif -static struct hda_codec_ops cs421x_patch_ops = { +static const struct hda_codec_ops cs421x_patch_ops = {  	.build_controls = cs421x_build_controls,  	.build_pcms = cs_build_pcms,  	.init = cs421x_init, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 48d9d609f89..c0ce3b1f04b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5677,6 +5677,7 @@ static const struct hda_verb alc268_beep_init_verbs[] = {  enum {  	ALC268_FIXUP_INV_DMIC, +	ALC268_FIXUP_HP_EAPD,  };  static const struct alc_fixup alc268_fixups[] = { @@ -5684,10 +5685,26 @@ static const struct alc_fixup alc268_fixups[] = {  		.type = ALC_FIXUP_FUNC,  		.v.func = alc_fixup_inv_dmic_0x12,  	}, +	[ALC268_FIXUP_HP_EAPD] = { +		.type = ALC_FIXUP_VERBS, +		.v.verbs = (const struct hda_verb[]) { +			{0x15, AC_VERB_SET_EAPD_BTLENABLE, 0}, +			{} +		} +	},  };  static const struct alc_model_fixup alc268_fixup_models[] = {  	{.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"}, +	{.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"}, +	{} +}; + +static const struct snd_pci_quirk alc268_fixup_tbl[] = { +	/* below is codec SSID since multiple Toshiba laptops have the +	 * same PCI SSID 1179:ff00 +	 */ +	SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),  	{}  }; @@ -5722,7 +5739,7 @@ static int patch_alc268(struct hda_codec *codec)  	spec = codec->spec; -	alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups); +	alc_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);  	alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);  	/* automatic parse from the BIOS config */ @@ -5823,7 +5840,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)  	return alc_parse_auto_config(codec, alc269_ignore, ssids);  } -static void alc269_toggle_power_output(struct hda_codec *codec, int power_up) +static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)  {  	int val = alc_read_coef_idx(codec, 0x04);  	if (power_up) @@ -5840,10 +5857,10 @@ static void alc269_shutup(struct hda_codec *codec)  	if (spec->codec_variant != ALC269_TYPE_ALC269VB)  		return; -	if ((alc_get_coef0(codec) & 0x00ff) == 0x017) -		alc269_toggle_power_output(codec, 0); -	if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { -		alc269_toggle_power_output(codec, 0); +	if (spec->codec_variant == ALC269_TYPE_ALC269VB) +		alc269vb_toggle_power_output(codec, 0); +	if (spec->codec_variant == ALC269_TYPE_ALC269VB && +			(alc_get_coef0(codec) & 0x00ff) == 0x018) {  		msleep(150);  	}  } @@ -5853,24 +5870,22 @@ static int alc269_resume(struct hda_codec *codec)  {  	struct alc_spec *spec = codec->spec; -	if (spec->codec_variant == ALC269_TYPE_ALC269VB || +	if (spec->codec_variant == ALC269_TYPE_ALC269VB) +		alc269vb_toggle_power_output(codec, 0); +	if (spec->codec_variant == ALC269_TYPE_ALC269VB &&  			(alc_get_coef0(codec) & 0x00ff) == 0x018) { -		alc269_toggle_power_output(codec, 0);  		msleep(150);  	}  	codec->patch_ops.init(codec); -	if (spec->codec_variant == ALC269_TYPE_ALC269VB || +	if (spec->codec_variant == ALC269_TYPE_ALC269VB) +		alc269vb_toggle_power_output(codec, 1); +	if (spec->codec_variant == ALC269_TYPE_ALC269VB &&  			(alc_get_coef0(codec) & 0x00ff) == 0x017) { -		alc269_toggle_power_output(codec, 1);  		msleep(200);  	} -	if (spec->codec_variant == ALC269_TYPE_ALC269VB || -			(alc_get_coef0(codec) & 0x00ff) == 0x018) -		alc269_toggle_power_output(codec, 1); -  	snd_hda_codec_resume_amp(codec);  	snd_hda_codec_resume_cache(codec);  	hda_call_check_power_status(codec, 0x01); @@ -6188,6 +6203,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {  	SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),  	SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK),  	SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK), +	SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),  	SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),  	SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),  	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), @@ -7061,6 +7077,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {  	  .patch = patch_alc662 },  	{ .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },  	{ .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, +	{ .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },  	{ .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },  	{ .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },  	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, @@ -7078,6 +7095,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {  	{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },  	{ .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },  	{ .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 }, +	{ .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 },  	{} /* terminator */  }; diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 770013ff556..9ba8af05617 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1763,6 +1763,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {  			  "HP", STAC_HP_ZEPHYR),  	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660,  			  "HP Mini", STAC_92HD83XXX_HP_LED), +	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x144E, +			  "HP Pavilion dv5", STAC_92HD83XXX_HP_INV_LED),  	{} /* terminator */  }; diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 72a2f60b087..019e1a00414 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1809,11 +1809,11 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec)  {  	struct via_spec *spec = codec->spec;  	const struct auto_pin_cfg *cfg = &spec->autocfg; -	int i, dac_num; +	int i;  	hda_nid_t nid; +	spec->multiout.num_dacs = 0;  	spec->multiout.dac_nids = spec->private_dac_nids; -	dac_num = 0;  	for (i = 0; i < cfg->line_outs; i++) {  		hda_nid_t dac = 0;  		nid = cfg->line_out_pins[i]; @@ -1824,16 +1824,13 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec)  		if (!i && parse_output_path(codec, nid, dac, 1,  					    &spec->out_mix_path))  			dac = spec->out_mix_path.path[0]; -		if (dac) { -			spec->private_dac_nids[i] = dac; -			dac_num++; -		} +		if (dac) +			spec->private_dac_nids[spec->multiout.num_dacs++] = dac;  	}  	if (!spec->out_path[0].depth && spec->out_mix_path.depth) {  		spec->out_path[0] = spec->out_mix_path;  		spec->out_mix_path.depth = 0;  	} -	spec->multiout.num_dacs = dac_num;  	return 0;  } @@ -3628,6 +3625,7 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)   */  enum {  	VIA_FIXUP_INTMIC_BOOST, +	VIA_FIXUP_ASUS_G75,  };  static void via_fixup_intmic_boost(struct hda_codec *codec, @@ -3642,13 +3640,35 @@ static const struct hda_fixup via_fixups[] = {  		.type = HDA_FIXUP_FUNC,  		.v.func = via_fixup_intmic_boost,  	}, +	[VIA_FIXUP_ASUS_G75] = { +		.type = HDA_FIXUP_PINS, +		.v.pins = (const struct hda_pintbl[]) { +			/* set 0x24 and 0x33 as speakers */ +			{ 0x24, 0x991301f0 }, +			{ 0x33, 0x991301f1 }, /* subwoofer */ +			{ } +		} +	},  };  static const struct snd_pci_quirk vt2002p_fixups[] = { +	SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),  	SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),  	{}  }; +/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e + * Replace this with mixer NID 0x1c + */ +static void fix_vt1802_connections(struct hda_codec *codec) +{ +	static hda_nid_t conn_24[] = { 0x14, 0x1c }; +	static hda_nid_t conn_33[] = { 0x1c }; + +	snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24); +	snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33); +} +  /* patch for vt2002P */  static int patch_vt2002P(struct hda_codec *codec)  { @@ -3663,6 +3683,8 @@ static int patch_vt2002P(struct hda_codec *codec)  	spec->aa_mix_nid = 0x21;  	override_mic_boost(codec, 0x2b, 0, 3, 40);  	override_mic_boost(codec, 0x29, 0, 3, 40); +	if (spec->codec_type == VT1802) +		fix_vt1802_connections(codec);  	add_secret_dac_path(codec);  	snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups); diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 3050a527925..245d874891b 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -2859,7 +2859,12 @@ static int snd_vt1724_resume(struct device *dev)  		ice->set_spdif_clock(ice, 0);  	} else {  		/* internal on-card clock */ -		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); +		int rate; +		if (ice->cur_rate) +			rate = ice->cur_rate; +		else +			rate = ice->pro_rate_default; +		snd_vt1724_set_pro_rate(ice, rate, 1);  	}  	update_spdif_bits(ice, ice->pm_saved_spdif_ctrl); diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index b12308b5ba2..748e36c6660 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -971,6 +971,7 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);  static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);  static int hdspm_autosync_ref(struct hdspm *hdspm);  static int snd_hdspm_set_defaults(struct hdspm *hdspm); +static int hdspm_system_clock_mode(struct hdspm *hdspm);  static void hdspm_set_sgbuf(struct hdspm *hdspm,  			    struct snd_pcm_substream *substream,  			     unsigned int reg, int channels); @@ -1989,10 +1990,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm)  	rate = hdspm_calc_dds_value(hdspm, period);  	if (rate > 207000) { -		/* Unreasonable high sample rate as seen on PCI MADI cards. -		 * Use the cached value instead. -		 */ -		rate = hdspm->system_sample_rate; +		/* Unreasonable high sample rate as seen on PCI MADI cards. */ +		if (0 == hdspm_system_clock_mode(hdspm)) { +			/* master mode, return internal sample rate */ +			rate = hdspm->system_sample_rate; +		} else { +			/* slave mode, return external sample rate */ +			rate = hdspm_external_sample_rate(hdspm); +		}  	}  	return rate; @@ -2000,12 +2005,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm)  #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .name = xname, \ -  .index = xindex, \ -  .access = SNDRV_CTL_ELEM_ACCESS_READ, \ -  .info = snd_hdspm_info_system_sample_rate, \ -  .get = snd_hdspm_get_system_sample_rate \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.name = xname, \ +	.index = xindex, \ +	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ +		SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ +	.info = snd_hdspm_info_system_sample_rate, \ +	.put = snd_hdspm_put_system_sample_rate, \ +	.get = snd_hdspm_get_system_sample_rate \  }  static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol, @@ -2030,6 +2037,16 @@ static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,  	return 0;  } +static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol, +					    struct snd_ctl_elem_value * +					    ucontrol) +{ +	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); + +	hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]); +	return 0; +} +  /**   * Returns the WordClock sample rate class for the given card. @@ -2163,6 +2180,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,  				hdspm_get_s1_sample_rate(hdspm,  						kcontrol->private_value-1);  		} +		break;  	case AIO:  		switch (kcontrol->private_value) { @@ -2183,6 +2201,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,  				hdspm_get_s1_sample_rate(hdspm,  						ucontrol->id.index-1);  		} +		break;  	case AES32: @@ -2204,8 +2223,23 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,  				hdspm_get_s1_sample_rate(hdspm,  						kcontrol->private_value-1);  			break; +		} +		break; +	case MADI: +	case MADIface: +		{ +			int rate = hdspm_external_sample_rate(hdspm); +			int i, selected_rate = 0; +			for (i = 1; i < 10; i++) +				if (HDSPM_bit2freq(i) == rate) { +					selected_rate = i; +					break; +				} +			ucontrol->value.enumerated.item[0] = selected_rate;  		} +		break; +  	default:  		break;  	} @@ -2430,7 +2464,7 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,  #define HDSPM_PREF_SYNC_REF(xname, xindex) \ -{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \  	.name = xname, \  	.index = xindex, \  	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ @@ -2766,12 +2800,12 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,  #define HDSPM_AUTOSYNC_REF(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .name = xname, \ -  .index = xindex, \ -  .access = SNDRV_CTL_ELEM_ACCESS_READ, \ -  .info = snd_hdspm_info_autosync_ref, \ -  .get = snd_hdspm_get_autosync_ref, \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.name = xname, \ +	.index = xindex, \ +	.access = SNDRV_CTL_ELEM_ACCESS_READ, \ +	.info = snd_hdspm_info_autosync_ref, \ +	.get = snd_hdspm_get_autosync_ref, \  }  static int hdspm_autosync_ref(struct hdspm *hdspm) @@ -2855,12 +2889,12 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,  #define HDSPM_LINE_OUT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .name = xname, \ -  .index = xindex, \ -  .info = snd_hdspm_info_line_out, \ -  .get = snd_hdspm_get_line_out, \ -  .put = snd_hdspm_put_line_out \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.name = xname, \ +	.index = xindex, \ +	.info = snd_hdspm_info_line_out, \ +	.get = snd_hdspm_get_line_out, \ +	.put = snd_hdspm_put_line_out \  }  static int hdspm_line_out(struct hdspm * hdspm) @@ -2912,12 +2946,12 @@ static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,  #define HDSPM_TX_64(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .name = xname, \ -  .index = xindex, \ -  .info = snd_hdspm_info_tx_64, \ -  .get = snd_hdspm_get_tx_64, \ -  .put = snd_hdspm_put_tx_64 \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.name = xname, \ +	.index = xindex, \ +	.info = snd_hdspm_info_tx_64, \ +	.get = snd_hdspm_get_tx_64, \ +	.put = snd_hdspm_put_tx_64 \  }  static int hdspm_tx_64(struct hdspm * hdspm) @@ -2968,12 +3002,12 @@ static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,  #define HDSPM_C_TMS(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .name = xname, \ -  .index = xindex, \ -  .info = snd_hdspm_info_c_tms, \ -  .get = snd_hdspm_get_c_tms, \ -  .put = snd_hdspm_put_c_tms \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.name = xname, \ +	.index = xindex, \ +	.info = snd_hdspm_info_c_tms, \ +	.get = snd_hdspm_get_c_tms, \ +	.put = snd_hdspm_put_c_tms \  }  static int hdspm_c_tms(struct hdspm * hdspm) @@ -3024,12 +3058,12 @@ static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,  #define HDSPM_SAFE_MODE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .name = xname, \ -  .index = xindex, \ -  .info = snd_hdspm_info_safe_mode, \ -  .get = snd_hdspm_get_safe_mode, \ -  .put = snd_hdspm_put_safe_mode \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.name = xname, \ +	.index = xindex, \ +	.info = snd_hdspm_info_safe_mode, \ +	.get = snd_hdspm_get_safe_mode, \ +	.put = snd_hdspm_put_safe_mode \  }  static int hdspm_safe_mode(struct hdspm * hdspm) @@ -3080,12 +3114,12 @@ static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,  #define HDSPM_EMPHASIS(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .name = xname, \ -  .index = xindex, \ -  .info = snd_hdspm_info_emphasis, \ -  .get = snd_hdspm_get_emphasis, \ -  .put = snd_hdspm_put_emphasis \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.name = xname, \ +	.index = xindex, \ +	.info = snd_hdspm_info_emphasis, \ +	.get = snd_hdspm_get_emphasis, \ +	.put = snd_hdspm_put_emphasis \  }  static int hdspm_emphasis(struct hdspm * hdspm) @@ -3136,12 +3170,12 @@ static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,  #define HDSPM_DOLBY(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .name = xname, \ -  .index = xindex, \ -  .info = snd_hdspm_info_dolby, \ -  .get = snd_hdspm_get_dolby, \ -  .put = snd_hdspm_put_dolby \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.name = xname, \ +	.index = xindex, \ +	.info = snd_hdspm_info_dolby, \ +	.get = snd_hdspm_get_dolby, \ +	.put = snd_hdspm_put_dolby \  }  static int hdspm_dolby(struct hdspm * hdspm) @@ -3192,12 +3226,12 @@ static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,  #define HDSPM_PROFESSIONAL(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .name = xname, \ -  .index = xindex, \ -  .info = snd_hdspm_info_professional, \ -  .get = snd_hdspm_get_professional, \ -  .put = snd_hdspm_put_professional \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.name = xname, \ +	.index = xindex, \ +	.info = snd_hdspm_info_professional, \ +	.get = snd_hdspm_get_professional, \ +	.put = snd_hdspm_put_professional \  }  static int hdspm_professional(struct hdspm * hdspm) @@ -3247,12 +3281,12 @@ static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,  }  #define HDSPM_INPUT_SELECT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .name = xname, \ -  .index = xindex, \ -  .info = snd_hdspm_info_input_select, \ -  .get = snd_hdspm_get_input_select, \ -  .put = snd_hdspm_put_input_select \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.name = xname, \ +	.index = xindex, \ +	.info = snd_hdspm_info_input_select, \ +	.get = snd_hdspm_get_input_select, \ +	.put = snd_hdspm_put_input_select \  }  static int hdspm_input_select(struct hdspm * hdspm) @@ -3319,12 +3353,12 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,  #define HDSPM_DS_WIRE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .name = xname, \ -  .index = xindex, \ -  .info = snd_hdspm_info_ds_wire, \ -  .get = snd_hdspm_get_ds_wire, \ -  .put = snd_hdspm_put_ds_wire \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.name = xname, \ +	.index = xindex, \ +	.info = snd_hdspm_info_ds_wire, \ +	.get = snd_hdspm_get_ds_wire, \ +	.put = snd_hdspm_put_ds_wire \  }  static int hdspm_ds_wire(struct hdspm * hdspm) @@ -3391,12 +3425,12 @@ static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,  #define HDSPM_QS_WIRE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .name = xname, \ -  .index = xindex, \ -  .info = snd_hdspm_info_qs_wire, \ -  .get = snd_hdspm_get_qs_wire, \ -  .put = snd_hdspm_put_qs_wire \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.name = xname, \ +	.index = xindex, \ +	.info = snd_hdspm_info_qs_wire, \ +	.get = snd_hdspm_get_qs_wire, \ +	.put = snd_hdspm_put_qs_wire \  }  static int hdspm_qs_wire(struct hdspm * hdspm) @@ -3563,15 +3597,15 @@ static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,  }  #define HDSPM_MIXER(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ -  .name = xname, \ -  .index = xindex, \ -  .device = 0, \ -  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ -		 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ -  .info = snd_hdspm_info_mixer, \ -  .get = snd_hdspm_get_mixer, \ -  .put = snd_hdspm_put_mixer \ +{	.iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ +	.name = xname, \ +	.index = xindex, \ +	.device = 0, \ +	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ +		SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ +	.info = snd_hdspm_info_mixer, \ +	.get = snd_hdspm_get_mixer, \ +	.put = snd_hdspm_put_mixer \  }  static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol, @@ -3670,12 +3704,12 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,  */  #define HDSPM_PLAYBACK_MIXER \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \ -		 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ -  .info = snd_hdspm_info_playback_mixer, \ -  .get = snd_hdspm_get_playback_mixer, \ -  .put = snd_hdspm_put_playback_mixer \ +{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \ +		SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ +	.info = snd_hdspm_info_playback_mixer, \ +	.get = snd_hdspm_get_playback_mixer, \ +	.put = snd_hdspm_put_playback_mixer \  }  static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol, @@ -3851,12 +3885,17 @@ static int hdspm_sync_in_sync_check(struct hdspm *hdspm)  		break;  	case MADI: -	case AES32: -		status = hdspm_read(hdspm, HDSPM_statusRegister2); +		status = hdspm_read(hdspm, HDSPM_statusRegister);  		lock = (status & HDSPM_syncInLock) ? 1 : 0;  		sync = (status & HDSPM_syncInSync) ? 1 : 0;  		break; +	case AES32: +		status = hdspm_read(hdspm, HDSPM_statusRegister2); +		lock = (status & 0x100000) ? 1 : 0; +		sync = (status & 0x200000) ? 1 : 0; +		break; +  	case MADIface:  		break;  	} @@ -3940,8 +3979,10 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,  		case 8: /* SYNC IN */  			val = hdspm_sync_in_sync_check(hdspm); break;  		default: -			val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); +			val = hdspm_s1_sync_check(hdspm, +					kcontrol->private_value-1);  		} +		break;  	case AIO:  		switch (kcontrol->private_value) { @@ -3954,6 +3995,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,  		default:  			val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);  		} +		break;  	case MADI:  		switch (kcontrol->private_value) { @@ -3966,6 +4008,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,  		case 3: /* SYNC_IN */  			val = hdspm_sync_in_sync_check(hdspm); break;  		} +		break;  	case MADIface:  		val = hdspm_madi_sync_check(hdspm); /* MADI */ @@ -3983,6 +4026,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,  			 val = hdspm_aes_sync_check(hdspm,  					 kcontrol->private_value-1);  		} +		break;  	} @@ -4427,9 +4471,10 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {  	HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),  	HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),  	HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), +	HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),  	HDSPM_SYNC_CHECK("WC SyncCheck", 0),  	HDSPM_SYNC_CHECK("MADI SyncCheck", 1), -	HDSPM_SYNC_CHECK("TCO SyncCHeck", 2), +	HDSPM_SYNC_CHECK("TCO SyncCheck", 2),  	HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),  	HDSPM_LINE_OUT("Line Out", 0),  	HDSPM_TX_64("TX 64 channels mode", 0), @@ -4855,7 +4900,7 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,  		insel = "Coaxial";  		break;  	default: -		insel = "Unkown"; +		insel = "Unknown";  	}  	snd_iprintf(buffer, diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 61599298fb2..4d8db3685e9 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -763,7 +763,7 @@ static int cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,  	if ((freq >= CS42L52_MIN_CLK) && (freq <= CS42L52_MAX_CLK)) {  		cs42l52->sysclk = freq;  	} else { -		dev_err(codec->dev, "Invalid freq paramter\n"); +		dev_err(codec->dev, "Invalid freq parameter\n");  		return -EINVAL;  	}  	return 0; diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 2b2dadc54da..b2b2b37131b 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1045,6 +1045,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,  		      struct snd_kcontrol *kcontrol, int event)  {  	struct snd_soc_codec *codec = w->codec; +	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);  	struct wm8994 *control = codec->control_data;  	int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA;  	int i; @@ -1063,6 +1064,10 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,  	switch (event) {  	case SND_SOC_DAPM_PRE_PMU: +		/* Don't enable timeslot 2 if not in use */ +		if (wm8994->channels[0] <= 2) +			mask &= ~(WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA); +  		val = snd_soc_read(codec, WM8994_AIF1_CONTROL_1);  		if ((val & WM8994_AIF1ADCL_SRC) &&  		    (val & WM8994_AIF1ADCR_SRC)) @@ -2687,7 +2692,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,  		return -EINVAL;  	} -	bclk_rate = params_rate(params) * 4; +	bclk_rate = params_rate(params);  	switch (params_format(params)) {  	case SNDRV_PCM_FORMAT_S16_LE:  		bclk_rate *= 16; @@ -2708,6 +2713,17 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,  		return -EINVAL;  	} +	wm8994->channels[id] = params_channels(params); +	switch (params_channels(params)) { +	case 1: +	case 2: +		bclk_rate *= 2; +		break; +	default: +		bclk_rate *= 4; +		break; +	} +  	/* Try to find an appropriate sample rate; look for an exact match. */  	for (i = 0; i < ARRAY_SIZE(srs); i++)  		if (srs[i].rate == params_rate(params)) @@ -3706,7 +3722,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)  	} while (count--);  	if (count == 0) -		dev_warn(codec->dev, "No impedence range reported for jack\n"); +		dev_warn(codec->dev, "No impedance range reported for jack\n");  #ifndef CONFIG_SND_SOC_WM8994_MODULE  	trace_snd_soc_jack_irq(dev_name(codec->dev)); diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index f142ec198db..ccbce5791e9 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -77,6 +77,7 @@ struct wm8994_priv {  	int sysclk_rate[2];  	int mclk[2];  	int aifclk[2]; +	int channels[2];  	struct wm8994_fll_config fll[2], fll_suspend[2];  	struct completion fll_locked[2];  	bool fll_locked_irq; diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 68f2cd1a920..5a6aeaf552a 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c @@ -464,9 +464,9 @@ static __devinit int asoc_dmic_probe(struct platform_device *pdev)  	mutex_init(&dmic->mutex); -	dmic->fclk = clk_get(dmic->dev, "dmic_fck"); +	dmic->fclk = clk_get(dmic->dev, "fck");  	if (IS_ERR(dmic->fclk)) { -		dev_err(dmic->dev, "cant get dmic_fck\n"); +		dev_err(dmic->dev, "cant get fck\n");  		return -ENODEV;  	} diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 677b567935f..1ff6bb9ade5 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c @@ -21,15 +21,14 @@  #include <linux/clk.h>  #include <linux/platform_device.h> +#include <linux/gpio.h>  #include <sound/core.h>  #include <sound/pcm.h>  #include <sound/soc.h>  #include <asm/mach-types.h> -#include <mach/hardware.h> -#include <mach/gpio.h> -#include <mach/board-zoom.h>  #include <linux/platform_data/asoc-ti-mcbsp.h> +#include <linux/platform_data/gpio-omap.h>  /* Register descriptions for twl4030 codec part */  #include <linux/mfd/twl4030-audio.h> diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 356611d9654..54f7e25b6f7 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -57,6 +57,20 @@ static struct snd_soc_card mop500_card = {  	.num_links = ARRAY_SIZE(mop500_dai_links),  }; +static void mop500_of_node_put(void) +{ +	int i; + +	for (i = 0; i < 2; i++) { +		if (mop500_dai_links[i].cpu_of_node) +			of_node_put((struct device_node *) +				mop500_dai_links[i].cpu_of_node); +		if (mop500_dai_links[i].codec_of_node) +			of_node_put((struct device_node *) +				mop500_dai_links[i].codec_of_node); +	} +} +  static int __devinit mop500_of_probe(struct platform_device *pdev,  				struct device_node *np)  { @@ -69,6 +83,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,  	if (!(msp_np[0] && msp_np[1] && codec_np)) {  		dev_err(&pdev->dev, "Phandle missing or invalid\n"); +		mop500_of_node_put();  		return -EINVAL;  	} @@ -83,6 +98,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,  	return 0;  } +  static int __devinit mop500_probe(struct platform_device *pdev)  {  	struct device_node *np = pdev->dev.of_node; @@ -128,6 +144,7 @@ static int __devexit mop500_remove(struct platform_device *pdev)  	snd_soc_unregister_card(mop500_card);  	mop500_ab8500_remove(mop500_card); +	mop500_of_node_put();  	return 0;  } diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index b7c996e7757..a26c6bf0a29 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -18,6 +18,7 @@  #include <linux/pinctrl/consumer.h>  #include <linux/delay.h>  #include <linux/slab.h> +#include <linux/io.h>  #include <linux/of.h>  #include <mach/hardware.h> @@ -697,14 +698,11 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,  			platform_data = devm_kzalloc(&pdev->dev,  				sizeof(struct msp_i2s_platform_data), GFP_KERNEL);  			if (!platform_data) -				ret = -ENOMEM; +				return -ENOMEM;  		}  	} else  		if (!platform_data) -			ret = -EINVAL; - -	if (ret) -		goto err_res; +			return -EINVAL;  	dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__,  		pdev->name, platform_data->id); diff --git a/sound/usb/card.c b/sound/usb/card.c index 561bb74fd36..282f0fc9fed 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,  	}  	mutex_init(&chip->mutex); -	mutex_init(&chip->shutdown_mutex); +	init_rwsem(&chip->shutdown_rwsem);  	chip->index = idx;  	chip->dev = dev;  	chip->card = card; @@ -560,7 +560,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,  	card = chip->card;  	mutex_lock(®ister_mutex); -	mutex_lock(&chip->shutdown_mutex); +	down_write(&chip->shutdown_rwsem);  	chip->shutdown = 1;  	chip->num_interfaces--;  	if (chip->num_interfaces <= 0) { @@ -582,11 +582,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,  			snd_usb_mixer_disconnect(p);  		}  		usb_chip[chip->index] = NULL; -		mutex_unlock(&chip->shutdown_mutex); +		up_write(&chip->shutdown_rwsem);  		mutex_unlock(®ister_mutex);  		snd_card_free_when_closed(card);  	} else { -		mutex_unlock(&chip->shutdown_mutex); +		up_write(&chip->shutdown_rwsem);  		mutex_unlock(®ister_mutex);  	}  } @@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)  {  	int err = -ENODEV; +	down_read(&chip->shutdown_rwsem);  	if (!chip->shutdown && !chip->probing)  		err = usb_autopm_get_interface(chip->pm_intf); +	up_read(&chip->shutdown_rwsem);  	return err;  }  void snd_usb_autosuspend(struct snd_usb_audio *chip)  { +	down_read(&chip->shutdown_rwsem);  	if (!chip->shutdown && !chip->probing)  		usb_autopm_put_interface(chip->pm_intf); +	up_read(&chip->shutdown_rwsem);  }  static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) diff --git a/sound/usb/card.h b/sound/usb/card.h index afa4f9e9b27..814cb357ff8 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -126,6 +126,7 @@ struct snd_usb_substream {  	struct snd_usb_endpoint *sync_endpoint;  	unsigned long flags;  	bool need_setup_ep;		/* (re)configure EP at prepare? */ +	unsigned int speed;		/* USB_SPEED_XXX */  	u64 formats;			/* format bitmasks (all or'ed) */  	unsigned int num_formats;		/* number of supported audio formats (list) */ diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 7f78c6d782b..34de6f2faf6 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -35,6 +35,7 @@  #define EP_FLAG_ACTIVATED	0  #define EP_FLAG_RUNNING		1 +#define EP_FLAG_STOPPING	2  /*   * snd_usb_endpoint is a model that abstracts everything related to an @@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)  	if (alive)  		snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n",  					alive, ep->ep_num); +	clear_bit(EP_FLAG_STOPPING, &ep->flags);  	return 0;  } +/* sync the pending stop operation; + * this function itself doesn't trigger the stop operation + */ +void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) +{ +	if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags)) +		wait_clear_urbs(ep); +} +  /*   * unlink active urbs.   */ @@ -918,6 +929,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,  		if (wait)  			wait_clear_urbs(ep); +		else +			set_bit(EP_FLAG_STOPPING, &ep->flags);  	}  } diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index 6376ccf10fd..3d4c9705041 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -19,6 +19,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,  int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);  void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,  			   int force, int can_sleep, int wait); +void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);  int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);  int  snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);  void snd_usb_endpoint_free(struct list_head *head); diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index fe56c9da38e..298070e8f2d 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v  	unsigned char buf[2];  	int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;  	int timeout = 10; -	int err; +	int idx = 0, err;  	err = snd_usb_autoresume(cval->mixer->chip);  	if (err < 0)  		return -EIO; +	down_read(&chip->shutdown_rwsem);  	while (timeout-- > 0) { +		if (chip->shutdown) +			break; +		idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);  		if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,  				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -				    validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), -				    buf, val_len) >= val_len) { +				    validx, idx, buf, val_len) >= val_len) {  			*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); -			snd_usb_autosuspend(cval->mixer->chip); -			return 0; +			err = 0; +			goto out;  		}  	} -	snd_usb_autosuspend(cval->mixer->chip);  	snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", -		    request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); -	return -EINVAL; +		    request, validx, idx, cval->val_type); +	err = -EINVAL; + + out: +	up_read(&chip->shutdown_rwsem); +	snd_usb_autosuspend(cval->mixer->chip); +	return err;  }  static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) @@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v  	struct snd_usb_audio *chip = cval->mixer->chip;  	unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */  	unsigned char *val; -	int ret, size; +	int idx = 0, ret, size;  	__u8 bRequest;  	if (request == UAC_GET_CUR) { @@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v  	if (ret)  		goto error; -	ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, +	down_read(&chip->shutdown_rwsem); +	if (chip->shutdown) +		ret = -ENODEV; +	else { +		idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); +		ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,  			      USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -			      validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), -			      buf, size); +			      validx, idx, buf, size); +	} +	up_read(&chip->shutdown_rwsem);  	snd_usb_autosuspend(chip);  	if (ret < 0) {  error:  		snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", -			   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); +			   request, validx, idx, cval->val_type);  		return ret;  	} @@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,  {  	struct snd_usb_audio *chip = cval->mixer->chip;  	unsigned char buf[2]; -	int val_len, err, timeout = 10; +	int idx = 0, val_len, err, timeout = 10;  	if (cval->mixer->protocol == UAC_VERSION_1) {  		val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; @@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,  	err = snd_usb_autoresume(chip);  	if (err < 0)  		return -EIO; -	while (timeout-- > 0) +	down_read(&chip->shutdown_rwsem); +	while (timeout-- > 0) { +		if (chip->shutdown) +			break; +		idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);  		if (snd_usb_ctl_msg(chip->dev,  				    usb_sndctrlpipe(chip->dev, 0), request,  				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, -				    validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), -				    buf, val_len) >= 0) { -			snd_usb_autosuspend(chip); -			return 0; +				    validx, idx, buf, val_len) >= 0) { +			err = 0; +			goto out;  		} -	snd_usb_autosuspend(chip); +	}  	snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", -		    request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); -	return -EINVAL; +		    request, validx, idx, cval->val_type, buf[0], buf[1]); +	err = -EINVAL; + + out: +	up_read(&chip->shutdown_rwsem); +	snd_usb_autosuspend(chip); +	return err;  }  static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 690000db0ec..ae2b7143522 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e  	if (value > 1)  		return -EINVAL;  	changed = value != mixer->audigy2nx_leds[index]; +	down_read(&mixer->chip->shutdown_rwsem); +	if (mixer->chip->shutdown) { +		err = -ENODEV; +		goto out; +	}  	if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042))  		err = snd_usb_ctl_msg(mixer->chip->dev,  			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, @@ -299,6 +304,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e  			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,  			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,  			      value, index + 2, NULL, 0); + out: +	up_read(&mixer->chip->shutdown_rwsem);  	if (err < 0)  		return err;  	mixer->audigy2nx_leds[index] = value; @@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,  	for (i = 0; jacks[i].name; ++i) {  		snd_iprintf(buffer, "%s: ", jacks[i].name); -		err = snd_usb_ctl_msg(mixer->chip->dev, +		down_read(&mixer->chip->shutdown_rwsem); +		if (mixer->chip->shutdown) +			err = 0; +		else +			err = snd_usb_ctl_msg(mixer->chip->dev,  				      usb_rcvctrlpipe(mixer->chip->dev, 0),  				      UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |  				      USB_RECIP_INTERFACE, 0,  				      jacks[i].unitid << 8, buf, 3); +		up_read(&mixer->chip->shutdown_rwsem);  		if (err == 3 && (buf[0] == 3 || buf[0] == 6))  			snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);  		else @@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,  	else  		new_status = old_status & ~0x02;  	changed = new_status != old_status; -	err = snd_usb_ctl_msg(mixer->chip->dev, +	down_read(&mixer->chip->shutdown_rwsem); +	if (mixer->chip->shutdown) +		err = -ENODEV; +	else +		err = snd_usb_ctl_msg(mixer->chip->dev,  			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,  			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,  			      50, 0, &new_status, 1); +	up_read(&mixer->chip->shutdown_rwsem);  	if (err < 0)  		return err;  	mixer->xonar_u1_status = new_status; @@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,  	u8 bRequest = (kcontrol->private_value >> 16) & 0xff;  	u16 wIndex = kcontrol->private_value & 0xffff;  	u8 tmp; +	int ret; -	int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, +	down_read(&mixer->chip->shutdown_rwsem); +	if (mixer->chip->shutdown) +		ret = -ENODEV; +	else +		ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,  				  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,  				  0, cpu_to_le16(wIndex),  				  &tmp, sizeof(tmp), 1000); +	up_read(&mixer->chip->shutdown_rwsem);  	if (ret < 0) {  		snd_printk(KERN_ERR @@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,  	u8 bRequest = (kcontrol->private_value >> 16) & 0xff;  	u16 wIndex = kcontrol->private_value & 0xffff;  	u16 wValue = ucontrol->value.integer.value[0]; +	int ret; -	int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, +	down_read(&mixer->chip->shutdown_rwsem); +	if (mixer->chip->shutdown) +		ret = -ENODEV; +	else +		ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,  				  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,  				  cpu_to_le16(wValue), cpu_to_le16(wIndex),  				  NULL, 0, 1000); +	up_read(&mixer->chip->shutdown_rwsem);  	if (ret < 0) {  		snd_printk(KERN_ERR @@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,  		return -EINVAL; -	err = snd_usb_ctl_msg(chip->dev, +	down_read(&mixer->chip->shutdown_rwsem); +	if (mixer->chip->shutdown) +		err = -ENODEV; +	else +		err = snd_usb_ctl_msg(chip->dev,  			usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,  			USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,  			validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),  			value, val_len); +	up_read(&mixer->chip->shutdown_rwsem);  	if (err < 0)  		return err; @@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,  	if (!pval->is_cached) {  		/* Read current value */ -		err = snd_usb_ctl_msg(chip->dev, +		down_read(&mixer->chip->shutdown_rwsem); +		if (mixer->chip->shutdown) +			err = -ENODEV; +		else +			err = snd_usb_ctl_msg(chip->dev,  				usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,  				USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,  				validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),  				value, val_len); +		up_read(&mixer->chip->shutdown_rwsem);  		if (err < 0)  			return err; @@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,  	if (cur_val != new_val) {  		value[0] = new_val;  		value[1] = 0; -		err = snd_usb_ctl_msg(chip->dev, +		down_read(&mixer->chip->shutdown_rwsem); +		if (mixer->chip->shutdown) +			err = -ENODEV; +		else +			err = snd_usb_ctl_msg(chip->dev,  				usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,  				USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,  				validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),  				value, val_len); +		up_read(&mixer->chip->shutdown_rwsem);  		if (err < 0)  			return err; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 55e19e1b80e..5c12a3fe8c3 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -71,6 +71,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream  	unsigned int hwptr_done;  	subs = (struct snd_usb_substream *)substream->runtime->private_data; +	if (subs->stream->chip->shutdown) +		return SNDRV_PCM_POS_XRUN;  	spin_lock(&subs->lock);  	hwptr_done = subs->hwptr_done;  	substream->runtime->delay = snd_usb_pcm_delay(subs, @@ -444,7 +446,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)  {  	int ret; -	mutex_lock(&subs->stream->chip->shutdown_mutex);  	/* format changed */  	stop_endpoints(subs, 0, 0, 0);  	ret = snd_usb_endpoint_set_params(subs->data_endpoint, @@ -455,7 +456,7 @@ static int configure_endpoint(struct snd_usb_substream *subs)  					  subs->cur_audiofmt,  					  subs->sync_endpoint);  	if (ret < 0) -		goto unlock; +		return ret;  	if (subs->sync_endpoint)  		ret = snd_usb_endpoint_set_params(subs->data_endpoint, @@ -465,9 +466,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)  						  subs->cur_rate,  						  subs->cur_audiofmt,  						  NULL); - -unlock: -	mutex_unlock(&subs->stream->chip->shutdown_mutex);  	return ret;  } @@ -505,7 +503,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,  		return -EINVAL;  	} -	if ((ret = set_format(subs, fmt)) < 0) +	down_read(&subs->stream->chip->shutdown_rwsem); +	if (subs->stream->chip->shutdown) +		ret = -ENODEV; +	else +		ret = set_format(subs, fmt); +	up_read(&subs->stream->chip->shutdown_rwsem); +	if (ret < 0)  		return ret;  	subs->interface = fmt->iface; @@ -527,10 +531,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)  	subs->cur_audiofmt = NULL;  	subs->cur_rate = 0;  	subs->period_bytes = 0; -	mutex_lock(&subs->stream->chip->shutdown_mutex); -	stop_endpoints(subs, 0, 1, 1); -	deactivate_endpoints(subs); -	mutex_unlock(&subs->stream->chip->shutdown_mutex); +	down_read(&subs->stream->chip->shutdown_rwsem); +	if (!subs->stream->chip->shutdown) { +		stop_endpoints(subs, 0, 1, 1); +		deactivate_endpoints(subs); +	} +	up_read(&subs->stream->chip->shutdown_rwsem);  	return snd_pcm_lib_free_vmalloc_buffer(substream);  } @@ -552,12 +558,22 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)  		return -ENXIO;  	} -	if (snd_BUG_ON(!subs->data_endpoint)) -		return -EIO; +	down_read(&subs->stream->chip->shutdown_rwsem); +	if (subs->stream->chip->shutdown) { +		ret = -ENODEV; +		goto unlock; +	} +	if (snd_BUG_ON(!subs->data_endpoint)) { +		ret = -EIO; +		goto unlock; +	} + +	snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); +	snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);  	ret = set_format(subs, subs->cur_audiofmt);  	if (ret < 0) -		return ret; +		goto unlock;  	iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);  	alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; @@ -567,12 +583,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)  				       subs->cur_audiofmt,  				       subs->cur_rate);  	if (ret < 0) -		return ret; +		goto unlock;  	if (subs->need_setup_ep) {  		ret = configure_endpoint(subs);  		if (ret < 0) -			return ret; +			goto unlock;  		subs->need_setup_ep = false;  	} @@ -592,9 +608,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)  	/* for playback, submit the URBs now; otherwise, the first hwptr_done  	 * updates for all URBs would happen at the same time when starting */  	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) -		return start_endpoints(subs, 1); +		ret = start_endpoints(subs, 1); -	return 0; + unlock: +	up_read(&subs->stream->chip->shutdown_rwsem); +	return ret;  }  static struct snd_pcm_hardware snd_usb_hardware = @@ -647,7 +665,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,  		return 0;  	}  	/* check whether the period time is >= the data packet interval */ -	if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { +	if (subs->speed != USB_SPEED_FULL) {  		ptime = 125 * (1 << fp->datainterval);  		if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {  			hwc_debug("   > check: ptime %u > max %u\n", ptime, pt->max); @@ -925,7 +943,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre  		return err;  	param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; -	if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) +	if (subs->speed == USB_SPEED_FULL)  		/* full speed devices have fixed data packet interval */  		ptmin = 1000;  	if (ptmin == 1000) diff --git a/sound/usb/proc.c b/sound/usb/proc.c index ebc1a5b5b3f..d218f763501 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -108,7 +108,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s  			}  			snd_iprintf(buffer, "\n");  		} -		if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) +		if (subs->speed != USB_SPEED_FULL)  			snd_iprintf(buffer, "    Data packet interval: %d us\n",  				    125 * (1 << fp->datainterval));  		// snd_iprintf(buffer, "    Max Packet Size = %d\n", fp->maxpacksize); @@ -124,7 +124,7 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs,  		return;  	snd_iprintf(buffer, "    Packet Size = %d\n", ep->curpacksize);  	snd_iprintf(buffer, "    Momentary freq = %u Hz (%#x.%04x)\n", -		    snd_usb_get_speed(subs->dev) == USB_SPEED_FULL +		    subs->speed == USB_SPEED_FULL  		    ? get_full_speed_hz(ep->freqm)  		    : get_high_speed_hz(ep->freqm),  		    ep->freqm >> 16, ep->freqm & 0xffff); diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 083ed81160e..1de0c8c002a 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -90,6 +90,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,  	subs->direction = stream;  	subs->dev = as->chip->dev;  	subs->txfr_quirk = as->chip->txfr_quirk; +	subs->speed = snd_usb_get_speed(subs->dev);  	snd_usb_set_pcm_ops(as->pcm, stream); diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index b8233ebe250..ef42797f56f 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -37,7 +37,7 @@ struct snd_usb_audio {  	struct usb_interface *pm_intf;  	u32 usb_id;  	struct mutex mutex; -	struct mutex shutdown_mutex; +	struct rw_semaphore shutdown_rwsem;  	unsigned int shutdown:1;  	unsigned int probing:1;  	unsigned int autosuspended:1;	 diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 411ee5664e9..178b88ae3d2 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c @@ -414,7 +414,7 @@ static int show_html_page(const char *perf_cmd)  int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)  {  	bool show_all = false; -	enum help_format help_format = HELP_FORMAT_NONE; +	enum help_format help_format = HELP_FORMAT_MAN;  	struct option builtin_help_options[] = {  	OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),  	OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN), diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index dec8ced61fb..7aaee39f677 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -56,6 +56,10 @@ static int trace__read_syscall_info(struct trace *trace, int id)  {  	char tp_name[128];  	struct syscall *sc; +	const char *name = audit_syscall_to_name(id, trace->audit_machine); + +	if (name == NULL) +		return -1;  	if (id > trace->syscalls.max) {  		struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc)); @@ -75,11 +79,8 @@ static int trace__read_syscall_info(struct trace *trace, int id)  	}  	sc = trace->syscalls.table + id; -	sc->name = audit_syscall_to_name(id, trace->audit_machine); -	if (sc->name == NULL) -		return -1; - -	sc->fmt = syscall_fmt__find(sc->name); +	sc->name = name; +	sc->fmt  = syscall_fmt__find(sc->name);  	snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);  	sc->tp_format = event_format__new("syscalls", tp_name); @@ -267,6 +268,13 @@ again:  			if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)  				printf("%d ", sample.tid); +			if (sample.raw_data == NULL) { +				printf("%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", +				       perf_evsel__name(evsel), sample.tid, +				       sample.cpu, sample.raw_size); +				continue; +			} +  			handler = evsel->handler.func;  			handler(trace, evsel, &sample);  		} diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index 28c18d1d52c..516ecd9ddd6 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c @@ -513,7 +513,8 @@ static int test__group1(struct perf_evlist *evlist)  	TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);  	TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);  	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); -	TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); +	/* use of precise requires exclude_guest */ +	TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);  	TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);  	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);  	TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); @@ -599,7 +600,8 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)  	TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);  	TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);  	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); -	TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); +	/* use of precise requires exclude_guest */ +	TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);  	TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);  	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3);  	TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); @@ -662,7 +664,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)  	TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);  	TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);  	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); -	TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); +	/* use of precise requires exclude_guest */ +	TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);  	TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);  	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);  	TEST_ASSERT_VAL("wrong group name", !evsel->group_name); @@ -676,7 +679,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)  	TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);  	TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);  	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); -	TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); +	/* use of precise requires exclude_guest */ +	TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);  	TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);  	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);  	TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index fb4b7ea6752..8b3e5939afb 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -39,7 +39,6 @@ int thread__set_comm(struct thread *self, const char *comm)  	err = self->comm == NULL ? -ENOMEM : 0;  	if (!err) {  		self->comm_set = true; -		map_groups__flush(&self->mg);  	}  	return err;  } diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index b51d787176d..c7ba7614061 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1740,8 +1740,10 @@ sub install {      open(IN, "$output_config") or dodie("Can't read config file");      while (<IN>) {  	if (/CONFIG_MODULES(=y)?/) { -	    $install_mods = 1 if (defined($1)); -	    last; +	    if (defined($1)) { +		$install_mods = 1; +		last; +	    }  	}      }      close(IN); diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 43480149119..85baf11e2ac 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -1,4 +1,4 @@ -TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug epoll +TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug  all:  	for TARGET in $(TARGETS); do \ diff --git a/tools/testing/selftests/epoll/Makefile b/tools/testing/selftests/epoll/Makefile deleted file mode 100644 index 19806ed62f5..00000000000 --- a/tools/testing/selftests/epoll/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# Makefile for epoll selftests - -all: test_epoll -%: %.c -	gcc -pthread -g -o $@ $^ - -run_tests: all -	./test_epoll - -clean: -	$(RM) test_epoll diff --git a/tools/testing/selftests/epoll/test_epoll.c b/tools/testing/selftests/epoll/test_epoll.c deleted file mode 100644 index e0fcff1e833..00000000000 --- a/tools/testing/selftests/epoll/test_epoll.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - *  tools/testing/selftests/epoll/test_epoll.c - * - *  Copyright 2012 Adobe Systems Incorporated - * - *  This program is free software; you can redistribute it and/or modify - *  it under the terms of the GNU General Public License as published by - *  the Free Software Foundation; either version 2 of the License, or - *  (at your option) any later version. - * - *  Paton J. Lewis <palewis@adobe.com> - * - */ - -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/epoll.h> -#include <sys/socket.h> - -/* - * A pointer to an epoll_item_private structure will be stored in the epoll - * item's event structure so that we can get access to the epoll_item_private - * data after calling epoll_wait: - */ -struct epoll_item_private { -	int index;  /* Position of this struct within the epoll_items array. */ -	int fd; -	uint32_t events; -	pthread_mutex_t mutex;  /* Guards the following variables... */ -	int stop; -	int status;  /* Stores any error encountered while handling item. */ -	/* The following variable allows us to test whether we have encountered -	   a problem while attempting to cancel and delete the associated -	   event. When the test program exits, 'deleted' should be exactly -	   one. If it is greater than one, then the failed test reflects a real -	   world situation where we would have tried to access the epoll item's -	   private data after deleting it: */ -	int deleted; -}; - -struct epoll_item_private *epoll_items; - -/* - * Delete the specified item from the epoll set. In a real-world secneario this - * is where we would free the associated data structure, but in this testing - * environment we retain the structure so that we can test for double-deletion: - */ -void delete_item(int index) -{ -	__sync_fetch_and_add(&epoll_items[index].deleted, 1); -} - -/* - * A pointer to a read_thread_data structure will be passed as the argument to - * each read thread: - */ -struct read_thread_data { -	int stop; -	int status;  /* Indicates any error encountered by the read thread. */ -	int epoll_set; -}; - -/* - * The function executed by the read threads: - */ -void *read_thread_function(void *function_data) -{ -	struct read_thread_data *thread_data = -		(struct read_thread_data *)function_data; -	struct epoll_event event_data; -	struct epoll_item_private *item_data; -	char socket_data; - -	/* Handle events until we encounter an error or this thread's 'stop' -	   condition is set: */ -	while (1) { -		int result = epoll_wait(thread_data->epoll_set, -					&event_data, -					1,	/* Number of desired events */ -					1000);  /* Timeout in ms */ -		if (result < 0) { -			/* Breakpoints signal all threads. Ignore that while -			   debugging: */ -			if (errno == EINTR) -				continue; -			thread_data->status = errno; -			return 0; -		} else if (thread_data->stop) -			return 0; -		else if (result == 0)  /* Timeout */ -			continue; - -		/* We need the mutex here because checking for the stop -		   condition and re-enabling the epoll item need to be done -		   together as one atomic operation when EPOLL_CTL_DISABLE is -		   available: */ -		item_data = (struct epoll_item_private *)event_data.data.ptr; -		pthread_mutex_lock(&item_data->mutex); - -		/* Remove the item from the epoll set if we want to stop -		   handling that event: */ -		if (item_data->stop) -			delete_item(item_data->index); -		else { -			/* Clear the data that was written to the other end of -			   our non-blocking socket: */ -			do { -				if (read(item_data->fd, &socket_data, 1) < 1) { -					if ((errno == EAGAIN) || -					    (errno == EWOULDBLOCK)) -						break; -					else -						goto error_unlock; -				} -			} while (item_data->events & EPOLLET); - -			/* The item was one-shot, so re-enable it: */ -			event_data.events = item_data->events; -			if (epoll_ctl(thread_data->epoll_set, -						  EPOLL_CTL_MOD, -						  item_data->fd, -						  &event_data) < 0) -				goto error_unlock; -		} - -		pthread_mutex_unlock(&item_data->mutex); -	} - -error_unlock: -	thread_data->status = item_data->status = errno; -	pthread_mutex_unlock(&item_data->mutex); -	return 0; -} - -/* - * A pointer to a write_thread_data structure will be passed as the argument to - * the write thread: - */ -struct write_thread_data { -	int stop; -	int status;  /* Indicates any error encountered by the write thread. */ -	int n_fds; -	int *fds; -}; - -/* - * The function executed by the write thread. It writes a single byte to each - * socket in turn until the stop condition for this thread is set. If writing to - * a socket would block (i.e. errno was EAGAIN), we leave that socket alone for - * the moment and just move on to the next socket in the list. We don't care - * about the order in which we deliver events to the epoll set. In fact we don't - * care about the data we're writing to the pipes at all; we just want to - * trigger epoll events: - */ -void *write_thread_function(void *function_data) -{ -	const char data = 'X'; -	int index; -	struct write_thread_data *thread_data = -		(struct write_thread_data *)function_data; -	while (!write_thread_data->stop) -		for (index = 0; -		     !thread_data->stop && (index < thread_data->n_fds); -		     ++index) -			if ((write(thread_data->fds[index], &data, 1) < 1) && -				(errno != EAGAIN) && -				(errno != EWOULDBLOCK)) { -				write_thread_data->status = errno; -				return; -			} -} - -/* - * Arguments are currently ignored: - */ -int main(int argc, char **argv) -{ -	const int n_read_threads = 100; -	const int n_epoll_items = 500; -	int index; -	int epoll_set = epoll_create1(0); -	struct write_thread_data write_thread_data = { -		0, 0, n_epoll_items, malloc(n_epoll_items * sizeof(int)) -	}; -	struct read_thread_data *read_thread_data = -		malloc(n_read_threads * sizeof(struct read_thread_data)); -	pthread_t *read_threads = malloc(n_read_threads * sizeof(pthread_t)); -	pthread_t write_thread; - -	printf("-----------------\n"); -	printf("Runing test_epoll\n"); -	printf("-----------------\n"); - -	epoll_items = malloc(n_epoll_items * sizeof(struct epoll_item_private)); - -	if (epoll_set < 0 || epoll_items == 0 || write_thread_data.fds == 0 || -		read_thread_data == 0 || read_threads == 0) -		goto error; - -	if (sysconf(_SC_NPROCESSORS_ONLN) < 2) { -		printf("Error: please run this test on a multi-core system.\n"); -		goto error; -	} - -	/* Create the socket pairs and epoll items: */ -	for (index = 0; index < n_epoll_items; ++index) { -		int socket_pair[2]; -		struct epoll_event event_data; -		if (socketpair(AF_UNIX, -			       SOCK_STREAM | SOCK_NONBLOCK, -			       0, -			       socket_pair) < 0) -			goto error; -		write_thread_data.fds[index] = socket_pair[0]; -		epoll_items[index].index = index; -		epoll_items[index].fd = socket_pair[1]; -		if (pthread_mutex_init(&epoll_items[index].mutex, NULL) != 0) -			goto error; -		/* We always use EPOLLONESHOT because this test is currently -		   structured to demonstrate the need for EPOLL_CTL_DISABLE, -		   which only produces useful information in the EPOLLONESHOT -		   case (without EPOLLONESHOT, calling epoll_ctl with -		   EPOLL_CTL_DISABLE will never return EBUSY). If support for -		   testing events without EPOLLONESHOT is desired, it should -		   probably be implemented in a separate unit test. */ -		epoll_items[index].events = EPOLLIN | EPOLLONESHOT; -		if (index < n_epoll_items / 2) -			epoll_items[index].events |= EPOLLET; -		epoll_items[index].stop = 0; -		epoll_items[index].status = 0; -		epoll_items[index].deleted = 0; -		event_data.events = epoll_items[index].events; -		event_data.data.ptr = &epoll_items[index]; -		if (epoll_ctl(epoll_set, -			      EPOLL_CTL_ADD, -			      epoll_items[index].fd, -			      &event_data) < 0) -			goto error; -	} - -	/* Create and start the read threads: */ -	for (index = 0; index < n_read_threads; ++index) { -		read_thread_data[index].stop = 0; -		read_thread_data[index].status = 0; -		read_thread_data[index].epoll_set = epoll_set; -		if (pthread_create(&read_threads[index], -				   NULL, -				   read_thread_function, -				   &read_thread_data[index]) != 0) -			goto error; -	} - -	if (pthread_create(&write_thread, -			   NULL, -			   write_thread_function, -			   &write_thread_data) != 0) -		goto error; - -	/* Cancel all event pollers: */ -#ifdef EPOLL_CTL_DISABLE -	for (index = 0; index < n_epoll_items; ++index) { -		pthread_mutex_lock(&epoll_items[index].mutex); -		++epoll_items[index].stop; -		if (epoll_ctl(epoll_set, -			      EPOLL_CTL_DISABLE, -			      epoll_items[index].fd, -			      NULL) == 0) -			delete_item(index); -		else if (errno != EBUSY) { -			pthread_mutex_unlock(&epoll_items[index].mutex); -			goto error; -		} -		/* EBUSY means events were being handled; allow the other thread -		   to delete the item. */ -		pthread_mutex_unlock(&epoll_items[index].mutex); -	} -#else -	for (index = 0; index < n_epoll_items; ++index) { -		pthread_mutex_lock(&epoll_items[index].mutex); -		++epoll_items[index].stop; -		pthread_mutex_unlock(&epoll_items[index].mutex); -		/* Wait in case a thread running read_thread_function is -		   currently executing code between epoll_wait and -		   pthread_mutex_lock with this item. Note that a longer delay -		   would make double-deletion less likely (at the expense of -		   performance), but there is no guarantee that any delay would -		   ever be sufficient. Note also that we delete all event -		   pollers at once for testing purposes, but in a real-world -		   environment we are likely to want to be able to cancel event -		   pollers at arbitrary times. Therefore we can't improve this -		   situation by just splitting this loop into two loops -		   (i.e. signal 'stop' for all items, sleep, and then delete all -		   items). We also can't fix the problem via EPOLL_CTL_DEL -		   because that command can't prevent the case where some other -		   thread is executing read_thread_function within the region -		   mentioned above: */ -		usleep(1); -		pthread_mutex_lock(&epoll_items[index].mutex); -		if (!epoll_items[index].deleted) -			delete_item(index); -		pthread_mutex_unlock(&epoll_items[index].mutex); -	} -#endif - -	/* Shut down the read threads: */ -	for (index = 0; index < n_read_threads; ++index) -		__sync_fetch_and_add(&read_thread_data[index].stop, 1); -	for (index = 0; index < n_read_threads; ++index) { -		if (pthread_join(read_threads[index], NULL) != 0) -			goto error; -		if (read_thread_data[index].status) -			goto error; -	} - -	/* Shut down the write thread: */ -	__sync_fetch_and_add(&write_thread_data.stop, 1); -	if ((pthread_join(write_thread, NULL) != 0) || write_thread_data.status) -		goto error; - -	/* Check for final error conditions: */ -	for (index = 0; index < n_epoll_items; ++index) { -		if (epoll_items[index].status != 0) -			goto error; -		if (pthread_mutex_destroy(&epoll_items[index].mutex) < 0) -			goto error; -	} -	for (index = 0; index < n_epoll_items; ++index) -		if (epoll_items[index].deleted != 1) { -			printf("Error: item data deleted %1d times.\n", -				   epoll_items[index].deleted); -			goto error; -		} - -	printf("[PASS]\n"); -	return 0; - - error: -	printf("[FAIL]\n"); -	return errno; -} diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c index cd1b03e8089..b76edf2f833 100644 --- a/tools/vm/page-types.c +++ b/tools/vm/page-types.c @@ -35,7 +35,7 @@  #include <sys/mount.h>  #include <sys/statfs.h>  #include "../../include/uapi/linux/magic.h" -#include "../../include/linux/kernel-page-flags.h" +#include "../../include/uapi/linux/kernel-page-flags.h"  #ifndef MAX_PATH diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c index af0f22fb1ef..aca6edcbbc6 100644 --- a/usr/gen_init_cpio.c +++ b/usr/gen_init_cpio.c @@ -303,7 +303,7 @@ static int cpio_mkfile(const char *name, const char *location,  	int retval;  	int rc = -1;  	int namesize; -	int i; +	unsigned int i;  	mode |= S_IFREG; @@ -381,25 +381,28 @@ error:  static char *cpio_replace_env(char *new_location)  { -       char expanded[PATH_MAX + 1]; -       char env_var[PATH_MAX + 1]; -       char *start; -       char *end; +	char expanded[PATH_MAX + 1]; +	char env_var[PATH_MAX + 1]; +	char *start; +	char *end; -       for (start = NULL; (start = strstr(new_location, "${")); ) { -               end = strchr(start, '}'); -               if (start < end) { -                       *env_var = *expanded = '\0'; -                       strncat(env_var, start + 2, end - start - 2); -                       strncat(expanded, new_location, start - new_location); -                       strncat(expanded, getenv(env_var), PATH_MAX); -                       strncat(expanded, end + 1, PATH_MAX); -                       strncpy(new_location, expanded, PATH_MAX); -               } else -                       break; -       } +	for (start = NULL; (start = strstr(new_location, "${")); ) { +		end = strchr(start, '}'); +		if (start < end) { +			*env_var = *expanded = '\0'; +			strncat(env_var, start + 2, end - start - 2); +			strncat(expanded, new_location, start - new_location); +			strncat(expanded, getenv(env_var), +				PATH_MAX - strlen(expanded)); +			strncat(expanded, end + 1, +				PATH_MAX - strlen(expanded)); +			strncpy(new_location, expanded, PATH_MAX); +			new_location[PATH_MAX] = 0; +		} else +			break; +	} -       return new_location; +	return new_location;  }  |