diff options
400 files changed, 3872 insertions, 2757 deletions
diff --git a/Documentation/ABI/stable/sysfs-driver-usb-usbtmc b/Documentation/ABI/stable/sysfs-driver-usb-usbtmc index 2a7f9a00cb0a..e960cd027e1e 100644 --- a/Documentation/ABI/stable/sysfs-driver-usb-usbtmc +++ b/Documentation/ABI/stable/sysfs-driver-usb-usbtmc @@ -1,5 +1,5 @@ -What: /sys/bus/usb/drivers/usbtmc/devices/*/interface_capabilities -What: /sys/bus/usb/drivers/usbtmc/devices/*/device_capabilities +What: /sys/bus/usb/drivers/usbtmc/*/interface_capabilities +What: /sys/bus/usb/drivers/usbtmc/*/device_capabilities Date: August 2008 Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Description: @@ -12,8 +12,8 @@ Description: The files are read only. -What: /sys/bus/usb/drivers/usbtmc/devices/*/usb488_interface_capabilities -What: /sys/bus/usb/drivers/usbtmc/devices/*/usb488_device_capabilities +What: /sys/bus/usb/drivers/usbtmc/*/usb488_interface_capabilities +What: /sys/bus/usb/drivers/usbtmc/*/usb488_device_capabilities Date: August 2008 Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Description: @@ -27,7 +27,7 @@ Description: The files are read only. -What: /sys/bus/usb/drivers/usbtmc/devices/*/TermChar +What: /sys/bus/usb/drivers/usbtmc/*/TermChar Date: August 2008 Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Description: @@ -40,7 +40,7 @@ Description: sent to the device or not. -What: /sys/bus/usb/drivers/usbtmc/devices/*/TermCharEnabled +What: /sys/bus/usb/drivers/usbtmc/*/TermCharEnabled Date: August 2008 Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Description: @@ -51,7 +51,7 @@ Description: published by the USB-IF. -What: /sys/bus/usb/drivers/usbtmc/devices/*/auto_abort +What: /sys/bus/usb/drivers/usbtmc/*/auto_abort Date: August 2008 Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Description: diff --git a/Documentation/ABI/testing/sysfs-block-rssd b/Documentation/ABI/testing/sysfs-block-rssd new file mode 100644 index 000000000000..d535757799fe --- /dev/null +++ b/Documentation/ABI/testing/sysfs-block-rssd @@ -0,0 +1,18 @@ +What: /sys/block/rssd*/registers +Date: March 2012 +KernelVersion: 3.3 +Contact: Asai Thambi S P <asamymuthupa@micron.com> +Description: This is a read-only file. Dumps below driver information and + hardware registers. + - S ACTive + - Command Issue + - Allocated + - Completed + - PORT IRQ STAT + - HOST IRQ STAT + +What: /sys/block/rssd*/status +Date: April 2012 +KernelVersion: 3.4 +Contact: Asai Thambi S P <asamymuthupa@micron.com> +Description: This is a read-only file. Indicates the status of the device. diff --git a/Documentation/ABI/testing/sysfs-cfq-target-latency b/Documentation/ABI/testing/sysfs-cfq-target-latency new file mode 100644 index 000000000000..df0f7828c5e3 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-cfq-target-latency @@ -0,0 +1,8 @@ +What: /sys/block/<device>/iosched/target_latency +Date: March 2012 +contact: Tao Ma <boyu.mt@taobao.com> +Description: + The /sys/block/<device>/iosched/target_latency only exists + when the user sets cfq to /sys/block/<device>/scheduler. + It contains an estimated latency time for the cfq. cfq will + use it to calculate the time slice used for every task. diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 4c95c0034a4b..9b1067afb224 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -34,8 +34,7 @@ Current Status: linux-2.6.34-mmotm(development version of 2010/April) Features: - accounting anonymous pages, file caches, swap caches usage and limiting them. - - private LRU and reclaim routine. (system's global LRU and private LRU - work independently from each other) + - pages are linked to per-memcg LRU exclusively, and there is no global LRU. - optionally, memory+swap usage can be accounted and limited. - hierarchical accounting - soft limit @@ -154,7 +153,7 @@ updated. page_cgroup has its own LRU on cgroup. 2.2.1 Accounting details All mapped anon pages (RSS) and cache pages (Page Cache) are accounted. -Some pages which are never reclaimable and will not be on the global LRU +Some pages which are never reclaimable and will not be on the LRU are not accounted. We just account pages under usual VM management. RSS pages are accounted at page_fault unless they've already been accounted diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 709e08e9a222..03ca210406ed 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -531,3 +531,11 @@ Why: There appear to be no production users of the get_robust_list syscall, of ASLR. It was only ever intended for debugging, so it should be removed. Who: Kees Cook <keescook@chromium.org> + +---------------------------- + +What: setitimer accepts user NULL pointer (value) +When: 3.6 +Why: setitimer is not returning -EFAULT if user pointer is NULL. This + violates the spec. +Who: Sasikantha Babu <sasikanth.v19@gmail.com> diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index e916e3d36488..0d0492028082 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -114,7 +114,7 @@ members are defined: struct file_system_type { const char *name; int fs_flags; - struct dentry (*mount) (struct file_system_type *, int, + struct dentry *(*mount) (struct file_system_type *, int, const char *, void *); void (*kill_sb) (struct super_block *); struct module *owner; diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index d97d992ced14..03f7897c6414 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -43,7 +43,9 @@ ALC680 ALC882/883/885/888/889 ====================== - N/A + acer-aspire-4930g Acer Aspire 4930G/5930G/6530G/6930G/7730G + acer-aspire-8930g Acer Aspire 8330G/6935G + acer-aspire Acer Aspire others ALC861/660 ========== diff --git a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt index 8ffce746d496..00d2c644068e 100644 --- a/Documentation/usb/URB.txt +++ b/Documentation/usb/URB.txt @@ -168,6 +168,28 @@ that if the completion handler or anyone else tries to resubmit it they will get a -EPERM error. Thus you can be sure that when usb_kill_urb() returns, the URB is totally idle. +There is a lifetime issue to consider. An URB may complete at any +time, and the completion handler may free the URB. If this happens +while usb_unlink_urb or usb_kill_urb is running, it will cause a +memory-access violation. The driver is responsible for avoiding this, +which often means some sort of lock will be needed to prevent the URB +from being deallocated while it is still in use. + +On the other hand, since usb_unlink_urb may end up calling the +completion handler, the handler must not take any lock that is held +when usb_unlink_urb is invoked. The general solution to this problem +is to increment the URB's reference count while holding the lock, then +drop the lock and call usb_unlink_urb or usb_kill_urb, and then +decrement the URB's reference count. You increment the reference +count by calling + + struct urb *usb_get_urb(struct urb *urb) + +(ignore the return value; it is the same as the argument) and +decrement the reference count by calling usb_free_urb. Of course, +none of this is necessary if there's no danger of the URB being freed +by the completion handler. + 1.7. What about the completion handler? diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt index 5335fa8b06eb..c42bb9cd3b43 100644 --- a/Documentation/usb/usbmon.txt +++ b/Documentation/usb/usbmon.txt @@ -183,10 +183,10 @@ An input control transfer to get a port status. d5ea89a0 3575914555 S Ci:1:001:0 s a3 00 0000 0003 0004 4 < d5ea89a0 3575914560 C Ci:1:001:0 0 4 = 01050000 -An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper -to a storage device at address 5: +An output bulk transfer to send a SCSI command 0x28 (READ_10) in a 31-byte +Bulk wrapper to a storage device at address 5: -dd65f0e8 4128379752 S Bo:1:005:2 -115 31 = 55534243 5e000000 00000000 00000600 00000000 00000000 00000000 000000 +dd65f0e8 4128379752 S Bo:1:005:2 -115 31 = 55534243 ad000000 00800000 80010a28 20000000 20000040 00000000 000000 dd65f0e8 4128379808 C Bo:1:005:2 0 31 > * Raw binary format and API diff --git a/MAINTAINERS b/MAINTAINERS index 0b568b6f1163..3ea1af5c2709 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1521,8 +1521,8 @@ M: Gustavo Padovan <gustavo@padovan.org> M: Johan Hedberg <johan.hedberg@gmail.com> L: linux-bluetooth@vger.kernel.org W: http://www.bluez.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jh/bluetooth.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git S: Maintained F: drivers/bluetooth/ @@ -1532,8 +1532,8 @@ M: Gustavo Padovan <gustavo@padovan.org> M: Johan Hedberg <johan.hedberg@gmail.com> L: linux-bluetooth@vger.kernel.org W: http://www.bluez.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jh/bluetooth.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git S: Maintained F: net/bluetooth/ F: include/net/bluetooth/ @@ -2321,9 +2321,9 @@ S: Supported F: drivers/acpi/dock.c DOCUMENTATION -M: Randy Dunlap <rdunlap@xenotime.net> +M: Rob Landley <rob@landley.net> L: linux-doc@vger.kernel.org -T: quilt http://xenotime.net/kernel-doc-patches/current/ +T: TBD S: Maintained F: Documentation/ @@ -4533,8 +4533,7 @@ S: Supported F: drivers/net/ethernet/myricom/myri10ge/ NATSEMI ETHERNET DRIVER (DP8381x) -M: Tim Hockin <thockin@hockin.org> -S: Maintained +S: Orphan F: drivers/net/ethernet/natsemi/natsemi.c NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER @@ -4803,6 +4802,7 @@ F: arch/arm/mach-omap2/clockdomain2xxx_3xxx.c F: arch/arm/mach-omap2/clockdomain44xx.c OMAP AUDIO SUPPORT +M: Peter Ujfalusi <peter.ujfalusi@ti.com> M: Jarkko Nikula <jarkko.nikula@bitmer.com> L: alsa-devel@alsa-project.org (subscribers-only) L: linux-omap@vger.kernel.org @@ -5117,6 +5117,11 @@ F: drivers/i2c/busses/i2c-pca-* F: include/linux/i2c-algo-pca.h F: include/linux/i2c-pca-platform.h +PCDP - PRIMARY CONSOLE AND DEBUG PORT +M: Khalid Aziz <khalid.aziz@hp.com> +S: Maintained +F: drivers/firmware/pcdp.* + PCI ERROR RECOVERY M: Linas Vepstas <linasvepstas@gmail.com> L: linux-pci@vger.kernel.org @@ -6466,6 +6471,7 @@ S: Odd Fixes F: drivers/staging/olpc_dcon/ STAGING - OZMO DEVICES USB OVER WIFI DRIVER +M: Rupesh Gujare <rgujare@ozmodevices.com> M: Chris Kelly <ckelly@ozmodevices.com> S: Maintained F: drivers/staging/ozwpan/ @@ -7461,8 +7467,7 @@ F: include/linux/wm97xx.h WOLFSON MICROELECTRONICS DRIVERS M: Mark Brown <broonie@opensource.wolfsonmicro.com> -M: Ian Lartey <ian@opensource.wolfsonmicro.com> -M: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> +L: patches@opensource.wolfsonmicro.com T: git git://opensource.wolfsonmicro.com/linux-2.6-asoc T: git git://opensource.wolfsonmicro.com/linux-2.6-audioplus W: http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3 NAME = Saber-toothed Squirrel # *DOCUMENTATION* diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h index f62251e82ffa..3bb7ffeae3bc 100644 --- a/arch/alpha/include/asm/atomic.h +++ b/arch/alpha/include/asm/atomic.h @@ -3,6 +3,7 @@ #include <linux/types.h> #include <asm/barrier.h> +#include <asm/cmpxchg.h> /* * Atomic operations that C can't guarantee us. Useful for @@ -168,73 +169,6 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v) return result; } -/* - * Atomic exchange routines. - */ - -#define __ASM__MB -#define ____xchg(type, args...) __xchg ## type ## _local(args) -#define ____cmpxchg(type, args...) __cmpxchg ## type ## _local(args) -#include <asm/xchg.h> - -#define xchg_local(ptr,x) \ - ({ \ - __typeof__(*(ptr)) _x_ = (x); \ - (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_, \ - sizeof(*(ptr))); \ - }) - -#define cmpxchg_local(ptr, o, n) \ - ({ \ - __typeof__(*(ptr)) _o_ = (o); \ - __typeof__(*(ptr)) _n_ = (n); \ - (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \ - (unsigned long)_n_, \ - sizeof(*(ptr))); \ - }) - -#define cmpxchg64_local(ptr, o, n) \ - ({ \ - BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ - cmpxchg_local((ptr), (o), (n)); \ - }) - -#ifdef CONFIG_SMP -#undef __ASM__MB -#define __ASM__MB "\tmb\n" -#endif -#undef ____xchg -#undef ____cmpxchg -#define ____xchg(type, args...) __xchg ##type(args) -#define ____cmpxchg(type, args...) __cmpxchg ##type(args) -#include <asm/xchg.h> - -#define xchg(ptr,x) \ - ({ \ - __typeof__(*(ptr)) _x_ = (x); \ - (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, \ - sizeof(*(ptr))); \ - }) - -#define cmpxchg(ptr, o, n) \ - ({ \ - __typeof__(*(ptr)) _o_ = (o); \ - __typeof__(*(ptr)) _n_ = (n); \ - (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ - (unsigned long)_n_, sizeof(*(ptr)));\ - }) - -#define cmpxchg64(ptr, o, n) \ - ({ \ - BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ - cmpxchg((ptr), (o), (n)); \ - }) - -#undef __ASM__MB -#undef ____cmpxchg - -#define __HAVE_ARCH_CMPXCHG 1 - #define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new)) #define atomic64_xchg(v, new) (xchg(&((v)->counter), new)) diff --git a/arch/alpha/include/asm/cmpxchg.h b/arch/alpha/include/asm/cmpxchg.h new file mode 100644 index 000000000000..429e8cd0d78e --- /dev/null +++ b/arch/alpha/include/asm/cmpxchg.h @@ -0,0 +1,71 @@ +#ifndef _ALPHA_CMPXCHG_H +#define _ALPHA_CMPXCHG_H + +/* + * Atomic exchange routines. + */ + +#define __ASM__MB +#define ____xchg(type, args...) __xchg ## type ## _local(args) +#define ____cmpxchg(type, args...) __cmpxchg ## type ## _local(args) +#include <asm/xchg.h> + +#define xchg_local(ptr, x) \ +({ \ + __typeof__(*(ptr)) _x_ = (x); \ + (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_, \ + sizeof(*(ptr))); \ +}) + +#define cmpxchg_local(ptr, o, n) \ +({ \ + __typeof__(*(ptr)) _o_ = (o); \ + __typeof__(*(ptr)) _n_ = (n); \ + (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \ + (unsigned long)_n_, \ + sizeof(*(ptr))); \ +}) + +#define cmpxchg64_local(ptr, o, n) \ +({ \ + BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ + cmpxchg_local((ptr), (o), (n)); \ +}) + +#ifdef CONFIG_SMP +#undef __ASM__MB +#define __ASM__MB "\tmb\n" +#endif +#undef ____xchg +#undef ____cmpxchg +#define ____xchg(type, args...) __xchg ##type(args) +#define ____cmpxchg(type, args...) __cmpxchg ##type(args) +#include <asm/xchg.h> + +#define xchg(ptr, x) \ +({ \ + __typeof__(*(ptr)) _x_ = (x); \ + (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, \ + sizeof(*(ptr))); \ +}) + +#define cmpxchg(ptr, o, n) \ +({ \ + __typeof__(*(ptr)) _o_ = (o); \ + __typeof__(*(ptr)) _n_ = (n); \ + (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ + (unsigned long)_n_, sizeof(*(ptr)));\ +}) + +#define cmpxchg64(ptr, o, n) \ +({ \ + BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ + cmpxchg((ptr), (o), (n)); \ +}) + +#undef __ASM__MB +#undef ____cmpxchg + +#define __HAVE_ARCH_CMPXCHG 1 + +#endif /* _ALPHA_CMPXCHG_H */ diff --git a/arch/alpha/include/asm/xchg.h b/arch/alpha/include/asm/xchg.h index 1d1b436fbff2..0ca9724597c1 100644 --- a/arch/alpha/include/asm/xchg.h +++ b/arch/alpha/include/asm/xchg.h @@ -1,10 +1,10 @@ -#ifndef _ALPHA_ATOMIC_H +#ifndef _ALPHA_CMPXCHG_H #error Do not include xchg.h directly! #else /* * xchg/xchg_local and cmpxchg/cmpxchg_local share the same code * except that local version do not have the expensive memory barrier. - * So this file is included twice from asm/system.h. + * So this file is included twice from asm/cmpxchg.h. */ /* diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c index 6ce11c481178..797f04bedb47 100644 --- a/arch/arm/boot/compressed/atags_to_fdt.c +++ b/arch/arm/boot/compressed/atags_to_fdt.c @@ -77,6 +77,8 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space) } else if (atag->hdr.tag == ATAG_MEM) { if (memcount >= sizeof(mem_reg_property)/4) continue; + if (!atag->u.mem.size) + continue; mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start); mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size); } else if (atag->hdr.tag == ATAG_INITRD2) { diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 5f6045f1766c..dc7e8ce8e6be 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -273,7 +273,7 @@ restart: adr r0, LC0 add r0, r0, #0x100 mov r1, r6 sub r2, sp, r6 - blne atags_to_fdt + bleq atags_to_fdt ldmfd sp!, {r0-r3, ip, lr} sub sp, sp, #0x10000 diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi index 799ad1889b51..773ef484037a 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/at91sam9g20.dtsi @@ -55,7 +55,6 @@ #interrupt-cells = <2>; compatible = "atmel,at91rm9200-aic"; interrupt-controller; - interrupt-parent; reg = <0xfffff000 0x200>; }; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index 9e6eb6ecea0e..c8042147eaa2 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -56,7 +56,6 @@ #interrupt-cells = <2>; compatible = "atmel,at91rm9200-aic"; interrupt-controller; - interrupt-parent; reg = <0xfffff000 0x200>; }; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 70ab3a4e026f..dd4ed748469a 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -54,7 +54,6 @@ #interrupt-cells = <2>; compatible = "atmel,at91rm9200-aic"; interrupt-controller; - interrupt-parent; reg = <0xfffff000 0x200>; }; diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi index d73dce645667..14bc30705099 100644 --- a/arch/arm/boot/dts/db8500.dtsi +++ b/arch/arm/boot/dts/db8500.dtsi @@ -24,7 +24,6 @@ #interrupt-cells = <3>; #address-cells = <1>; interrupt-controller; - interrupt-parent; reg = <0xa0411000 0x1000>, <0xa0410100 0x100>; }; diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts index 37c0ff9c8b90..83e72294aefb 100644 --- a/arch/arm/boot/dts/highbank.dts +++ b/arch/arm/boot/dts/highbank.dts @@ -89,7 +89,6 @@ #size-cells = <0>; #address-cells = <1>; interrupt-controller; - interrupt-parent; reg = <0xfff11000 0x1000>, <0xfff10100 0x100>; }; diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index 7a66311f3066..7e288f96cedf 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c @@ -427,19 +427,18 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent) /* * Handle each interrupt in a single VIC. Returns non-zero if we've - * handled at least one interrupt. This does a single read of the - * status register and handles all interrupts in order from LSB first. + * handled at least one interrupt. This reads the status register + * before handling each interrupt, which is necessary given that + * handle_IRQ may briefly re-enable interrupts for soft IRQ handling. */ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) { u32 stat, irq; int handled = 0; - stat = readl_relaxed(vic->base + VIC_IRQ_STATUS); - while (stat) { + while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) { irq = ffs(stat) - 1; handle_IRQ(irq_find_mapping(vic->domain, irq), regs); - stat &= ~(1 << irq); handled = 1; } diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h index 5c5ca2ea62b0..bfc198c75913 100644 --- a/arch/arm/include/asm/jump_label.h +++ b/arch/arm/include/asm/jump_label.h @@ -14,7 +14,7 @@ #define JUMP_LABEL_NOP "nop" #endif -static __always_inline bool arch_static_branch(struct jump_label_key *key) +static __always_inline bool arch_static_branch(struct static_key *key) { asm goto("1:\n\t" JUMP_LABEL_NOP "\n\t" diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index b91411371ae1..ebfac782593f 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -523,7 +523,21 @@ int __init arm_add_memory(phys_addr_t start, unsigned long size) */ size -= start & ~PAGE_MASK; bank->start = PAGE_ALIGN(start); - bank->size = size & PAGE_MASK; + +#ifndef CONFIG_LPAE + if (bank->start + size < bank->start) { + printk(KERN_CRIT "Truncating memory at 0x%08llx to fit in " + "32-bit physical address space\n", (long long)start); + /* + * To ensure bank->start + bank->size is representable in + * 32 bits, we use ULONG_MAX as the upper limit rather than 4GB. + * This means we lose a page after masking. + */ + size = ULONG_MAX - bank->start; + } +#endif + + bank->size = size & PAGE_MASK; /* * Check whether this memory region has non-zero size or diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index fef42b21cecb..5b150afb995b 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -118,10 +118,14 @@ static int twd_cpufreq_transition(struct notifier_block *nb, * The twd clock events must be reprogrammed to account for the new * frequency. The timer is local to a cpu, so cross-call to the * changing cpu. + * + * Only wait for it to finish, if the cpu is active to avoid + * deadlock when cpu1 is spinning on while(!cpu_active(cpu1)) during + * booting of that cpu. */ if (state == CPUFREQ_POSTCHANGE || state == CPUFREQ_RESUMECHANGE) smp_call_function_single(freqs->cpu, twd_update_frequency, - NULL, 1); + NULL, cpu_active(freqs->cpu)); return NOTIFY_OK; } diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 0491ceef1cda..e81c35f936b5 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -368,6 +368,7 @@ comment "Flattened Device Tree based board for EXYNOS SoCs" config MACH_EXYNOS4_DT bool "Samsung Exynos4 Machine using device tree" + depends on ARCH_EXYNOS4 select CPU_EXYNOS4210 select USE_OF select ARM_AMBA @@ -380,6 +381,7 @@ config MACH_EXYNOS4_DT config MACH_EXYNOS5_DT bool "SAMSUNG EXYNOS5 Machine using device tree" + depends on ARCH_EXYNOS5 select SOC_EXYNOS5250 select USE_OF select ARM_AMBA diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h index 9bee8535d9e0..591e78521a9f 100644 --- a/arch/arm/mach-exynos/include/mach/irqs.h +++ b/arch/arm/mach-exynos/include/mach/irqs.h @@ -212,6 +212,8 @@ #define IRQ_MFC EXYNOS4_IRQ_MFC #define IRQ_SDO EXYNOS4_IRQ_SDO +#define IRQ_I2S0 EXYNOS4_IRQ_I2S0 + #define IRQ_ADC EXYNOS4_IRQ_ADC0 #define IRQ_TC EXYNOS4_IRQ_PEN0 diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 024d38ff1718..6e6d11ff352a 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -89,6 +89,10 @@ #define EXYNOS4_PA_MDMA1 0x12840000 #define EXYNOS4_PA_PDMA0 0x12680000 #define EXYNOS4_PA_PDMA1 0x12690000 +#define EXYNOS5_PA_MDMA0 0x10800000 +#define EXYNOS5_PA_MDMA1 0x11C10000 +#define EXYNOS5_PA_PDMA0 0x121A0000 +#define EXYNOS5_PA_PDMA1 0x121B0000 #define EXYNOS4_PA_SYSMMU_MDMA 0x10A40000 #define EXYNOS4_PA_SYSMMU_SSS 0x10A50000 diff --git a/arch/arm/mach-exynos/include/mach/regs-clock.h b/arch/arm/mach-exynos/include/mach/regs-clock.h index e141c1fd68d8..d9578a58ae7f 100644 --- a/arch/arm/mach-exynos/include/mach/regs-clock.h +++ b/arch/arm/mach-exynos/include/mach/regs-clock.h @@ -255,9 +255,15 @@ /* For EXYNOS5250 */ +#define EXYNOS5_APLL_LOCK EXYNOS_CLKREG(0x00000) #define EXYNOS5_APLL_CON0 EXYNOS_CLKREG(0x00100) #define EXYNOS5_CLKSRC_CPU EXYNOS_CLKREG(0x00200) +#define EXYNOS5_CLKMUX_STATCPU EXYNOS_CLKREG(0x00400) #define EXYNOS5_CLKDIV_CPU0 EXYNOS_CLKREG(0x00500) +#define EXYNOS5_CLKDIV_CPU1 EXYNOS_CLKREG(0x00504) +#define EXYNOS5_CLKDIV_STATCPU0 EXYNOS_CLKREG(0x00600) +#define EXYNOS5_CLKDIV_STATCPU1 EXYNOS_CLKREG(0x00604) + #define EXYNOS5_MPLL_CON0 EXYNOS_CLKREG(0x04100) #define EXYNOS5_CLKSRC_CORE1 EXYNOS_CLKREG(0x04204) diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c index 0d26f50081ad..4711c8920e37 100644 --- a/arch/arm/mach-exynos/mach-exynos5-dt.c +++ b/arch/arm/mach-exynos/mach-exynos5-dt.c @@ -45,7 +45,7 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = { "exynos4210-uart.3", NULL), OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL), OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL), - OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.2", NULL), + OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL), {}, }; diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index b3982c867c9c..b4f1f902ce6d 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c @@ -307,49 +307,7 @@ static struct i2c_board_info i2c1_devs[] __initdata = { }; /* TSP */ -static u8 mxt_init_vals[] = { - /* MXT_GEN_COMMAND(6) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_GEN_POWER(7) */ - 0x20, 0xff, 0x32, - /* MXT_GEN_ACQUIRE(8) */ - 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23, - /* MXT_TOUCH_MULTI(9) */ - 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, - /* MXT_TOUCH_KEYARRAY(15) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, - /* MXT_SPT_GPIOPWM(19) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_PROCI_GRIPFACE(20) */ - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04, - 0x0f, 0x0a, - /* MXT_PROCG_NOISE(22) */ - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00, - 0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03, - /* MXT_TOUCH_PROXIMITY(23) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_PROCI_ONETOUCH(24) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_SPT_SELFTEST(25) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - /* MXT_PROCI_TWOTOUCH(27) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* MXT_SPT_CTECONFIG(28) */ - 0x00, 0x00, 0x02, 0x08, 0x10, 0x00, -}; - static struct mxt_platform_data mxt_platform_data = { - .config = mxt_init_vals, - .config_length = ARRAY_SIZE(mxt_init_vals), - .x_line = 18, .y_line = 11, .x_size = 1024, @@ -571,7 +529,7 @@ static struct regulator_init_data __initdata max8997_ldo7_data = { static struct regulator_init_data __initdata max8997_ldo8_data = { .constraints = { - .name = "VUSB/VDAC_3.3V_C210", + .name = "VUSB+VDAC_3.3V_C210", .min_uV = 3300000, .max_uV = 3300000, .valid_ops_mask = REGULATOR_CHANGE_STATUS, @@ -1347,6 +1305,7 @@ static struct platform_device *nuri_devices[] __initdata = { static void __init nuri_map_io(void) { + clk_xusbxti.rate = 24000000; exynos_init_io(NULL, 0); s3c24xx_init_clocks(24000000); s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs)); @@ -1379,7 +1338,6 @@ static void __init nuri_machine_init(void) nuri_camera_init(); nuri_ehci_init(); - clk_xusbxti.rate = 24000000; /* Last */ platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices)); diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c index 6bb9dbdd73fd..7ebf79c2ab34 100644 --- a/arch/arm/mach-exynos/mach-universal_c210.c +++ b/arch/arm/mach-exynos/mach-universal_c210.c @@ -29,6 +29,7 @@ #include <asm/mach-types.h> #include <plat/regs-serial.h> +#include <plat/clock.h> #include <plat/cpu.h> #include <plat/devs.h> #include <plat/iic.h> @@ -1057,6 +1058,7 @@ static struct platform_device *universal_devices[] __initdata = { static void __init universal_map_io(void) { + clk_xusbxti.rate = 24000000; exynos_init_io(NULL, 0); s3c24xx_init_clocks(24000000); s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs)); diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c index 3698a370d636..26aac363a064 100644 --- a/arch/arm/mach-msm/board-halibut.c +++ b/arch/arm/mach-msm/board-halibut.c @@ -86,9 +86,6 @@ static void __init halibut_init(void) static void __init halibut_fixup(struct tag *tags, char **cmdline, struct meminfo *mi) { - mi->nr_banks=1; - mi->bank[0].start = PHYS_OFFSET; - mi->bank[0].size = (101*1024*1024); } static void __init halibut_map_io(void) diff --git a/arch/arm/mach-msm/board-trout-panel.c b/arch/arm/mach-msm/board-trout-panel.c index 25105c1027fe..89bf6b426699 100644 --- a/arch/arm/mach-msm/board-trout-panel.c +++ b/arch/arm/mach-msm/board-trout-panel.c @@ -12,6 +12,7 @@ #include <asm/io.h> #include <asm/mach-types.h> +#include <asm/system_info.h> #include <mach/msm_fb.h> #include <mach/vreg.h> diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c index 5414f76ec0a9..d4060a37e23d 100644 --- a/arch/arm/mach-msm/board-trout.c +++ b/arch/arm/mach-msm/board-trout.c @@ -19,6 +19,7 @@ #include <linux/platform_device.h> #include <linux/clkdev.h> +#include <asm/system_info.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> diff --git a/arch/arm/mach-msm/proc_comm.c b/arch/arm/mach-msm/proc_comm.c index 67e701c7f183..9980dc736e7b 100644 --- a/arch/arm/mach-msm/proc_comm.c +++ b/arch/arm/mach-msm/proc_comm.c @@ -121,7 +121,7 @@ int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2) * and unknown state. This function should be called early to * wait on the ARM9. */ -void __init proc_comm_boot_wait(void) +void __devinit proc_comm_boot_wait(void) { void __iomem *base = MSM_SHARED_RAM_BASE; diff --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c index 7072e0d651b1..3d9d746b221a 100644 --- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c +++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c @@ -165,83 +165,3 @@ int omap2_select_table_rate(struct clk *clk, unsigned long rate) return 0; } - -#ifdef CONFIG_CPU_FREQ -/* - * Walk PRCM rate table and fillout cpufreq freq_table - * XXX This should be replaced by an OPP layer in the near future - */ -static struct cpufreq_frequency_table *freq_table; - -void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table) -{ - const struct prcm_config *prcm; - int i = 0; - int tbl_sz = 0; - - if (!cpu_is_omap24xx()) - return; - - for (prcm = rate_table; prcm->mpu_speed; prcm++) { - if (!(prcm->flags & cpu_mask)) - continue; - if (prcm->xtal_speed != sclk->rate) - continue; - - /* don't put bypass rates in table */ - if (prcm->dpll_speed == prcm->xtal_speed) - continue; - - tbl_sz++; - } - - /* - * XXX Ensure that we're doing what CPUFreq expects for this error - * case and the following one - */ - if (tbl_sz == 0) { - pr_warning("%s: no matching entries in rate_table\n", - __func__); - return; - } - - /* Include the CPUFREQ_TABLE_END terminator entry */ - tbl_sz++; - - freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) * tbl_sz, - GFP_ATOMIC); - if (!freq_table) { - pr_err("%s: could not kzalloc frequency table\n", __func__); - return; - } - - for (prcm = rate_table; prcm->mpu_speed; prcm++) { - if (!(prcm->flags & cpu_mask)) - continue; - if (prcm->xtal_speed != sclk->rate) - continue; - - /* don't put bypass rates in table */ - if (prcm->dpll_speed == prcm->xtal_speed) - continue; - - freq_table[i].index = i; - freq_table[i].frequency = prcm->mpu_speed / 1000; - i++; - } - - freq_table[i].index = i; - freq_table[i].frequency = CPUFREQ_TABLE_END; - - *table = &freq_table[0]; -} - -void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) -{ - if (!cpu_is_omap24xx()) - return; - - kfree(freq_table); -} - -#endif diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index f57ed5baeccf..d9f4931513f9 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -536,10 +536,5 @@ struct clk_functions omap2_clk_functions = { .clk_set_rate = omap2_clk_set_rate, .clk_set_parent = omap2_clk_set_parent, .clk_disable_unused = omap2_clk_disable_unused, -#ifdef CONFIG_CPU_FREQ - /* These will be removed when the OPP code is integrated */ - .clk_init_cpufreq_table = omap2_clk_init_cpufreq_table, - .clk_exit_cpufreq_table = omap2_clk_exit_cpufreq_table, -#endif }; diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index b8c2a686481c..a1bb23a23351 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -146,14 +146,6 @@ extern const struct clksel_rate gpt_sys_rates[]; extern const struct clksel_rate gfx_l3_rates[]; extern const struct clksel_rate dsp_ick_rates[]; -#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ) -extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table); -extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table); -#else -#define omap2_clk_init_cpufreq_table 0 -#define omap2_clk_exit_cpufreq_table 0 -#endif - extern const struct clkops clkops_omap2_iclk_dflt_wait; extern const struct clkops clkops_omap2_iclk_dflt; extern const struct clkops clkops_omap2_iclk_idle_only; diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c index 86ce62f66190..b8337e248b09 100644 --- a/arch/arm/mach-s5pv210/dma.c +++ b/arch/arm/mach-s5pv210/dma.c @@ -33,8 +33,6 @@ #include <mach/irqs.h> #include <mach/dma.h> -static u64 dma_dmamask = DMA_BIT_MASK(32); - static u8 pdma0_peri[] = { DMACH_UART0_RX, DMACH_UART0_TX, diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index a9ea64e0da0d..48d018f2332b 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -484,8 +484,8 @@ static struct wm8994_pdata wm8994_platform_data = { .gpio_defaults[8] = 0x0100, .gpio_defaults[9] = 0x0100, .gpio_defaults[10] = 0x0100, - .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */ - .ldo[1] = { 0, NULL, &wm8994_ldo2_data }, + .ldo[0] = { S5PV210_MP03(6), &wm8994_ldo1_data }, /* XM0FRNB_2 */ + .ldo[1] = { 0, &wm8994_ldo2_data }, }; /* GPIO I2C PMIC */ diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index 2cf5ed75f390..a8933de3d627 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -674,8 +674,8 @@ static struct wm8994_pdata wm8994_platform_data = { .gpio_defaults[8] = 0x0100, .gpio_defaults[9] = 0x0100, .gpio_defaults[10] = 0x0100, - .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */ - .ldo[1] = { 0, NULL, &wm8994_ldo2_data }, + .ldo[0] = { S5PV210_MP03(6), &wm8994_ldo1_data }, /* XM0FRNB_2 */ + .ldo[1] = { 0, &wm8994_ldo2_data }, }; /* GPIO I2C PMIC */ diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 7edef9121632..7c8a7d8467bf 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -723,7 +723,7 @@ config CPU_HIGH_VECTOR bool "Select the High exception vector" help Say Y here to select high exception vector(0xFFFF0000~). - The exception vector can be vary depending on the platform + The exception vector can vary depending on the platform design in nommu mode. If your platform needs to select high exception vector, say Y. Otherwise or if you are unsure, say N, and the low exception diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 9055b5a84ec5..f07467533365 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -320,7 +320,7 @@ retry: */ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr); - if (flags & FAULT_FLAG_ALLOW_RETRY) { + if (!(fault & VM_FAULT_ERROR) && flags & FAULT_FLAG_ALLOW_RETRY) { if (fault & VM_FAULT_MAJOR) { tsk->maj_flt++; perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 6486d2f253cd..d51225f90ae2 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -13,6 +13,7 @@ #include <asm/sections.h> #include <asm/page.h> #include <asm/setup.h> +#include <asm/traps.h> #include <asm/mach/arch.h> #include "mm.h" @@ -39,6 +40,7 @@ void __init sanity_check_meminfo(void) */ void __init paging_init(struct machine_desc *mdesc) { + early_trap_init((void *)CONFIG_VECTORS_BASE); bootmem_init(); } diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index f1c8486f7501..c2e2b66f72b5 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -255,6 +255,18 @@ __v7_setup: mcr p15, 0, r5, c10, c2, 0 @ write PRRR mcr p15, 0, r6, c10, c2, 1 @ write NMRR #endif +#ifndef CONFIG_ARM_THUMBEE + mrc p15, 0, r0, c0, c1, 0 @ read ID_PFR0 for ThumbEE + and r0, r0, #(0xf << 12) @ ThumbEE enabled field + teq r0, #(1 << 12) @ check if ThumbEE is present + bne 1f + mov r5, #0 + mcr p14, 6, r5, c1, c0, 0 @ Initialize TEEHBR to 0 + mrc p14, 6, r0, c0, c0, 0 @ load TEECR + orr r0, r0, #1 @ set the 1st bit in order to + mcr p14, 6, r0, c0, c0, 0 @ stop userspace TEEHBR access +1: +#endif adr r5, v7_crval ldmia r5, {r5, r6} #ifdef CONFIG_CPU_ENDIAN_BE8 diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 8506cbb7fea4..62ec5c452792 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -398,32 +398,6 @@ struct clk dummy_ck = { .ops = &clkops_null, }; -#ifdef CONFIG_CPU_FREQ -void clk_init_cpufreq_table(struct cpufreq_frequency_table **table) -{ - unsigned long flags; - - if (!arch_clock || !arch_clock->clk_init_cpufreq_table) - return; - - spin_lock_irqsave(&clockfw_lock, flags); - arch_clock->clk_init_cpufreq_table(table); - spin_unlock_irqrestore(&clockfw_lock, flags); -} - -void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) -{ - unsigned long flags; - - if (!arch_clock || !arch_clock->clk_exit_cpufreq_table) - return; - - spin_lock_irqsave(&clockfw_lock, flags); - arch_clock->clk_exit_cpufreq_table(table); - spin_unlock_irqrestore(&clockfw_lock, flags); -} -#endif - /* * */ diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index 240a7b9fd946..d0ef57c1d71b 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h @@ -272,8 +272,6 @@ struct clk { #endif }; -struct cpufreq_frequency_table; - struct clk_functions { int (*clk_enable)(struct clk *clk); void (*clk_disable)(struct clk *clk); @@ -283,10 +281,6 @@ struct clk_functions { void (*clk_allow_idle)(struct clk *clk); void (*clk_deny_idle)(struct clk *clk); void (*clk_disable_unused)(struct clk *clk); -#ifdef CONFIG_CPU_FREQ - void (*clk_init_cpufreq_table)(struct cpufreq_frequency_table **); - void (*clk_exit_cpufreq_table)(struct cpufreq_frequency_table **); -#endif }; extern int mpurate; @@ -301,10 +295,6 @@ extern void recalculate_root_clocks(void); extern unsigned long followparent_recalc(struct clk *clk); extern void clk_enable_init_clocks(void); unsigned long omap_fixed_divisor_recalc(struct clk *clk); -#ifdef CONFIG_CPU_FREQ -extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table); -extern void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table); -#endif extern struct clk *omap_clk_get_by_name(const char *name); extern int omap_clk_enable_autoidle_all(void); extern int omap_clk_disable_autoidle_all(void); diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 71553f410016..a0ffc77da809 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -302,6 +302,7 @@ comment "Power management" config SAMSUNG_PM_DEBUG bool "S3C2410 PM Suspend debug" depends on PM + select DEBUG_LL help Say Y here if you want verbose debugging from the PM Suspend and Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt> diff --git a/arch/c6x/include/asm/irq.h b/arch/c6x/include/asm/irq.h index f13b78d5e1ca..ab4577f93d96 100644 --- a/arch/c6x/include/asm/irq.h +++ b/arch/c6x/include/asm/irq.h @@ -42,10 +42,6 @@ /* This number is used when no interrupt has been assigned */ #define NO_IRQ 0 -struct irq_data; -extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d); -extern irq_hw_number_t virq_to_hw(unsigned int virq); - extern void __init init_pic_c64xplus(void); extern void init_IRQ(void); diff --git a/arch/c6x/kernel/irq.c b/arch/c6x/kernel/irq.c index 65b8ddf54b44..c90fb5e82ad7 100644 --- a/arch/c6x/kernel/irq.c +++ b/arch/c6x/kernel/irq.c @@ -130,16 +130,3 @@ int arch_show_interrupts(struct seq_file *p, int prec) seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count); return 0; } - -irq_hw_number_t irqd_to_hwirq(struct irq_data *d) -{ - return d->hwirq; -} -EXPORT_SYMBOL_GPL(irqd_to_hwirq); - -irq_hw_number_t virq_to_hw(unsigned int virq) -{ - struct irq_data *irq_data = irq_get_irq_data(virq); - return WARN_ON(!irq_data) ? 0 : irq_data->hwirq; -} -EXPORT_SYMBOL_GPL(virq_to_hw); diff --git a/arch/ia64/include/asm/cmpxchg.h b/arch/ia64/include/asm/cmpxchg.h index 4c96187e2049..4f37dbbb8640 100644 --- a/arch/ia64/include/asm/cmpxchg.h +++ b/arch/ia64/include/asm/cmpxchg.h @@ -1 +1,147 @@ -#include <asm/intrinsics.h> +#ifndef _ASM_IA64_CMPXCHG_H +#define _ASM_IA64_CMPXCHG_H + +/* + * Compare/Exchange, forked from asm/intrinsics.h + * which was: + * + * Copyright (C) 2002-2003 Hewlett-Packard Co + * David Mosberger-Tang <davidm@hpl.hp.com> + */ + +#ifndef __ASSEMBLY__ + +#include <linux/types.h> +/* include compiler specific intrinsics */ +#include <asm/ia64regs.h> +#ifdef __INTEL_COMPILER +# include <asm/intel_intrin.h> +#else +# include <asm/gcc_intrin.h> +#endif + +/* + * This function doesn't exist, so you'll get a linker error if + * something tries to do an invalid xchg(). + */ +extern void ia64_xchg_called_with_bad_pointer(void); + +#define __xchg(x, ptr, size) \ +({ \ + unsigned long __xchg_result; \ + \ + switch (size) { \ + case 1: \ + __xchg_result = ia64_xchg1((__u8 *)ptr, x); \ + break; \ + \ + case 2: \ + __xchg_result = ia64_xchg2((__u16 *)ptr, x); \ + break; \ + \ + case 4: \ + __xchg_result = ia64_xchg4((__u32 *)ptr, x); \ + break; \ + \ + case 8: \ + __xchg_result = ia64_xchg8((__u64 *)ptr, x); \ + break; \ + default: \ + ia64_xchg_called_with_bad_pointer(); \ + } \ + __xchg_result; \ +}) + +#define xchg(ptr, x) \ +((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr)))) + +/* + * Atomic compare and exchange. Compare OLD with MEM, if identical, + * store NEW in MEM. Return the initial value in MEM. Success is + * indicated by comparing RETURN with OLD. + */ + +#define __HAVE_ARCH_CMPXCHG 1 + +/* + * This function doesn't exist, so you'll get a linker error + * if something tries to do an invalid cmpxchg(). + */ +extern long ia64_cmpxchg_called_with_bad_pointer(void); + +#define ia64_cmpxchg(sem, ptr, old, new, size) \ +({ \ + __u64 _o_, _r_; \ + \ + switch (size) { \ + case 1: \ + _o_ = (__u8) (long) (old); \ + break; \ + case 2: \ + _o_ = (__u16) (long) (old); \ + break; \ + case 4: \ + _o_ = (__u32) (long) (old); \ + break; \ + case 8: \ + _o_ = (__u64) (long) (old); \ + break; \ + default: \ + break; \ + } \ + switch (size) { \ + case 1: \ + _r_ = ia64_cmpxchg1_##sem((__u8 *) ptr, new, _o_); \ + break; \ + \ + case 2: \ + _r_ = ia64_cmpxchg2_##sem((__u16 *) ptr, new, _o_); \ + break; \ + \ + case 4: \ + _r_ = ia64_cmpxchg4_##sem((__u32 *) ptr, new, _o_); \ + break; \ + \ + case 8: \ + _r_ = ia64_cmpxchg8_##sem((__u64 *) ptr, new, _o_); \ + break; \ + \ + default: \ + _r_ = ia64_cmpxchg_called_with_bad_pointer(); \ + break; \ + } \ + (__typeof__(old)) _r_; \ +}) + +#define cmpxchg_acq(ptr, o, n) \ + ia64_cmpxchg(acq, (ptr), (o), (n), sizeof(*(ptr))) +#define cmpxchg_rel(ptr, o, n) \ + ia64_cmpxchg(rel, (ptr), (o), (n), sizeof(*(ptr))) + +/* for compatibility with other platforms: */ +#define cmpxchg(ptr, o, n) cmpxchg_acq((ptr), (o), (n)) +#define cmpxchg64(ptr, o, n) cmpxchg_acq((ptr), (o), (n)) + +#define cmpxchg_local cmpxchg +#define cmpxchg64_local cmpxchg64 + +#ifdef CONFIG_IA64_DEBUG_CMPXCHG +# define CMPXCHG_BUGCHECK_DECL int _cmpxchg_bugcheck_count = 128; +# define CMPXCHG_BUGCHECK(v) \ +do { \ + if (_cmpxchg_bugcheck_count-- <= 0) { \ + void *ip; \ + extern int printk(const char *fmt, ...); \ + ip = (void *) ia64_getreg(_IA64_REG_IP); \ + printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));\ + break; \ + } \ +} while (0) +#else /* !CONFIG_IA64_DEBUG_CMPXCHG */ +# define CMPXCHG_BUGCHECK_DECL +# define CMPXCHG_BUGCHECK(v) +#endif /* !CONFIG_IA64_DEBUG_CMPXCHG */ + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_IA64_CMPXCHG_H */ diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h index 0ab82cc2dc8f..d2bf1fd5e44f 100644 --- a/arch/ia64/include/asm/futex.h +++ b/arch/ia64/include/asm/futex.h @@ -106,15 +106,16 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, return -EFAULT; { - register unsigned long r8 __asm ("r8") = 0; + register unsigned long r8 __asm ("r8"); unsigned long prev; __asm__ __volatile__( " mf;; \n" - " mov ar.ccv=%3;; \n" - "[1:] cmpxchg4.acq %0=[%1],%2,ar.ccv \n" + " mov %0=r0 \n" + " mov ar.ccv=%4;; \n" + "[1:] cmpxchg4.acq %1=[%2],%3,ar.ccv \n" " .xdata4 \"__ex_table\", 1b-., 2f-. \n" "[2:]" - : "=r" (prev) + : "=r" (r8), "=r" (prev) : "r" (uaddr), "r" (newval), "rO" ((long) (unsigned) oldval) : "memory"); diff --git a/arch/ia64/include/asm/intrinsics.h b/arch/ia64/include/asm/intrinsics.h index e4076b511829..d129e367e764 100644 --- a/arch/ia64/include/asm/intrinsics.h +++ b/arch/ia64/include/asm/intrinsics.h @@ -18,6 +18,7 @@ #else # include <asm/gcc_intrin.h> #endif +#include <asm/cmpxchg.h> #define ia64_native_get_psr_i() (ia64_native_getreg(_IA64_REG_PSR) & IA64_PSR_I) @@ -81,119 +82,6 @@ extern unsigned long __bad_increment_for_ia64_fetch_and_add (void); #define ia64_fetch_and_add(i,v) (ia64_fetchadd(i, v, rel) + (i)) /* return new value */ -/* - * This function doesn't exist, so you'll get a linker error if - * something tries to do an invalid xchg(). - */ -extern void ia64_xchg_called_with_bad_pointer (void); - -#define __xchg(x,ptr,size) \ -({ \ - unsigned long __xchg_result; \ - \ - switch (size) { \ - case 1: \ - __xchg_result = ia64_xchg1((__u8 *)ptr, x); \ - break; \ - \ - case 2: \ - __xchg_result = ia64_xchg2((__u16 *)ptr, x); \ - break; \ - \ - case 4: \ - __xchg_result = ia64_xchg4((__u32 *)ptr, x); \ - break; \ - \ - case 8: \ - __xchg_result = ia64_xchg8((__u64 *)ptr, x); \ - break; \ - default: \ - ia64_xchg_called_with_bad_pointer(); \ - } \ - __xchg_result; \ -}) - -#define xchg(ptr,x) \ - ((__typeof__(*(ptr))) __xchg ((unsigned long) (x), (ptr), sizeof(*(ptr)))) - -/* - * Atomic compare and exchange. Compare OLD with MEM, if identical, - * store NEW in MEM. Return the initial value in MEM. Success is - * indicated by comparing RETURN with OLD. - */ - -#define __HAVE_ARCH_CMPXCHG 1 - -/* - * This function doesn't exist, so you'll get a linker error - * if something tries to do an invalid cmpxchg(). - */ -extern long ia64_cmpxchg_called_with_bad_pointer (void); - -#define ia64_cmpxchg(sem,ptr,old,new,size) \ -({ \ - __u64 _o_, _r_; \ - \ - switch (size) { \ - case 1: _o_ = (__u8 ) (long) (old); break; \ - case 2: _o_ = (__u16) (long) (old); break; \ - case 4: _o_ = (__u32) (long) (old); break; \ - case 8: _o_ = (__u64) (long) (old); break; \ - default: break; \ - } \ - switch (size) { \ - case 1: \ - _r_ = ia64_cmpxchg1_##sem((__u8 *) ptr, new, _o_); \ - break; \ - \ - case 2: \ - _r_ = ia64_cmpxchg2_##sem((__u16 *) ptr, new, _o_); \ - break; \ - \ - case 4: \ - _r_ = ia64_cmpxchg4_##sem((__u32 *) ptr, new, _o_); \ - break; \ - \ - case 8: \ - _r_ = ia64_cmpxchg8_##sem((__u64 *) ptr, new, _o_); \ - break; \ - \ - default: \ - _r_ = ia64_cmpxchg_called_with_bad_pointer(); \ - break; \ - } \ - (__typeof__(old)) _r_; \ -}) - -#define cmpxchg_acq(ptr, o, n) \ - ia64_cmpxchg(acq, (ptr), (o), (n), sizeof(*(ptr))) -#define cmpxchg_rel(ptr, o, n) \ - ia64_cmpxchg(rel, (ptr), (o), (n), sizeof(*(ptr))) - -/* for compatibility with other platforms: */ -#define cmpxchg(ptr, o, n) cmpxchg_acq((ptr), (o), (n)) -#define cmpxchg64(ptr, o, n) cmpxchg_acq((ptr), (o), (n)) - -#define cmpxchg_local cmpxchg -#define cmpxchg64_local cmpxchg64 - -#ifdef CONFIG_IA64_DEBUG_CMPXCHG -# define CMPXCHG_BUGCHECK_DECL int _cmpxchg_bugcheck_count = 128; -# define CMPXCHG_BUGCHECK(v) \ - do { \ - if (_cmpxchg_bugcheck_count-- <= 0) { \ - void *ip; \ - extern int printk(const char *fmt, ...); \ - ip = (void *) ia64_getreg(_IA64_REG_IP); \ - printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v)); \ - break; \ - } \ - } while (0) -#else /* !CONFIG_IA64_DEBUG_CMPXCHG */ -# define CMPXCHG_BUGCHECK_DECL -# define CMPXCHG_BUGCHECK(v) -#endif /* !CONFIG_IA64_DEBUG_CMPXCHG */ - #endif #ifdef __KERNEL__ diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h index cf417e510736..e648af92ced1 100644 --- a/arch/powerpc/include/asm/irq.h +++ b/arch/powerpc/include/asm/irq.h @@ -33,8 +33,6 @@ extern atomic_t ppc_n_lost_interrupts; /* Same thing, used by the generic IRQ code */ #define NR_IRQS_LEGACY NUM_ISA_INTERRUPTS -struct irq_data; -extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d); extern irq_hw_number_t virq_to_hw(unsigned int virq); /** diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 3e57a00b8cba..ba3aeb4bc06a 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -206,40 +206,43 @@ reenable_mmu: /* re-enable mmu so we can */ andi. r10,r10,MSR_EE /* Did EE change? */ beq 1f - /* Save handler and return address into the 2 unused words - * of the STACK_FRAME_OVERHEAD (sneak sneak sneak). Everything - * else can be recovered from the pt_regs except r3 which for - * normal interrupts has been set to pt_regs and for syscalls - * is an argument, so we temporarily use ORIG_GPR3 to save it - */ - stw r9,8(r1) - stw r11,12(r1) - stw r3,ORIG_GPR3(r1) /* * The trace_hardirqs_off will use CALLER_ADDR0 and CALLER_ADDR1. * If from user mode there is only one stack frame on the stack, and * accessing CALLER_ADDR1 will cause oops. So we need create a dummy * stack frame to make trace_hardirqs_off happy. + * + * This is handy because we also need to save a bunch of GPRs, + * r3 can be different from GPR3(r1) at this point, r9 and r11 + * contains the old MSR and handler address respectively, + * r4 & r5 can contain page fault arguments that need to be passed + * along as well. r12, CCR, CTR, XER etc... are left clobbered as + * they aren't useful past this point (aren't syscall arguments), + * the rest is restored from the exception frame. */ + stwu r1,-32(r1) + stw r9,8(r1) + stw r11,12(r1) + stw r3,16(r1) + stw r4,20(r1) + stw r5,24(r1) andi. r12,r12,MSR_PR - beq 11f - stwu r1,-16(r1) + b 11f bl trace_hardirqs_off - addi r1,r1,16 b 12f - 11: bl trace_hardirqs_off 12: + lwz r5,24(r1) + lwz r4,20(r1) + lwz r3,16(r1) + lwz r11,12(r1) + lwz r9,8(r1) + addi r1,r1,32 lwz r0,GPR0(r1) - lwz r3,ORIG_GPR3(r1) - lwz r4,GPR4(r1) - lwz r5,GPR5(r1) lwz r6,GPR6(r1) lwz r7,GPR7(r1) lwz r8,GPR8(r1) - lwz r9,8(r1) - lwz r11,12(r1) 1: mtctr r11 mtlr r9 bctr /* jump to handler */ diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 243dbabfe74d..5ec1b2354ca6 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -560,12 +560,6 @@ void do_softirq(void) local_irq_restore(flags); } -irq_hw_number_t irqd_to_hwirq(struct irq_data *d) -{ - return d->hwirq; -} -EXPORT_SYMBOL_GPL(irqd_to_hwirq); - irq_hw_number_t virq_to_hw(unsigned int virq) { struct irq_data *irq_data = irq_get_irq_data(virq); diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index f88698c0f332..4937c9690090 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1235,7 +1235,7 @@ void __ppc64_runlatch_on(void) ctrl |= CTRL_RUNLATCH; mtspr(SPRN_CTRLT, ctrl); - ti->local_flags |= TLF_RUNLATCH; + ti->local_flags |= _TLF_RUNLATCH; } /* Called with hard IRQs off */ @@ -1244,7 +1244,7 @@ void __ppc64_runlatch_off(void) struct thread_info *ti = current_thread_info(); unsigned long ctrl; - ti->local_flags &= ~TLF_RUNLATCH; + ti->local_flags &= ~_TLF_RUNLATCH; ctrl = mfspr(SPRN_CTRLF); ctrl &= ~CTRL_RUNLATCH; diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index db360fc4cf0e..d09f3e8e6867 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c @@ -392,7 +392,7 @@ static int axon_msi_probe(struct platform_device *device) } memset(msic->fifo_virt, 0xff, MSIC_FIFO_SIZE_BYTES); - msic->irq_domain = irq_domain_add_nomap(dn, &msic_host_ops, msic); + msic->irq_domain = irq_domain_add_nomap(dn, 0, &msic_host_ops, msic); if (!msic->irq_domain) { printk(KERN_ERR "axon_msi: couldn't allocate irq_domain for %s\n", dn->full_name); diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c index e5c3a2c6090d..f9a48af335cb 100644 --- a/arch/powerpc/platforms/cell/beat_interrupt.c +++ b/arch/powerpc/platforms/cell/beat_interrupt.c @@ -239,7 +239,7 @@ void __init beatic_init_IRQ(void) ppc_md.get_irq = beatic_get_irq; /* Allocate an irq host */ - beatic_host = irq_domain_add_nomap(NULL, &beatic_pic_host_ops, NULL); + beatic_host = irq_domain_add_nomap(NULL, 0, &beatic_pic_host_ops, NULL); BUG_ON(beatic_host == NULL); irq_set_default_host(beatic_host); } diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index a81e5a88fbdf..b4ddaa3fbb29 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -192,7 +192,7 @@ static int psurge_secondary_ipi_init(void) { int rc = -ENOMEM; - psurge_host = irq_domain_add_nomap(NULL, &psurge_host_ops, NULL); + psurge_host = irq_domain_add_nomap(NULL, 0, &psurge_host_ops, NULL); if (psurge_host) psurge_secondary_virq = irq_create_direct_mapping(psurge_host); diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index 2a4ff86cc21f..5f3b23220b8e 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c @@ -753,9 +753,8 @@ void __init ps3_init_IRQ(void) unsigned cpu; struct irq_domain *host; - host = irq_domain_add_nomap(NULL, &ps3_host_ops, NULL); + host = irq_domain_add_nomap(NULL, PS3_PLUG_MAX + 1, &ps3_host_ops, NULL); irq_set_default_host(host); - irq_set_virq_count(PS3_PLUG_MAX + 1); for_each_possible_cpu(cpu) { struct ps3_private *pd = &per_cpu(ps3_private, cpu); diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 2b7c0fbe578e..9015060919a0 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -90,7 +90,6 @@ config S390 select HAVE_KERNEL_XZ select HAVE_ARCH_MUTEX_CPU_RELAX select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 - select HAVE_RCU_TABLE_FREE if SMP select ARCH_SAVE_PAGE_KEYS if HIBERNATION select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 6cf8e26b3137..1957a9dd256d 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -1,8 +1,12 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y +CONFIG_FHANDLE=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y CONFIG_AUDIT=y -CONFIG_RCU_TRACE=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_CGROUPS=y @@ -14,16 +18,22 @@ CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_BLK_CGROUP=y +CONFIG_NAMESPACES=y CONFIG_BLK_DEV_INITRD=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_EXPERT=y # CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y CONFIG_PROFILING=y CONFIG_OPROFILE=y CONFIG_KPROBES=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_IBM_PARTITION=y CONFIG_DEFAULT_DEADLINE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -34,18 +44,15 @@ CONFIG_KSM=y CONFIG_BINFMT_MISC=m CONFIG_CMM=m CONFIG_HZ_100=y -CONFIG_KEXEC=y -CONFIG_PM=y +CONFIG_CRASH_DUMP=y CONFIG_HIBERNATION=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_NET_KEY=y -CONFIG_AFIUCV=m CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_INET_LRO is not set CONFIG_IPV6=y -CONFIG_NET_SCTPPROBE=m CONFIG_L2TP=m CONFIG_L2TP_DEBUGFS=m CONFIG_VLAN_8021Q=y @@ -84,15 +91,14 @@ CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y CONFIG_ZFCP=y -CONFIG_ZFCP_DIF=y CONFIG_NETDEVICES=y -CONFIG_DUMMY=m CONFIG_BONDING=m +CONFIG_DUMMY=m CONFIG_EQUALIZER=m CONFIG_TUN=m -CONFIG_NET_ETHERNET=y CONFIG_VIRTIO_NET=y CONFIG_RAW_DRIVER=m +CONFIG_VIRTIO_BALLOON=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set @@ -103,27 +109,21 @@ CONFIG_PROC_KCORE=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y # CONFIG_NETWORK_FILESYSTEMS is not set -CONFIG_PARTITION_ADVANCED=y -CONFIG_IBM_PARTITION=y -CONFIG_DLM=m CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_KERNEL=y CONFIG_TIMER_STATS=y CONFIG_PROVE_LOCKING=y CONFIG_PROVE_RCU=y CONFIG_LOCK_STAT=y CONFIG_DEBUG_LOCKDEP=y -CONFIG_DEBUG_SPINLOCK_SLEEP=y CONFIG_DEBUG_LIST=y CONFIG_DEBUG_NOTIFIERS=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_RCU_TRACE=y CONFIG_KPROBES_SANITY_TEST=y CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y CONFIG_CPU_NOTIFIER_ERROR_INJECT=m CONFIG_LATENCYTOP=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_DEBUG_PAGEALLOC=y -# CONFIG_FTRACE is not set +CONFIG_BLK_DEV_IO_TRACE=y # CONFIG_STRICT_DEVMEM is not set CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_CRYPTD=m @@ -173,4 +173,3 @@ CONFIG_CRYPTO_SHA512_S390=m CONFIG_CRYPTO_DES_S390=m CONFIG_CRYPTO_AES_S390=m CONFIG_CRC7=m -CONFIG_VIRTIO_BALLOON=y diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h index 1e5b27edc0c9..2ee66a65f2d4 100644 --- a/arch/s390/include/asm/facility.h +++ b/arch/s390/include/asm/facility.h @@ -38,12 +38,11 @@ static inline void stfle(u64 *stfle_fac_list, int size) unsigned long nr; preempt_disable(); - S390_lowcore.stfl_fac_list = 0; asm volatile( " .insn s,0xb2b10000,0(0)\n" /* stfl */ "0:\n" EX_TABLE(0b, 0b) - : "=m" (S390_lowcore.stfl_fac_list)); + : "+m" (S390_lowcore.stfl_fac_list)); nr = 4; /* bytes stored by stfl */ memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); if (S390_lowcore.stfl_fac_list & 0x01000000) { diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h index 8eef9b5b3cf4..78e3041919de 100644 --- a/arch/s390/include/asm/pgalloc.h +++ b/arch/s390/include/asm/pgalloc.h @@ -22,10 +22,7 @@ void crst_table_free(struct mm_struct *, unsigned long *); unsigned long *page_table_alloc(struct mm_struct *, unsigned long); void page_table_free(struct mm_struct *, unsigned long *); -#ifdef CONFIG_HAVE_RCU_TABLE_FREE void page_table_free_rcu(struct mmu_gather *, unsigned long *); -void __tlb_remove_table(void *_table); -#endif static inline void clear_table(unsigned long *s, unsigned long val, size_t n) { diff --git a/arch/s390/include/asm/swab.h b/arch/s390/include/asm/swab.h index 6bdee21c077e..a3e4ebb32090 100644 --- a/arch/s390/include/asm/swab.h +++ b/arch/s390/include/asm/swab.h @@ -77,7 +77,7 @@ static inline __u16 __arch_swab16p(const __u16 *x) asm volatile( #ifndef __s390x__ - " icm %0,2,%O+1(%R1)\n" + " icm %0,2,%O1+1(%R1)\n" " ic %0,%1\n" : "=&d" (result) : "Q" (*x) : "cc"); #else /* __s390x__ */ diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h index c687a2c83462..775a5eea8f9e 100644 --- a/arch/s390/include/asm/tlb.h +++ b/arch/s390/include/asm/tlb.h @@ -30,14 +30,10 @@ struct mmu_gather { struct mm_struct *mm; -#ifdef CONFIG_HAVE_RCU_TABLE_FREE struct mmu_table_batch *batch; -#endif unsigned int fullmm; - unsigned int need_flush; }; -#ifdef CONFIG_HAVE_RCU_TABLE_FREE struct mmu_table_batch { struct rcu_head rcu; unsigned int nr; @@ -49,7 +45,6 @@ struct mmu_table_batch { extern void tlb_table_flush(struct mmu_gather *tlb); extern void tlb_remove_table(struct mmu_gather *tlb, void *table); -#endif static inline void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, @@ -57,29 +52,20 @@ static inline void tlb_gather_mmu(struct mmu_gather *tlb, { tlb->mm = mm; tlb->fullmm = full_mm_flush; - tlb->need_flush = 0; -#ifdef CONFIG_HAVE_RCU_TABLE_FREE tlb->batch = NULL; -#endif if (tlb->fullmm) __tlb_flush_mm(mm); } static inline void tlb_flush_mmu(struct mmu_gather *tlb) { - if (!tlb->need_flush) - return; - tlb->need_flush = 0; - __tlb_flush_mm(tlb->mm); -#ifdef CONFIG_HAVE_RCU_TABLE_FREE tlb_table_flush(tlb); -#endif } static inline void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) { - tlb_flush_mmu(tlb); + tlb_table_flush(tlb); } /* @@ -105,10 +91,8 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, unsigned long address) { -#ifdef CONFIG_HAVE_RCU_TABLE_FREE if (!tlb->fullmm) return page_table_free_rcu(tlb, (unsigned long *) pte); -#endif page_table_free(tlb->mm, (unsigned long *) pte); } @@ -125,10 +109,8 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, #ifdef __s390x__ if (tlb->mm->context.asce_limit <= (1UL << 31)) return; -#ifdef CONFIG_HAVE_RCU_TABLE_FREE if (!tlb->fullmm) return tlb_remove_table(tlb, pmd); -#endif crst_table_free(tlb->mm, (unsigned long *) pmd); #endif } @@ -146,10 +128,8 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, #ifdef __s390x__ if (tlb->mm->context.asce_limit <= (1UL << 42)) return; -#ifdef CONFIG_HAVE_RCU_TABLE_FREE if (!tlb->fullmm) return tlb_remove_table(tlb, pud); -#endif crst_table_free(tlb->mm, (unsigned long *) pud); #endif } diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index c27a0727f930..adccd908ebc7 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -474,9 +474,9 @@ ENTRY(startup_kdump) stck __LC_LAST_UPDATE_CLOCK spt 5f-.LPG0(%r13) mvc __LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13) + xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST #ifndef CONFIG_MARCH_G5 # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10} - xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST .insn s,0xb2b10000,__LC_STFL_FAC_LIST # store facility list tm __LC_STFL_FAC_LIST,0x01 # stfle available ? jz 0f diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 1c2cdd59ccd0..8a22c27219dd 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -118,9 +118,10 @@ asmlinkage void do_softirq(void) "a" (__do_softirq) : "0", "1", "2", "3", "4", "5", "14", "cc", "memory" ); - } else + } else { /* We are already on the async stack. */ __do_softirq(); + } } local_irq_restore(flags); @@ -192,11 +193,12 @@ int unregister_external_interrupt(u16 code, ext_int_handler_t handler) int index = ext_hash(code); spin_lock_irqsave(&ext_int_hash_lock, flags); - list_for_each_entry_rcu(p, &ext_int_hash[index], entry) + list_for_each_entry_rcu(p, &ext_int_hash[index], entry) { if (p->code == code && p->handler == handler) { list_del_rcu(&p->entry); kfree_rcu(p, rcu); } + } spin_unlock_irqrestore(&ext_int_hash_lock, flags); return 0; } @@ -211,9 +213,10 @@ void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code, old_regs = set_irq_regs(regs); irq_enter(); - if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) + if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) { /* Serve timer interrupts first. */ clock_comparator_work(); + } kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; if (ext_code.code != 0x1004) __get_cpu_var(s390_idle).nohz_delay = 1; diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index 46405086479c..cb019f429e88 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -178,7 +178,7 @@ static void cpumf_pmu_enable(struct pmu *pmu) err = lcctl(cpuhw->state); if (err) { pr_err("Enabling the performance measuring unit " - "failed with rc=%lx\n", err); + "failed with rc=%x\n", err); return; } @@ -203,7 +203,7 @@ static void cpumf_pmu_disable(struct pmu *pmu) err = lcctl(inactive); if (err) { pr_err("Disabling the performance measuring unit " - "failed with rc=%lx\n", err); + "failed with rc=%x\n", err); return; } diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c index 7bb15fcca75e..e1335dc2b1b7 100644 --- a/arch/s390/mm/maccess.c +++ b/arch/s390/mm/maccess.c @@ -61,21 +61,14 @@ long probe_kernel_write(void *dst, const void *src, size_t size) return copied < 0 ? -EFAULT : 0; } -/* - * Copy memory in real mode (kernel to kernel) - */ -int memcpy_real(void *dest, void *src, size_t count) +static int __memcpy_real(void *dest, void *src, size_t count) { register unsigned long _dest asm("2") = (unsigned long) dest; register unsigned long _len1 asm("3") = (unsigned long) count; register unsigned long _src asm("4") = (unsigned long) src; register unsigned long _len2 asm("5") = (unsigned long) count; - unsigned long flags; int rc = -EFAULT; - if (!count) - return 0; - flags = __arch_local_irq_stnsm(0xf8UL); asm volatile ( "0: mvcle %1,%2,0x0\n" "1: jo 0b\n" @@ -86,7 +79,23 @@ int memcpy_real(void *dest, void *src, size_t count) "+d" (_len2), "=m" (*((long *) dest)) : "m" (*((long *) src)) : "cc", "memory"); - arch_local_irq_restore(flags); + return rc; +} + +/* + * Copy memory in real mode (kernel to kernel) + */ +int memcpy_real(void *dest, void *src, size_t count) +{ + unsigned long flags; + int rc; + + if (!count) + return 0; + local_irq_save(flags); + __arch_local_irq_stnsm(0xfbUL); + rc = __memcpy_real(dest, src, count); + local_irq_restore(flags); return rc; } diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 373adf69b01c..6e765bf00670 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -678,8 +678,6 @@ void page_table_free(struct mm_struct *mm, unsigned long *table) } } -#ifdef CONFIG_HAVE_RCU_TABLE_FREE - static void __page_table_free_rcu(void *table, unsigned bit) { struct page *page; @@ -733,7 +731,66 @@ void __tlb_remove_table(void *_table) free_pages((unsigned long) table, ALLOC_ORDER); } -#endif +static void tlb_remove_table_smp_sync(void *arg) +{ + /* Simply deliver the interrupt */ +} + +static void tlb_remove_table_one(void *table) +{ + /* + * This isn't an RCU grace period and hence the page-tables cannot be + * assumed to be actually RCU-freed. + * + * It is however sufficient for software page-table walkers that rely + * on IRQ disabling. See the comment near struct mmu_table_batch. + */ + smp_call_function(tlb_remove_table_smp_sync, NULL, 1); + __tlb_remove_table(table); +} + +static void tlb_remove_table_rcu(struct rcu_head *head) +{ + struct mmu_table_batch *batch; + int i; + + batch = container_of(head, struct mmu_table_batch, rcu); + + for (i = 0; i < batch->nr; i++) + __tlb_remove_table(batch->tables[i]); + + free_page((unsigned long)batch); +} + +void tlb_table_flush(struct mmu_gather *tlb) +{ + struct mmu_table_batch **batch = &tlb->batch; + + if (*batch) { + __tlb_flush_mm(tlb->mm); + call_rcu_sched(&(*batch)->rcu, tlb_remove_table_rcu); + *batch = NULL; + } +} + +void tlb_remove_table(struct mmu_gather *tlb, void *table) +{ + struct mmu_table_batch **batch = &tlb->batch; + + if (*batch == NULL) { + *batch = (struct mmu_table_batch *) + __get_free_page(GFP_NOWAIT | __GFP_NOWARN); + if (*batch == NULL) { + __tlb_flush_mm(tlb->mm); + tlb_remove_table_one(table); + return; + } + (*batch)->nr = 0; + } + (*batch)->tables[(*batch)->nr++] = table; + if ((*batch)->nr == MAX_TABLE_BATCH) + tlb_table_flush(tlb); +} /* * switch on pgstes for its userspace process (for kvm) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ed2419f7afe5..98405fa24e81 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -695,6 +695,20 @@ config SECCOMP If unsure, say N. +config CC_STACKPROTECTOR + bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" + depends on SUPERH32 && EXPERIMENTAL + help + This option turns on the -fstack-protector GCC feature. This + feature puts, at the beginning of functions, a canary value on + the stack just before the return address, and validates + the value just before actually returning. Stack based buffer + overflows (that need to overwrite this return address) now also + overwrite the canary, which gets detected and the attack is then + neutralized via a kernel panic. + + This feature requires gcc version 4.2 or above. + config SMP bool "Symmetric multi-processing support" depends on SYS_SUPPORTS_SMP diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 3fc0f413777c..24875c8c1514 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -199,6 +199,10 @@ ifeq ($(CONFIG_DWARF_UNWINDER),y) KBUILD_CFLAGS += -fasynchronous-unwind-tables endif +ifeq ($(CONFIG_CC_STACKPROTECTOR),y) + KBUILD_CFLAGS += -fstack-protector +endif + libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y) libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y) diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index d893411022d5..6c96daab499b 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -338,8 +338,6 @@ config SH_APSH4AD0A help Select AP-SH4AD-0A if configuring for an ALPHAPROJECT AP-SH4AD-0A. -endmenu - source "arch/sh/boards/mach-r2d/Kconfig" source "arch/sh/boards/mach-highlander/Kconfig" source "arch/sh/boards/mach-sdk7780/Kconfig" @@ -359,3 +357,5 @@ config SH_MAGIC_PANEL_R2_VERSION endmenu endif + +endmenu diff --git a/arch/sh/include/asm/stackprotector.h b/arch/sh/include/asm/stackprotector.h new file mode 100644 index 000000000000..d9df3a76847c --- /dev/null +++ b/arch/sh/include/asm/stackprotector.h @@ -0,0 +1,27 @@ +#ifndef __ASM_SH_STACKPROTECTOR_H +#define __ASM_SH_STACKPROTECTOR_H + +#include <linux/random.h> +#include <linux/version.h> + +extern unsigned long __stack_chk_guard; + +/* + * Initialize the stackprotector canary value. + * + * NOTE: this must only be called from functions that never return, + * and it must always be inlined. + */ +static __always_inline void boot_init_stack_canary(void) +{ + unsigned long canary; + + /* Try to get a semi random initial value. */ + get_random_bytes(&canary, sizeof(canary)); + canary ^= LINUX_VERSION_CODE; + + current->stack_canary = canary; + __stack_chk_guard = current->stack_canary; +} + +#endif /* __ASM_SH_STACKPROTECTOR_H */ diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 325f98b1736d..f3f03e4c785d 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -2,10 +2,17 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/sched.h> +#include <linux/export.h> +#include <linux/stackprotector.h> struct kmem_cache *task_xstate_cachep = NULL; unsigned int xstate_size; +#ifdef CONFIG_CC_STACKPROTECTOR +unsigned long __stack_chk_guard __read_mostly; +EXPORT_SYMBOL(__stack_chk_guard); +#endif + int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { *dst = *src; diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 94273aaf78c1..f78cc421e665 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -22,6 +22,7 @@ #include <linux/ftrace.h> #include <linux/hw_breakpoint.h> #include <linux/prefetch.h> +#include <linux/stackprotector.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> #include <asm/fpu.h> @@ -220,6 +221,10 @@ __switch_to(struct task_struct *prev, struct task_struct *next) { struct thread_struct *next_t = &next->thread; +#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) + __stack_chk_guard = next->stack_canary; +#endif + unlazy_fpu(prev, task_pt_regs(prev)); /* we're going to use this soon, after a few expensive things */ diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index 98e88a6112ba..8ce856d1572d 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c @@ -35,6 +35,74 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap) return ret; } +/* + * This is useful to dump out the page tables associated with + * 'addr' in mm 'mm'. + */ +static void show_pte(struct mm_struct *mm, unsigned long addr) +{ + pgd_t *pgd; + + if (mm) + pgd = mm->pgd; + else + pgd = get_TTB(); + + printk(KERN_ALERT "pgd = %p\n", pgd); + pgd += pgd_index(addr); + printk(KERN_ALERT "[%08lx] *pgd=%0*Lx", addr, + sizeof(*pgd) * 2, (u64)pgd_val(*pgd)); + + do { + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + if (pgd_none(*pgd)) + break; + + if (pgd_bad(*pgd)) { + printk("(bad)"); + break; + } + + pud = pud_offset(pgd, addr); + if (PTRS_PER_PUD != 1) + printk(", *pud=%0*Lx", sizeof(*pud) * 2, + (u64)pud_val(*pud)); + + if (pud_none(*pud)) + break; + + if (pud_bad(*pud)) { + printk("(bad)"); + break; + } + + pmd = pmd_offset(pud, addr); + if (PTRS_PER_PMD != 1) + printk(", *pmd=%0*Lx", sizeof(*pmd) * 2, + (u64)pmd_val(*pmd)); + + if (pmd_none(*pmd)) + break; + + if (pmd_bad(*pmd)) { + printk("(bad)"); + break; + } + + /* We must not map this if we have highmem enabled */ + if (PageHighMem(pfn_to_page(pmd_val(*pmd) >> PAGE_SHIFT))) + break; + + pte = pte_offset_kernel(pmd, addr); + printk(", *pte=%0*Lx", sizeof(*pte) * 2, (u64)pte_val(*pte)); + } while (0); + + printk("\n"); +} + static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) { unsigned index = pgd_index(address); @@ -86,7 +154,7 @@ static noinline int vmalloc_fault(unsigned long address) pte_t *pte_k; /* Make sure we are in vmalloc/module/P3 area: */ - if (!(address >= VMALLOC_START && address < P3_ADDR_MAX)) + if (!(address >= P3SEG && address < P3_ADDR_MAX)) return -1; /* @@ -274,29 +342,12 @@ no_context: bust_spinlocks(1); if (oops_may_print()) { - unsigned long page; - - if (address < PAGE_SIZE) - printk(KERN_ALERT "Unable to handle kernel NULL " - "pointer dereference"); - else - printk(KERN_ALERT "Unable to handle kernel paging " - "request"); - printk(" at virtual address %08lx\n", address); - printk(KERN_ALERT "pc = %08lx\n", regs->pc); - page = (unsigned long)get_TTB(); - if (page) { - page = ((__typeof__(page) *)page)[address >> PGDIR_SHIFT]; - printk(KERN_ALERT "*pde = %08lx\n", page); - if (page & _PAGE_PRESENT) { - page &= PAGE_MASK; - address &= 0x003ff000; - page = ((__typeof__(page) *) - __va(page))[address >> - PAGE_SHIFT]; - printk(KERN_ALERT "*pte = %08lx\n", page); - } - } + printk(KERN_ALERT + "Unable to handle kernel %s at virtual address %08lx\n", + (address < PAGE_SIZE) ? "NULL pointer dereference" : + "paging request", address); + + show_pte(mm, address); } die("Oops", regs, writeaccess); diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c index fea13c7b1aee..b93c2c9ccb1d 100644 --- a/arch/sparc/kernel/ds.c +++ b/arch/sparc/kernel/ds.c @@ -1264,4 +1264,4 @@ static int __init ds_init(void) return vio_register_driver(&ds_driver); } -subsys_initcall(ds_init); +fs_initcall(ds_init); diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S index 77f1b95e0806..9171fc238def 100644 --- a/arch/sparc/kernel/rtrap_64.S +++ b/arch/sparc/kernel/rtrap_64.S @@ -20,11 +20,6 @@ .text .align 32 -__handle_softirq: - call do_softirq - nop - ba,a,pt %xcc, __handle_softirq_continue - nop __handle_preemption: call schedule wrpr %g0, RTRAP_PSTATE, %pstate @@ -89,9 +84,7 @@ rtrap: cmp %l1, 0 /* mm/ultra.S:xcall_report_regs KNOWS about this load. */ - bne,pn %icc, __handle_softirq ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 -__handle_softirq_continue: rtrap_xcall: sethi %hi(0xf << 20), %l4 and %l1, %l4, %l4 diff --git a/arch/tile/kernel/proc.c b/arch/tile/kernel/proc.c index 7a9327046404..446a7f52cc11 100644 --- a/arch/tile/kernel/proc.c +++ b/arch/tile/kernel/proc.c @@ -146,7 +146,6 @@ static ctl_table unaligned_table[] = { }, {} }; -#endif static struct ctl_path tile_path[] = { { .procname = "tile" }, @@ -155,10 +154,9 @@ static struct ctl_path tile_path[] = { static int __init proc_sys_tile_init(void) { -#ifndef __tilegx__ /* FIXME: GX: no support for unaligned access yet */ register_sysctl_paths(tile_path, unaligned_table); -#endif return 0; } arch_initcall(proc_sys_tile_init); +#endif diff --git a/arch/tile/kernel/smpboot.c b/arch/tile/kernel/smpboot.c index b949edcec200..172aef7d3159 100644 --- a/arch/tile/kernel/smpboot.c +++ b/arch/tile/kernel/smpboot.c @@ -196,6 +196,8 @@ void __cpuinit online_secondary(void) /* This must be done before setting cpu_online_mask */ wmb(); + notify_cpu_starting(smp_processor_id()); + /* * We need to hold call_lock, so there is no inconsistency * between the time smp_call_function() determines number of diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h index b3b733262909..99480e55973d 100644 --- a/arch/x86/include/asm/cmpxchg.h +++ b/arch/x86/include/asm/cmpxchg.h @@ -43,7 +43,7 @@ extern void __add_wrong_size(void) switch (sizeof(*(ptr))) { \ case __X86_CASE_B: \ asm volatile (lock #op "b %b0, %1\n" \ - : "+r" (__ret), "+m" (*(ptr)) \ + : "+q" (__ret), "+m" (*(ptr)) \ : : "memory", "cc"); \ break; \ case __X86_CASE_W: \ @@ -173,7 +173,7 @@ extern void __add_wrong_size(void) switch (sizeof(*(ptr))) { \ case __X86_CASE_B: \ asm volatile (lock "addb %b1, %0\n" \ - : "+m" (*(ptr)) : "ri" (inc) \ + : "+m" (*(ptr)) : "qi" (inc) \ : "memory", "cc"); \ break; \ case __X86_CASE_W: \ diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 8be5f54d9360..e0544597cfe7 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -557,6 +557,8 @@ struct __large_struct { unsigned long buf[100]; }; extern unsigned long copy_from_user_nmi(void *to, const void __user *from, unsigned long n); +extern __must_check long +strncpy_from_user(char *dst, const char __user *src, long count); /* * movsl can be slow when source and dest are not both 8-byte aligned diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h index 566e803cc602..8084bc73b18c 100644 --- a/arch/x86/include/asm/uaccess_32.h +++ b/arch/x86/include/asm/uaccess_32.h @@ -213,11 +213,6 @@ static inline unsigned long __must_check copy_from_user(void *to, return n; } -long __must_check strncpy_from_user(char *dst, const char __user *src, - long count); -long __must_check __strncpy_from_user(char *dst, - const char __user *src, long count); - /** * strlen_user: - Get the size of a string in user space. * @str: The string to measure. diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index 1c66d30971ad..fcd4b6f3ef02 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -208,10 +208,6 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size) } } -__must_check long -strncpy_from_user(char *dst, const char __user *src, long count); -__must_check long -__strncpy_from_user(char *dst, const char __user *src, long count); __must_check long strnlen_user(const char __user *str, long n); __must_check long __strnlen_user(const char __user *str, long n); __must_check long strlen_user(const char __user *str); diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index f386dc49f988..7515cf0e1805 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c @@ -216,9 +216,9 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) current_thread_info()->sig_on_uaccess_error = 1; /* - * 0 is a valid user pointer (in the access_ok sense) on 32-bit and + * NULL is a valid user pointer (in the access_ok sense) on 32-bit and * 64-bit, so we don't need to special-case it here. For all the - * vsyscalls, 0 means "don't write anything" not "write it at + * vsyscalls, NULL means "don't write anything" not "write it at * address 0". */ ret = -EFAULT; @@ -247,7 +247,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) ret = sys_getcpu((unsigned __user *)regs->di, (unsigned __user *)regs->si, - 0); + NULL); break; } diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c index 25feb1ae71c5..b1e6c4b2e8eb 100644 --- a/arch/x86/lib/insn.c +++ b/arch/x86/lib/insn.c @@ -379,8 +379,8 @@ err_out: return; } -/* Decode moffset16/32/64 */ -static void __get_moffset(struct insn *insn) +/* Decode moffset16/32/64. Return 0 if failed */ +static int __get_moffset(struct insn *insn) { switch (insn->addr_bytes) { case 2: @@ -397,15 +397,19 @@ static void __get_moffset(struct insn *insn) insn->moffset2.value = get_next(int, insn); insn->moffset2.nbytes = 4; break; + default: /* opnd_bytes must be modified manually */ + goto err_out; } insn->moffset1.got = insn->moffset2.got = 1; + return 1; + err_out: - return; + return 0; } -/* Decode imm v32(Iz) */ -static void __get_immv32(struct insn *insn) +/* Decode imm v32(Iz). Return 0 if failed */ +static int __get_immv32(struct insn *insn) { switch (insn->opnd_bytes) { case 2: @@ -417,14 +421,18 @@ static void __get_immv32(struct insn *insn) insn->immediate.value = get_next(int, insn); insn->immediate.nbytes = 4; break; + default: /* opnd_bytes must be modified manually */ + goto err_out; } + return 1; + err_out: - return; + return 0; } -/* Decode imm v64(Iv/Ov) */ -static void __get_immv(struct insn *insn) +/* Decode imm v64(Iv/Ov), Return 0 if failed */ +static int __get_immv(struct insn *insn) { switch (insn->opnd_bytes) { case 2: @@ -441,15 +449,18 @@ static void __get_immv(struct insn *insn) insn->immediate2.value = get_next(int, insn); insn->immediate2.nbytes = 4; break; + default: /* opnd_bytes must be modified manually */ + goto err_out; } insn->immediate1.got = insn->immediate2.got = 1; + return 1; err_out: - return; + return 0; } /* Decode ptr16:16/32(Ap) */ -static void __get_immptr(struct insn *insn) +static int __get_immptr(struct insn *insn) { switch (insn->opnd_bytes) { case 2: @@ -462,14 +473,17 @@ static void __get_immptr(struct insn *insn) break; case 8: /* ptr16:64 is not exist (no segment) */ - return; + return 0; + default: /* opnd_bytes must be modified manually */ + goto err_out; } insn->immediate2.value = get_next(unsigned short, insn); insn->immediate2.nbytes = 2; insn->immediate1.got = insn->immediate2.got = 1; + return 1; err_out: - return; + return 0; } /** @@ -489,7 +503,8 @@ void insn_get_immediate(struct insn *insn) insn_get_displacement(insn); if (inat_has_moffset(insn->attr)) { - __get_moffset(insn); + if (!__get_moffset(insn)) + goto err_out; goto done; } @@ -517,16 +532,20 @@ void insn_get_immediate(struct insn *insn) insn->immediate2.nbytes = 4; break; case INAT_IMM_PTR: - __get_immptr(insn); + if (!__get_immptr(insn)) + goto err_out; break; case INAT_IMM_VWORD32: - __get_immv32(insn); + if (!__get_immv32(insn)) + goto err_out; break; case INAT_IMM_VWORD: - __get_immv(insn); + if (!__get_immv(insn)) + goto err_out; break; default: - break; + /* Here, insn must have an immediate, but failed */ + goto err_out; } if (inat_has_second_immediate(insn->attr)) { insn->immediate2.value = get_next(char, insn); diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c index 97be9cb54483..d6ae30bbd7bb 100644 --- a/arch/x86/lib/usercopy.c +++ b/arch/x86/lib/usercopy.c @@ -7,6 +7,8 @@ #include <linux/highmem.h> #include <linux/module.h> +#include <asm/word-at-a-time.h> + /* * best effort, GUP based copy_from_user() that is NMI-safe */ @@ -41,3 +43,104 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) return len; } EXPORT_SYMBOL_GPL(copy_from_user_nmi); + +static inline unsigned long count_bytes(unsigned long mask) +{ + mask = (mask - 1) & ~mask; + mask >>= 7; + return count_masked_bytes(mask); +} + +/* + * Do a strncpy, return length of string without final '\0'. + * 'count' is the user-supplied count (return 'count' if we + * hit it), 'max' is the address space maximum (and we return + * -EFAULT if we hit it). + */ +static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max) +{ + long res = 0; + + /* + * Truncate 'max' to the user-specified limit, so that + * we only have one limit we need to check in the loop + */ + if (max > count) + max = count; + + while (max >= sizeof(unsigned long)) { + unsigned long c; + + /* Fall back to byte-at-a-time if we get a page fault */ + if (unlikely(__get_user(c,(unsigned long __user *)(src+res)))) + break; + /* This can write a few bytes past the NUL character, but that's ok */ + *(unsigned long *)(dst+res) = c; + c = has_zero(c); + if (c) + return res + count_bytes(c); + res += sizeof(unsigned long); + max -= sizeof(unsigned long); + } + + while (max) { + char c; + + if (unlikely(__get_user(c,src+res))) + return -EFAULT; + dst[res] = c; + if (!c) + return res; + res++; + max--; + } + + /* + * Uhhuh. We hit 'max'. But was that the user-specified maximum + * too? If so, that's ok - we got as much as the user asked for. + */ + if (res >= count) + return res; + + /* + * Nope: we hit the address space limit, and we still had more + * characters the caller would have wanted. That's an EFAULT. + */ + return -EFAULT; +} + +/** + * strncpy_from_user: - Copy a NUL terminated string from userspace. + * @dst: Destination address, in kernel space. This buffer must be at + * least @count bytes long. + * @src: Source address, in user space. + * @count: Maximum number of bytes to copy, including the trailing NUL. + * + * Copies a NUL-terminated string from userspace to kernel space. + * + * On success, returns the length of the string (not including the trailing + * NUL). + * + * If access to userspace fails, returns -EFAULT (some data may have been + * copied). + * + * If @count is smaller than the length of the string, copies @count bytes + * and returns @count. + */ +long +strncpy_from_user(char *dst, const char __user *src, long count) +{ + unsigned long max_addr, src_addr; + + if (unlikely(count <= 0)) + return 0; + + max_addr = current_thread_info()->addr_limit.seg; + src_addr = (unsigned long)src; + if (likely(src_addr < max_addr)) { + unsigned long max = max_addr - src_addr; + return do_strncpy_from_user(dst, src, count, max); + } + return -EFAULT; +} +EXPORT_SYMBOL(strncpy_from_user); diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c index d9b094ca7aaa..ef2a6a5d78e3 100644 --- a/arch/x86/lib/usercopy_32.c +++ b/arch/x86/lib/usercopy_32.c @@ -33,93 +33,6 @@ static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned lon __movsl_is_ok((unsigned long)(a1), (unsigned long)(a2), (n)) /* - * Copy a null terminated string from userspace. - */ - -#define __do_strncpy_from_user(dst, src, count, res) \ -do { \ - int __d0, __d1, __d2; \ - might_fault(); \ - __asm__ __volatile__( \ - " testl %1,%1\n" \ - " jz 2f\n" \ - "0: lodsb\n" \ - " stosb\n" \ - " testb %%al,%%al\n" \ - " jz 1f\n" \ - " decl %1\n" \ - " jnz 0b\n" \ - "1: subl %1,%0\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: movl %5,%0\n" \ - " jmp 2b\n" \ - ".previous\n" \ - _ASM_EXTABLE(0b,3b) \ - : "=&d"(res), "=&c"(count), "=&a" (__d0), "=&S" (__d1), \ - "=&D" (__d2) \ - : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \ - : "memory"); \ -} while (0) - -/** - * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking. - * @dst: Destination address, in kernel space. This buffer must be at - * least @count bytes long. - * @src: Source address, in user space. - * @count: Maximum number of bytes to copy, including the trailing NUL. - * - * Copies a NUL-terminated string from userspace to kernel space. - * Caller must check the specified block with access_ok() before calling - * this function. - * - * On success, returns the length of the string (not including the trailing - * NUL). - * - * If access to userspace fails, returns -EFAULT (some data may have been - * copied). - * - * If @count is smaller than the length of the string, copies @count bytes - * and returns @count. - */ -long -__strncpy_from_user(char *dst, const char __user *src, long count) -{ - long res; - __do_strncpy_from_user(dst, src, count, res); - return res; -} -EXPORT_SYMBOL(__strncpy_from_user); - -/** - * strncpy_from_user: - Copy a NUL terminated string from userspace. - * @dst: Destination address, in kernel space. This buffer must be at - * least @count bytes long. - * @src: Source address, in user space. - * @count: Maximum number of bytes to copy, including the trailing NUL. - * - * Copies a NUL-terminated string from userspace to kernel space. - * - * On success, returns the length of the string (not including the trailing - * NUL). - * - * If access to userspace fails, returns -EFAULT (some data may have been - * copied). - * - * If @count is smaller than the length of the string, copies @count bytes - * and returns @count. - */ -long -strncpy_from_user(char *dst, const char __user *src, long count) -{ - long res = -EFAULT; - if (access_ok(VERIFY_READ, src, 1)) - __do_strncpy_from_user(dst, src, count, res); - return res; -} -EXPORT_SYMBOL(strncpy_from_user); - -/* * Zero Userspace */ diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c index b7c2849ffb66..0d0326f388c0 100644 --- a/arch/x86/lib/usercopy_64.c +++ b/arch/x86/lib/usercopy_64.c @@ -9,55 +9,6 @@ #include <asm/uaccess.h> /* - * Copy a null terminated string from userspace. - */ - -#define __do_strncpy_from_user(dst,src,count,res) \ -do { \ - long __d0, __d1, __d2; \ - might_fault(); \ - __asm__ __volatile__( \ - " testq %1,%1\n" \ - " jz 2f\n" \ - "0: lodsb\n" \ - " stosb\n" \ - " testb %%al,%%al\n" \ - " jz 1f\n" \ - " decq %1\n" \ - " jnz 0b\n" \ - "1: subq %1,%0\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: movq %5,%0\n" \ - " jmp 2b\n" \ - ".previous\n" \ - _ASM_EXTABLE(0b,3b) \ - : "=&r"(res), "=&c"(count), "=&a" (__d0), "=&S" (__d1), \ - "=&D" (__d2) \ - : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \ - : "memory"); \ -} while (0) - -long -__strncpy_from_user(char *dst, const char __user *src, long count) -{ - long res; - __do_strncpy_from_user(dst, src, count, res); - return res; -} -EXPORT_SYMBOL(__strncpy_from_user); - -long -strncpy_from_user(char *dst, const char __user *src, long count) -{ - long res = -EFAULT; - if (access_ok(VERIFY_READ, src, 1)) - return __strncpy_from_user(dst, src, count); - return res; -} -EXPORT_SYMBOL(strncpy_from_user); - -/* * Zero Userspace */ diff --git a/block/blk-core.c b/block/blk-core.c index 3a78b00edd71..1f61b74867e4 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -483,7 +483,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) if (!q) return NULL; - q->id = ida_simple_get(&blk_queue_ida, 0, 0, GFP_KERNEL); + q->id = ida_simple_get(&blk_queue_ida, 0, 0, gfp_mask); if (q->id < 0) goto fail_q; @@ -1277,7 +1277,8 @@ static bool attempt_plug_merge(struct request_queue *q, struct bio *bio, list_for_each_entry_reverse(rq, &plug->list, queuelist) { int el_ret; - (*request_count)++; + if (rq->q == q) + (*request_count)++; if (rq->q != q || !blk_rq_merge_ok(rq, bio)) continue; diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 5eed6a76721d..f2ddb94626bd 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -1218,7 +1218,7 @@ void blk_throtl_drain(struct request_queue *q) struct bio_list bl; struct bio *bio; - WARN_ON_ONCE(!queue_is_locked(q)); + queue_lockdep_assert_held(q); bio_list_init(&bl); diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 457295253566..3c38536bd52c 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -295,6 +295,7 @@ struct cfq_data { unsigned int cfq_slice_idle; unsigned int cfq_group_idle; unsigned int cfq_latency; + unsigned int cfq_target_latency; /* * Fallback dummy cfqq for extreme OOM conditions @@ -604,7 +605,7 @@ cfq_group_slice(struct cfq_data *cfqd, struct cfq_group *cfqg) { struct cfq_rb_root *st = &cfqd->grp_service_tree; - return cfq_target_latency * cfqg->weight / st->total_weight; + return cfqd->cfq_target_latency * cfqg->weight / st->total_weight; } static inline unsigned @@ -2271,7 +2272,8 @@ new_workload: * to have higher weight. A more accurate thing would be to * calculate system wide asnc/sync ratio. */ - tmp = cfq_target_latency * cfqg_busy_async_queues(cfqd, cfqg); + tmp = cfqd->cfq_target_latency * + cfqg_busy_async_queues(cfqd, cfqg); tmp = tmp/cfqd->busy_queues; slice = min_t(unsigned, slice, tmp); @@ -3737,6 +3739,7 @@ static void *cfq_init_queue(struct request_queue *q) cfqd->cfq_back_penalty = cfq_back_penalty; cfqd->cfq_slice[0] = cfq_slice_async; cfqd->cfq_slice[1] = cfq_slice_sync; + cfqd->cfq_target_latency = cfq_target_latency; cfqd->cfq_slice_async_rq = cfq_slice_async_rq; cfqd->cfq_slice_idle = cfq_slice_idle; cfqd->cfq_group_idle = cfq_group_idle; @@ -3788,6 +3791,7 @@ SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); SHOW_FUNCTION(cfq_low_latency_show, cfqd->cfq_latency, 0); +SHOW_FUNCTION(cfq_target_latency_show, cfqd->cfq_target_latency, 1); #undef SHOW_FUNCTION #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ @@ -3821,6 +3825,7 @@ STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0); STORE_FUNCTION(cfq_low_latency_store, &cfqd->cfq_latency, 0, 1, 0); +STORE_FUNCTION(cfq_target_latency_store, &cfqd->cfq_target_latency, 1, UINT_MAX, 1); #undef STORE_FUNCTION #define CFQ_ATTR(name) \ @@ -3838,6 +3843,7 @@ static struct elv_fs_entry cfq_attrs[] = { CFQ_ATTR(slice_idle), CFQ_ATTR(group_idle), CFQ_ATTR(low_latency), + CFQ_ATTR(target_latency), __ATTR_NULL }; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index ba14fb93c929..c3881b2eb8b2 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -607,8 +607,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, acpi_irq_handler = handler; acpi_irq_context = context; - if (request_threaded_irq(irq, NULL, acpi_irq, IRQF_SHARED, "acpi", - acpi_irq)) { + if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); acpi_irq_handler = NULL; return AE_NOT_ACQUIRED; diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 01c2cf4efcdd..cc273226dbd0 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -247,8 +247,7 @@ static int amba_pm_restore(struct device *dev) /* * Hooks to provide runtime PM of the pclk (bus clock). It is safe to * enable/disable the bus clock at runtime PM suspend/resume as this - * does not result in loss of context. However, disabling vcore power - * would do, so we leave that to the driver. + * does not result in loss of context. */ static int amba_pm_runtime_suspend(struct device *dev) { @@ -354,39 +353,6 @@ static void amba_put_disable_pclk(struct amba_device *pcdev) clk_put(pclk); } -static int amba_get_enable_vcore(struct amba_device *pcdev) -{ - struct regulator *vcore = regulator_get(&pcdev->dev, "vcore"); - int ret; - - pcdev->vcore = vcore; - - if (IS_ERR(vcore)) { - /* It is OK not to supply a vcore regulator */ - if (PTR_ERR(vcore) == -ENODEV) - return 0; - return PTR_ERR(vcore); - } - - ret = regulator_enable(vcore); - if (ret) { - regulator_put(vcore); - pcdev->vcore = ERR_PTR(-ENODEV); - } - - return ret; -} - -static void amba_put_disable_vcore(struct amba_device *pcdev) -{ - struct regulator *vcore = pcdev->vcore; - - if (!IS_ERR(vcore)) { - regulator_disable(vcore); - regulator_put(vcore); - } -} - /* * These are the device model conversion veneers; they convert the * device model structures to our more specific structures. @@ -399,10 +365,6 @@ static int amba_probe(struct device *dev) int ret; do { - ret = amba_get_enable_vcore(pcdev); - if (ret) - break; - ret = amba_get_enable_pclk(pcdev); if (ret) break; @@ -420,7 +382,6 @@ static int amba_probe(struct device *dev) pm_runtime_put_noidle(dev); amba_put_disable_pclk(pcdev); - amba_put_disable_vcore(pcdev); } while (0); return ret; @@ -442,7 +403,6 @@ static int amba_remove(struct device *dev) pm_runtime_put_noidle(dev); amba_put_disable_pclk(pcdev); - amba_put_disable_vcore(pcdev); return ret; } diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 68013f96729f..7857e8fd0a3e 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -329,6 +329,8 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (Lynx Point) */ { 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (DH89xxCC) */ + { 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, { } /* terminate list */ }; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e0bda9ff89cd..28db50b57b91 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -95,7 +95,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev); static void ata_dev_xfermask(struct ata_device *dev); static unsigned long ata_dev_blacklisted(const struct ata_device *dev); -unsigned int ata_print_id = 1; +atomic_t ata_print_id = ATOMIC_INIT(1); struct ata_force_param { const char *name; @@ -6029,7 +6029,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) /* give ports names and add SCSI hosts */ for (i = 0; i < host->n_ports; i++) - host->ports[i]->print_id = ata_print_id++; + host->ports[i]->print_id = atomic_inc_return(&ata_print_id); /* Create associated sysfs transport objects */ diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 1ee00c8b5b04..93dabdcd2cbe 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3843,7 +3843,7 @@ int ata_sas_async_port_init(struct ata_port *ap) int rc = ap->ops->port_start(ap); if (!rc) { - ap->print_id = ata_print_id++; + ap->print_id = atomic_inc_return(&ata_print_id); __ata_port_probe(ap); } @@ -3867,7 +3867,7 @@ int ata_sas_port_init(struct ata_port *ap) int rc = ap->ops->port_start(ap); if (!rc) { - ap->print_id = ata_print_id++; + ap->print_id = atomic_inc_return(&ata_print_id); rc = ata_port_probe(ap); } diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index 74aaee30e264..c34190485377 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -294,6 +294,7 @@ int ata_tport_add(struct device *parent, device_enable_async_suspend(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); + pm_runtime_forbid(dev); transport_add_device(dev); transport_configure_device(dev); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 2e26fcaf635b..9d0fd0b71852 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -53,7 +53,7 @@ enum { ATA_DNXFER_QUIET = (1 << 31), }; -extern unsigned int ata_print_id; +extern atomic_t ata_print_id; extern int atapi_passthru16; extern int libata_fua; extern int libata_noacpi; diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 38950ea8398a..7336d4a7ab31 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -4025,7 +4025,8 @@ static int mv_platform_probe(struct platform_device *pdev) struct ata_host *host; struct mv_host_priv *hpriv; struct resource *res; - int n_ports, rc; + int n_ports = 0; + int rc; ata_print_version_once(&pdev->dev, DRV_VERSION); diff --git a/drivers/base/soc.c b/drivers/base/soc.c index 05f150382da8..ba29b2e73d48 100644 --- a/drivers/base/soc.c +++ b/drivers/base/soc.c @@ -15,7 +15,7 @@ #include <linux/sys_soc.h> #include <linux/err.h> -static DEFINE_IDR(soc_ida); +static DEFINE_IDA(soc_ida); static DEFINE_SPINLOCK(soc_lock); static ssize_t soc_info_get(struct device *dev, @@ -168,8 +168,6 @@ void soc_device_unregister(struct soc_device *soc_dev) static int __init soc_bus_register(void) { - spin_lock_init(&soc_lock); - return bus_register(&soc_bus_type); } core_initcall(soc_bus_register); diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig index c1172dafdffa..fb7c80fb721e 100644 --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig @@ -29,7 +29,7 @@ config BCMA_HOST_PCI config BCMA_DRIVER_PCI_HOSTMODE bool "Driver for PCI core working in hostmode" - depends on BCMA && MIPS + depends on BCMA && MIPS && BCMA_HOST_PCI help PCI core hostmode operation (external PCI bus). diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index 4e20bcfa7ec5..d2097a11c3c7 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c @@ -10,6 +10,7 @@ */ #include "bcma_private.h" +#include <linux/pci.h> #include <linux/export.h> #include <linux/bcma/bcma.h> #include <asm/paccess.h> diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index e820b68d2f6c..acda773b3720 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -866,6 +866,7 @@ cciss_scsi_detect(ctlr_info_t *h) sh->can_queue = cciss_tape_cmds; sh->sg_tablesize = h->maxsgentries; sh->max_cmd_len = MAX_COMMAND_SIZE; + sh->max_sectors = h->cciss_max_sectors; ((struct cciss_scsi_adapter_data_t *) h->scsi_ctlr)->scsi_host = sh; @@ -1410,7 +1411,7 @@ static void cciss_scatter_gather(ctlr_info_t *h, CommandList_struct *c, /* track how many SG entries we are using */ if (request_nsgs > h->maxSG) h->maxSG = request_nsgs; - c->Header.SGTotal = (__u8) request_nsgs + chained; + c->Header.SGTotal = (u16) request_nsgs + chained; if (request_nsgs > h->max_cmd_sgentries) c->Header.SGList = h->max_cmd_sgentries; else diff --git a/drivers/block/mtip32xx/Kconfig b/drivers/block/mtip32xx/Kconfig index b5dd14e072f2..0ba837fc62a8 100644 --- a/drivers/block/mtip32xx/Kconfig +++ b/drivers/block/mtip32xx/Kconfig @@ -4,6 +4,6 @@ config BLK_DEV_PCIESSD_MTIP32XX tristate "Block Device Driver for Micron PCIe SSDs" - depends on HOTPLUG_PCI_PCIE + depends on PCI help This enables the block driver for Micron PCIe SSDs. diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 8eb81c96608f..00f9fc992090 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -36,6 +36,7 @@ #include <linux/idr.h> #include <linux/kthread.h> #include <../drivers/ata/ahci.h> +#include <linux/export.h> #include "mtip32xx.h" #define HW_CMD_SLOT_SZ (MTIP_MAX_COMMAND_SLOTS * 32) @@ -44,6 +45,7 @@ #define HW_PORT_PRIV_DMA_SZ \ (HW_CMD_SLOT_SZ + HW_CMD_TBL_AR_SZ + AHCI_RX_FIS_SZ) +#define HOST_CAP_NZDMA (1 << 19) #define HOST_HSORG 0xFC #define HSORG_DISABLE_SLOTGRP_INTR (1<<24) #define HSORG_DISABLE_SLOTGRP_PXIS (1<<16) @@ -139,6 +141,12 @@ static void mtip_command_cleanup(struct driver_data *dd) int group = 0, commandslot = 0, commandindex = 0; struct mtip_cmd *command; struct mtip_port *port = dd->port; + static int in_progress; + + if (in_progress) + return; + + in_progress = 1; for (group = 0; group < 4; group++) { for (commandslot = 0; commandslot < 32; commandslot++) { @@ -165,7 +173,8 @@ static void mtip_command_cleanup(struct driver_data *dd) up(&port->cmd_slot); - atomic_set(&dd->drv_cleanup_done, true); + set_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag); + in_progress = 0; } /* @@ -262,6 +271,9 @@ static int hba_reset_nosleep(struct driver_data *dd) && time_before(jiffies, timeout)) mdelay(1); + if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)) + return -1; + if (readl(dd->mmio + HOST_CTL) & HOST_RESET) return -1; @@ -294,6 +306,10 @@ static inline void mtip_issue_ncq_command(struct mtip_port *port, int tag) port->cmd_issue[MTIP_TAG_INDEX(tag)]); spin_unlock_irqrestore(&port->cmd_issue_lock, flags); + + /* Set the command's timeout value.*/ + port->commands[tag].comp_time = jiffies + msecs_to_jiffies( + MTIP_NCQ_COMMAND_TIMEOUT_MS); } /* @@ -420,7 +436,12 @@ static void mtip_init_port(struct mtip_port *port) writel(0xFFFFFFFF, port->completed[i]); /* Clear any pending interrupts for this port */ - writel(readl(port->mmio + PORT_IRQ_STAT), port->mmio + PORT_IRQ_STAT); + writel(readl(port->dd->mmio + PORT_IRQ_STAT), + port->dd->mmio + PORT_IRQ_STAT); + + /* Clear any pending interrupts on the HBA. */ + writel(readl(port->dd->mmio + HOST_IRQ_STAT), + port->dd->mmio + HOST_IRQ_STAT); /* Enable port interrupts */ writel(DEF_PORT_IRQ, port->mmio + PORT_IRQ_MASK); @@ -447,6 +468,9 @@ static void mtip_restart_port(struct mtip_port *port) && time_before(jiffies, timeout)) ; + if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag)) + return; + /* * Chip quirk: escalate to hba reset if * PxCMD.CR not clear after 500 ms @@ -475,6 +499,9 @@ static void mtip_restart_port(struct mtip_port *port) while (time_before(jiffies, timeout)) ; + if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag)) + return; + /* Clear PxSCTL.DET */ writel(readl(port->mmio + PORT_SCR_CTL) & ~1, port->mmio + PORT_SCR_CTL); @@ -486,15 +513,35 @@ static void mtip_restart_port(struct mtip_port *port) && time_before(jiffies, timeout)) ; + if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag)) + return; + if ((readl(port->mmio + PORT_SCR_STAT) & 0x01) == 0) dev_warn(&port->dd->pdev->dev, "COM reset failed\n"); - /* Clear SError, the PxSERR.DIAG.x should be set so clear it */ - writel(readl(port->mmio + PORT_SCR_ERR), port->mmio + PORT_SCR_ERR); + mtip_init_port(port); + mtip_start_port(port); - /* Enable the DMA engine */ - mtip_enable_engine(port, 1); +} + +/* + * Helper function for tag logging + */ +static void print_tags(struct driver_data *dd, + char *msg, + unsigned long *tagbits, + int cnt) +{ + unsigned char tagmap[128]; + int group, tagmap_len = 0; + + memset(tagmap, 0, sizeof(tagmap)); + for (group = SLOTBITS_IN_LONGS; group > 0; group--) + tagmap_len = sprintf(tagmap + tagmap_len, "%016lX ", + tagbits[group-1]); + dev_warn(&dd->pdev->dev, + "%d command(s) %s: tagmap [%s]", cnt, msg, tagmap); } /* @@ -514,15 +561,18 @@ static void mtip_timeout_function(unsigned long int data) int tag, cmdto_cnt = 0; unsigned int bit, group; unsigned int num_command_slots = port->dd->slot_groups * 32; + unsigned long to, tagaccum[SLOTBITS_IN_LONGS]; if (unlikely(!port)) return; - if (atomic_read(&port->dd->resumeflag) == true) { + if (test_bit(MTIP_DDF_RESUME_BIT, &port->dd->dd_flag)) { mod_timer(&port->cmd_timer, jiffies + msecs_to_jiffies(30000)); return; } + /* clear the tag accumulator */ + memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); for (tag = 0; tag < num_command_slots; tag++) { /* @@ -540,12 +590,10 @@ static void mtip_timeout_function(unsigned long int data) command = &port->commands[tag]; fis = (struct host_to_dev_fis *) command->command; - dev_warn(&port->dd->pdev->dev, - "Timeout for command tag %d\n", tag); - + set_bit(tag, tagaccum); cmdto_cnt++; if (cmdto_cnt == 1) - set_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags); + set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); /* * Clear the completed bit. This should prevent @@ -578,15 +626,29 @@ static void mtip_timeout_function(unsigned long int data) } } - if (cmdto_cnt) { - dev_warn(&port->dd->pdev->dev, - "%d commands timed out: restarting port", - cmdto_cnt); + if (cmdto_cnt && !test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { + print_tags(port->dd, "timed out", tagaccum, cmdto_cnt); + mtip_restart_port(port); - clear_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags); + clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); wake_up_interruptible(&port->svc_wait); } + if (port->ic_pause_timer) { + to = port->ic_pause_timer + msecs_to_jiffies(1000); + if (time_after(jiffies, to)) { + if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { + port->ic_pause_timer = 0; + clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags); + clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags); + clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags); + wake_up_interruptible(&port->svc_wait); + } + + + } + } + /* Restart the timer */ mod_timer(&port->cmd_timer, jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD)); @@ -681,23 +743,18 @@ static void mtip_completion(struct mtip_port *port, complete(waiting); } -/* - * Helper function for tag logging - */ -static void print_tags(struct driver_data *dd, - char *msg, - unsigned long *tagbits) +static void mtip_null_completion(struct mtip_port *port, + int tag, + void *data, + int status) { - unsigned int tag, count = 0; - - for (tag = 0; tag < (dd->slot_groups) * 32; tag++) { - if (test_bit(tag, tagbits)) - count++; - } - if (count) - dev_info(&dd->pdev->dev, "%s [%i tags]\n", msg, count); + return; } +static int mtip_read_log_page(struct mtip_port *port, u8 page, u16 *buffer, + dma_addr_t buffer_dma, unsigned int sectors); +static int mtip_get_smart_attr(struct mtip_port *port, unsigned int id, + struct smart_attr *attrib); /* * Handle an error. * @@ -708,12 +765,16 @@ static void print_tags(struct driver_data *dd, */ static void mtip_handle_tfe(struct driver_data *dd) { - int group, tag, bit, reissue; + int group, tag, bit, reissue, rv; struct mtip_port *port; - struct mtip_cmd *command; + struct mtip_cmd *cmd; u32 completed; struct host_to_dev_fis *fis; unsigned long tagaccum[SLOTBITS_IN_LONGS]; + unsigned int cmd_cnt = 0; + unsigned char *buf; + char *fail_reason = NULL; + int fail_all_ncq_write = 0, fail_all_ncq_cmds = 0; dev_warn(&dd->pdev->dev, "Taskfile error\n"); @@ -722,8 +783,11 @@ static void mtip_handle_tfe(struct driver_data *dd) /* Stop the timer to prevent command timeouts. */ del_timer(&port->cmd_timer); + /* clear the tag accumulator */ + memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); + /* Set eh_active */ - set_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags); + set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); /* Loop through all the groups */ for (group = 0; group < dd->slot_groups; group++) { @@ -732,9 +796,6 @@ static void mtip_handle_tfe(struct driver_data *dd) /* clear completed status register in the hardware.*/ writel(completed, port->completed[group]); - /* clear the tag accumulator */ - memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); - /* Process successfully completed commands */ for (bit = 0; bit < 32 && completed; bit++) { if (!(completed & (1<<bit))) @@ -745,13 +806,14 @@ static void mtip_handle_tfe(struct driver_data *dd) if (tag == MTIP_TAG_INTERNAL) continue; - command = &port->commands[tag]; - if (likely(command->comp_func)) { + cmd = &port->commands[tag]; + if (likely(cmd->comp_func)) { set_bit(tag, tagaccum); - atomic_set(&port->commands[tag].active, 0); - command->comp_func(port, + cmd_cnt++; + atomic_set(&cmd->active, 0); + cmd->comp_func(port, tag, - command->comp_data, + cmd->comp_data, 0); } else { dev_err(&port->dd->pdev->dev, @@ -765,12 +827,45 @@ static void mtip_handle_tfe(struct driver_data *dd) } } } - print_tags(dd, "TFE tags completed:", tagaccum); + + print_tags(dd, "completed (TFE)", tagaccum, cmd_cnt); /* Restart the port */ mdelay(20); mtip_restart_port(port); + /* Trying to determine the cause of the error */ + rv = mtip_read_log_page(dd->port, ATA_LOG_SATA_NCQ, + dd->port->log_buf, + dd->port->log_buf_dma, 1); + if (rv) { + dev_warn(&dd->pdev->dev, + "Error in READ LOG EXT (10h) command\n"); + /* non-critical error, don't fail the load */ + } else { + buf = (unsigned char *)dd->port->log_buf; + if (buf[259] & 0x1) { + dev_info(&dd->pdev->dev, + "Write protect bit is set.\n"); + set_bit(MTIP_DDF_WRITE_PROTECT_BIT, &dd->dd_flag); + fail_all_ncq_write = 1; + fail_reason = "write protect"; + } + if (buf[288] == 0xF7) { + dev_info(&dd->pdev->dev, + "Exceeded Tmax, drive in thermal shutdown.\n"); + set_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag); + fail_all_ncq_cmds = 1; + fail_reason = "thermal shutdown"; + } + if (buf[288] == 0xBF) { + dev_info(&dd->pdev->dev, + "Drive indicates rebuild has failed.\n"); + fail_all_ncq_cmds = 1; + fail_reason = "rebuild failed"; + } + } + /* clear the tag accumulator */ memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); @@ -779,32 +874,47 @@ static void mtip_handle_tfe(struct driver_data *dd) for (bit = 0; bit < 32; bit++) { reissue = 1; tag = (group << 5) + bit; + cmd = &port->commands[tag]; /* If the active bit is set re-issue the command */ - if (atomic_read(&port->commands[tag].active) == 0) + if (atomic_read(&cmd->active) == 0) continue; - fis = (struct host_to_dev_fis *) - port->commands[tag].command; + fis = (struct host_to_dev_fis *)cmd->command; /* Should re-issue? */ if (tag == MTIP_TAG_INTERNAL || fis->command == ATA_CMD_SET_FEATURES) reissue = 0; + else { + if (fail_all_ncq_cmds || + (fail_all_ncq_write && + fis->command == ATA_CMD_FPDMA_WRITE)) { + dev_warn(&dd->pdev->dev, + " Fail: %s w/tag %d [%s].\n", + fis->command == ATA_CMD_FPDMA_WRITE ? + "write" : "read", + tag, + fail_reason != NULL ? + fail_reason : "unknown"); + atomic_set(&cmd->active, 0); + if (cmd->comp_func) { + cmd->comp_func(port, tag, + cmd->comp_data, + -ENODATA); + } + continue; + } + } /* * First check if this command has * exceeded its retries. */ - if (reissue && - (port->commands[tag].retries-- > 0)) { + if (reissue && (cmd->retries-- > 0)) { set_bit(tag, tagaccum); - /* Update the timeout value. */ - port->commands[tag].comp_time = - jiffies + msecs_to_jiffies( - MTIP_NCQ_COMMAND_TIMEOUT_MS); /* Re-issue the command. */ mtip_issue_ncq_command(port, tag); @@ -814,13 +924,13 @@ static void mtip_handle_tfe(struct driver_data *dd) /* Retire a command that will not be reissued */ dev_warn(&port->dd->pdev->dev, "retiring tag %d\n", tag); - atomic_set(&port->commands[tag].active, 0); + atomic_set(&cmd->active, 0); - if (port->commands[tag].comp_func) - port->commands[tag].comp_func( + if (cmd->comp_func) + cmd->comp_func( port, tag, - port->commands[tag].comp_data, + cmd->comp_data, PORT_IRQ_TF_ERR); else dev_warn(&port->dd->pdev->dev, @@ -828,10 +938,10 @@ static void mtip_handle_tfe(struct driver_data *dd) tag); } } - print_tags(dd, "TFE tags reissued:", tagaccum); + print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt); /* clear eh_active */ - clear_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags); + clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); wake_up_interruptible(&port->svc_wait); mod_timer(&port->cmd_timer, @@ -899,7 +1009,7 @@ static inline void mtip_process_legacy(struct driver_data *dd, u32 port_stat) struct mtip_port *port = dd->port; struct mtip_cmd *cmd = &port->commands[MTIP_TAG_INTERNAL]; - if (test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) && + if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags) && (cmd != NULL) && !(readl(port->cmd_issue[MTIP_TAG_INTERNAL]) & (1 << MTIP_TAG_INTERNAL))) { if (cmd->comp_func) { @@ -911,8 +1021,6 @@ static inline void mtip_process_legacy(struct driver_data *dd, u32 port_stat) } } - dev_warn(&dd->pdev->dev, "IRQ status 0x%x ignored.\n", port_stat); - return; } @@ -968,6 +1076,9 @@ static inline irqreturn_t mtip_handle_irq(struct driver_data *data) /* don't proceed further */ return IRQ_HANDLED; } + if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, + &dd->dd_flag)) + return rv; mtip_process_errors(dd, port_stat & PORT_IRQ_ERR); } @@ -1015,6 +1126,39 @@ static void mtip_issue_non_ncq_command(struct mtip_port *port, int tag) port->cmd_issue[MTIP_TAG_INDEX(tag)]); } +static bool mtip_pause_ncq(struct mtip_port *port, + struct host_to_dev_fis *fis) +{ + struct host_to_dev_fis *reply; + unsigned long task_file_data; + + reply = port->rxfis + RX_FIS_D2H_REG; + task_file_data = readl(port->mmio+PORT_TFDATA); + + if ((task_file_data & 1) || (fis->command == ATA_CMD_SEC_ERASE_UNIT)) + return false; + + if (fis->command == ATA_CMD_SEC_ERASE_PREP) { + set_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags); + port->ic_pause_timer = jiffies; + return true; + } else if ((fis->command == ATA_CMD_DOWNLOAD_MICRO) && + (fis->features == 0x03)) { + set_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags); + port->ic_pause_timer = jiffies; + return true; + } else if ((fis->command == ATA_CMD_SEC_ERASE_UNIT) || + ((fis->command == 0xFC) && + (fis->features == 0x27 || fis->features == 0x72 || + fis->features == 0x62 || fis->features == 0x26))) { + /* Com reset after secure erase or lowlevel format */ + mtip_restart_port(port); + return false; + } + + return false; +} + /* * Wait for port to quiesce * @@ -1033,11 +1177,13 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) to = jiffies + msecs_to_jiffies(timeout); do { - if (test_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags) && - test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) { + if (test_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags) && + test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) { msleep(20); continue; /* svc thd is actively issuing commands */ } + if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag)) + return -EFAULT; /* * Ignore s_active bit 0 of array element 0. * This bit will always be set @@ -1074,7 +1220,7 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) * -EAGAIN Time out waiting for command to complete. */ static int mtip_exec_internal_command(struct mtip_port *port, - void *fis, + struct host_to_dev_fis *fis, int fis_len, dma_addr_t buffer, int buf_len, @@ -1084,8 +1230,9 @@ static int mtip_exec_internal_command(struct mtip_port *port, { struct mtip_cmd_sg *command_sg; DECLARE_COMPLETION_ONSTACK(wait); - int rv = 0; + int rv = 0, ready2go = 1; struct mtip_cmd *int_cmd = &port->commands[MTIP_TAG_INTERNAL]; + unsigned long to; /* Make sure the buffer is 8 byte aligned. This is asic specific. */ if (buffer & 0x00000007) { @@ -1094,23 +1241,38 @@ static int mtip_exec_internal_command(struct mtip_port *port, return -EFAULT; } - /* Only one internal command should be running at a time */ - if (test_and_set_bit(MTIP_TAG_INTERNAL, port->allocated)) { + to = jiffies + msecs_to_jiffies(timeout); + do { + ready2go = !test_and_set_bit(MTIP_TAG_INTERNAL, + port->allocated); + if (ready2go) + break; + mdelay(100); + } while (time_before(jiffies, to)); + if (!ready2go) { dev_warn(&port->dd->pdev->dev, - "Internal command already active\n"); + "Internal cmd active. new cmd [%02X]\n", fis->command); return -EBUSY; } - set_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags); + set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags); + port->ic_pause_timer = 0; + + if (fis->command == ATA_CMD_SEC_ERASE_UNIT) + clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags); + else if (fis->command == ATA_CMD_DOWNLOAD_MICRO) + clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags); if (atomic == GFP_KERNEL) { - /* wait for io to complete if non atomic */ - if (mtip_quiesce_io(port, 5000) < 0) { - dev_warn(&port->dd->pdev->dev, - "Failed to quiesce IO\n"); - release_slot(port, MTIP_TAG_INTERNAL); - clear_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags); - wake_up_interruptible(&port->svc_wait); - return -EBUSY; + if (fis->command != ATA_CMD_STANDBYNOW1) { + /* wait for io to complete if non atomic */ + if (mtip_quiesce_io(port, 5000) < 0) { + dev_warn(&port->dd->pdev->dev, + "Failed to quiesce IO\n"); + release_slot(port, MTIP_TAG_INTERNAL); + clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags); + wake_up_interruptible(&port->svc_wait); + return -EBUSY; + } } /* Set the completion function and data for the command. */ @@ -1120,7 +1282,7 @@ static int mtip_exec_internal_command(struct mtip_port *port, } else { /* Clear completion - we're going to poll */ int_cmd->comp_data = NULL; - int_cmd->comp_func = NULL; + int_cmd->comp_func = mtip_null_completion; } /* Copy the command to the command table */ @@ -1159,6 +1321,12 @@ static int mtip_exec_internal_command(struct mtip_port *port, "Internal command did not complete [%d] " "within timeout of %lu ms\n", atomic, timeout); + if (mtip_check_surprise_removal(port->dd->pdev) || + test_bit(MTIP_DDF_REMOVE_PENDING_BIT, + &port->dd->dd_flag)) { + rv = -ENXIO; + goto exec_ic_exit; + } rv = -EAGAIN; } @@ -1166,31 +1334,59 @@ static int mtip_exec_internal_command(struct mtip_port *port, & (1 << MTIP_TAG_INTERNAL)) { dev_warn(&port->dd->pdev->dev, "Retiring internal command but CI is 1.\n"); + if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, + &port->dd->dd_flag)) { + hba_reset_nosleep(port->dd); + rv = -ENXIO; + } else { + mtip_restart_port(port); + rv = -EAGAIN; + } + goto exec_ic_exit; } } else { /* Spin for <timeout> checking if command still outstanding */ timeout = jiffies + msecs_to_jiffies(timeout); - - while ((readl( - port->cmd_issue[MTIP_TAG_INTERNAL]) - & (1 << MTIP_TAG_INTERNAL)) - && time_before(jiffies, timeout)) - ; + while ((readl(port->cmd_issue[MTIP_TAG_INTERNAL]) + & (1 << MTIP_TAG_INTERNAL)) + && time_before(jiffies, timeout)) { + if (mtip_check_surprise_removal(port->dd->pdev)) { + rv = -ENXIO; + goto exec_ic_exit; + } + if ((fis->command != ATA_CMD_STANDBYNOW1) && + test_bit(MTIP_DDF_REMOVE_PENDING_BIT, + &port->dd->dd_flag)) { + rv = -ENXIO; + goto exec_ic_exit; + } + } if (readl(port->cmd_issue[MTIP_TAG_INTERNAL]) & (1 << MTIP_TAG_INTERNAL)) { dev_err(&port->dd->pdev->dev, - "Internal command did not complete [%d]\n", - atomic); + "Internal command did not complete [atomic]\n"); rv = -EAGAIN; + if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, + &port->dd->dd_flag)) { + hba_reset_nosleep(port->dd); + rv = -ENXIO; + } else { + mtip_restart_port(port); + rv = -EAGAIN; + } } } - +exec_ic_exit: /* Clear the allocated and active bits for the internal command. */ atomic_set(&int_cmd->active, 0); release_slot(port, MTIP_TAG_INTERNAL); - clear_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags); + if (rv >= 0 && mtip_pause_ncq(port, fis)) { + /* NCQ paused */ + return rv; + } + clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags); wake_up_interruptible(&port->svc_wait); return rv; @@ -1240,6 +1436,9 @@ static int mtip_get_identify(struct mtip_port *port, void __user *user_buffer) int rv = 0; struct host_to_dev_fis fis; + if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag)) + return -EFAULT; + /* Build the FIS. */ memset(&fis, 0, sizeof(struct host_to_dev_fis)); fis.type = 0x27; @@ -1313,6 +1512,7 @@ static int mtip_standby_immediate(struct mtip_port *port) { int rv; struct host_to_dev_fis fis; + unsigned long start; /* Build the FIS. */ memset(&fis, 0, sizeof(struct host_to_dev_fis)); @@ -1320,15 +1520,150 @@ static int mtip_standby_immediate(struct mtip_port *port) fis.opts = 1 << 7; fis.command = ATA_CMD_STANDBYNOW1; - /* Execute the command. Use a 15-second timeout for large drives. */ + start = jiffies; rv = mtip_exec_internal_command(port, &fis, 5, 0, 0, 0, - GFP_KERNEL, + GFP_ATOMIC, 15000); + dbg_printk(MTIP_DRV_NAME "Time taken to complete standby cmd: %d ms\n", + jiffies_to_msecs(jiffies - start)); + if (rv) + dev_warn(&port->dd->pdev->dev, + "STANDBY IMMEDIATE command failed.\n"); + + return rv; +} + +/* + * Issue a READ LOG EXT command to the device. + * + * @port pointer to the port structure. + * @page page number to fetch + * @buffer pointer to buffer + * @buffer_dma dma address corresponding to @buffer + * @sectors page length to fetch, in sectors + * + * return value + * @rv return value from mtip_exec_internal_command() + */ +static int mtip_read_log_page(struct mtip_port *port, u8 page, u16 *buffer, + dma_addr_t buffer_dma, unsigned int sectors) +{ + struct host_to_dev_fis fis; + + memset(&fis, 0, sizeof(struct host_to_dev_fis)); + fis.type = 0x27; + fis.opts = 1 << 7; + fis.command = ATA_CMD_READ_LOG_EXT; + fis.sect_count = sectors & 0xFF; + fis.sect_cnt_ex = (sectors >> 8) & 0xFF; + fis.lba_low = page; + fis.lba_mid = 0; + fis.device = ATA_DEVICE_OBS; + + memset(buffer, 0, sectors * ATA_SECT_SIZE); + + return mtip_exec_internal_command(port, + &fis, + 5, + buffer_dma, + sectors * ATA_SECT_SIZE, + 0, + GFP_ATOMIC, + MTIP_INTERNAL_COMMAND_TIMEOUT_MS); +} + +/* + * Issue a SMART READ DATA command to the device. + * + * @port pointer to the port structure. + * @buffer pointer to buffer + * @buffer_dma dma address corresponding to @buffer + * + * return value + * @rv return value from mtip_exec_internal_command() + */ +static int mtip_get_smart_data(struct mtip_port *port, u8 *buffer, + dma_addr_t buffer_dma) +{ + struct host_to_dev_fis fis; + + memset(&fis, 0, sizeof(struct host_to_dev_fis)); + fis.type = 0x27; + fis.opts = 1 << 7; + fis.command = ATA_CMD_SMART; + fis.features = 0xD0; + fis.sect_count = 1; + fis.lba_mid = 0x4F; + fis.lba_hi = 0xC2; + fis.device = ATA_DEVICE_OBS; + + return mtip_exec_internal_command(port, + &fis, + 5, + buffer_dma, + ATA_SECT_SIZE, + 0, + GFP_ATOMIC, + 15000); +} + +/* + * Get the value of a smart attribute + * + * @port pointer to the port structure + * @id attribute number + * @attrib pointer to return attrib information corresponding to @id + * + * return value + * -EINVAL NULL buffer passed or unsupported attribute @id. + * -EPERM Identify data not valid, SMART not supported or not enabled + */ +static int mtip_get_smart_attr(struct mtip_port *port, unsigned int id, + struct smart_attr *attrib) +{ + int rv, i; + struct smart_attr *pattr; + + if (!attrib) + return -EINVAL; + + if (!port->identify_valid) { + dev_warn(&port->dd->pdev->dev, "IDENTIFY DATA not valid\n"); + return -EPERM; + } + if (!(port->identify[82] & 0x1)) { + dev_warn(&port->dd->pdev->dev, "SMART not supported\n"); + return -EPERM; + } + if (!(port->identify[85] & 0x1)) { + dev_warn(&port->dd->pdev->dev, "SMART not enabled\n"); + return -EPERM; + } + + memset(port->smart_buf, 0, ATA_SECT_SIZE); + rv = mtip_get_smart_data(port, port->smart_buf, port->smart_buf_dma); + if (rv) { + dev_warn(&port->dd->pdev->dev, "Failed to ge SMART data\n"); + return rv; + } + + pattr = (struct smart_attr *)(port->smart_buf + 2); + for (i = 0; i < 29; i++, pattr++) + if (pattr->attr_id == id) { + memcpy(attrib, pattr, sizeof(struct smart_attr)); + break; + } + + if (i == 29) { + dev_warn(&port->dd->pdev->dev, + "Query for invalid SMART attribute ID\n"); + rv = -EINVAL; + } return rv; } @@ -1504,10 +1839,7 @@ static int exec_drive_task(struct mtip_port *port, u8 *command) fis.cyl_hi = command[5]; fis.device = command[6] & ~0x10; /* Clear the dev bit*/ - - dbg_printk(MTIP_DRV_NAME "%s: User Command: cmd %x, feat %x, " - "nsect %x, sect %x, lcyl %x, " - "hcyl %x, sel %x\n", + dbg_printk(MTIP_DRV_NAME " %s: User Command: cmd %x, feat %x, nsect %x, sect %x, lcyl %x, hcyl %x, sel %x\n", __func__, command[0], command[1], @@ -1534,8 +1866,7 @@ static int exec_drive_task(struct mtip_port *port, u8 *command) command[4] = reply->cyl_low; command[5] = reply->cyl_hi; - dbg_printk(MTIP_DRV_NAME "%s: Completion Status: stat %x, " - "err %x , cyl_lo %x cyl_hi %x\n", + dbg_printk(MTIP_DRV_NAME " %s: Completion Status: stat %x, err %x , cyl_lo %x cyl_hi %x\n", __func__, command[0], command[1], @@ -1578,7 +1909,7 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, } dbg_printk(MTIP_DRV_NAME - "%s: User Command: cmd %x, sect %x, " + " %s: User Command: cmd %x, sect %x, " "feat %x, sectcnt %x\n", __func__, command[0], @@ -1607,7 +1938,7 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, command[2] = command[3]; dbg_printk(MTIP_DRV_NAME - "%s: Completion Status: stat %x, " + " %s: Completion Status: stat %x, " "err %x, cmd %x\n", __func__, command[0], @@ -1810,9 +2141,10 @@ static int exec_drive_taskfile(struct driver_data *dd, } dbg_printk(MTIP_DRV_NAME - "taskfile: cmd %x, feat %x, nsect %x," + " %s: cmd %x, feat %x, nsect %x," " sect/lbal %x, lcyl/lbam %x, hcyl/lbah %x," " head/dev %x\n", + __func__, fis.command, fis.features, fis.sect_count, @@ -1823,8 +2155,8 @@ static int exec_drive_taskfile(struct driver_data *dd, switch (fis.command) { case ATA_CMD_DOWNLOAD_MICRO: - /* Change timeout for Download Microcode to 60 seconds.*/ - timeout = 60000; + /* Change timeout for Download Microcode to 2 minutes */ + timeout = 120000; break; case ATA_CMD_SEC_ERASE_UNIT: /* Change timeout for Security Erase Unit to 4 minutes.*/ @@ -1840,8 +2172,8 @@ static int exec_drive_taskfile(struct driver_data *dd, timeout = 10000; break; case ATA_CMD_SMART: - /* Change timeout for vendor unique command to 10 secs */ - timeout = 10000; + /* Change timeout for vendor unique command to 15 secs */ + timeout = 15000; break; default: timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS; @@ -1903,18 +2235,8 @@ static int exec_drive_taskfile(struct driver_data *dd, req_task->hob_ports[1] = reply->features_ex; req_task->hob_ports[2] = reply->sect_cnt_ex; } - - /* Com rest after secure erase or lowlevel format */ - if (((fis.command == ATA_CMD_SEC_ERASE_UNIT) || - ((fis.command == 0xFC) && - (fis.features == 0x27 || fis.features == 0x72 || - fis.features == 0x62 || fis.features == 0x26))) && - !(reply->command & 1)) { - mtip_restart_port(dd->port); - } - dbg_printk(MTIP_DRV_NAME - "%s: Completion: stat %x," + " %s: Completion: stat %x," "err %x, sect_cnt %x, lbalo %x," "lbamid %x, lbahi %x, dev %x\n", __func__, @@ -2080,14 +2402,10 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, struct host_to_dev_fis *fis; struct mtip_port *port = dd->port; struct mtip_cmd *command = &port->commands[tag]; + int dma_dir = (dir == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; /* Map the scatter list for DMA access */ - if (dir == READ) - nents = dma_map_sg(&dd->pdev->dev, command->sg, - nents, DMA_FROM_DEVICE); - else - nents = dma_map_sg(&dd->pdev->dev, command->sg, - nents, DMA_TO_DEVICE); + nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir); command->scatter_ents = nents; @@ -2127,7 +2445,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, */ command->comp_data = dd; command->comp_func = mtip_async_complete; - command->direction = (dir == READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + command->direction = dma_dir; /* * Set the completion function and data for the command passed @@ -2140,19 +2458,16 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, * To prevent this command from being issued * if an internal command is in progress or error handling is active. */ - if (unlikely(test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) || - test_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags))) { + if (port->flags & MTIP_PF_PAUSE_IO) { set_bit(tag, port->cmds_to_issue); - set_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags); + set_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags); return; } /* Issue the command to the hardware */ mtip_issue_ncq_command(port, tag); - /* Set the command's timeout value.*/ - port->commands[tag].comp_time = jiffies + msecs_to_jiffies( - MTIP_NCQ_COMMAND_TIMEOUT_MS); + return; } /* @@ -2191,6 +2506,10 @@ static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd, down(&dd->port->cmd_slot); *tag = get_slot(dd->port); + if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))) { + up(&dd->port->cmd_slot); + return NULL; + } if (unlikely(*tag < 0)) return NULL; @@ -2207,7 +2526,7 @@ static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd, * return value * The size, in bytes, of the data copied into buf. */ -static ssize_t hw_show_registers(struct device *dev, +static ssize_t mtip_hw_show_registers(struct device *dev, struct device_attribute *attr, char *buf) { @@ -2216,7 +2535,7 @@ static ssize_t hw_show_registers(struct device *dev, int size = 0; int n; - size += sprintf(&buf[size], "%s:\ns_active:\n", __func__); + size += sprintf(&buf[size], "S ACTive:\n"); for (n = 0; n < dd->slot_groups; n++) size += sprintf(&buf[size], "0x%08x\n", @@ -2240,20 +2559,39 @@ static ssize_t hw_show_registers(struct device *dev, group_allocated); } - size += sprintf(&buf[size], "completed:\n"); + size += sprintf(&buf[size], "Completed:\n"); for (n = 0; n < dd->slot_groups; n++) size += sprintf(&buf[size], "0x%08x\n", readl(dd->port->completed[n])); - size += sprintf(&buf[size], "PORT_IRQ_STAT 0x%08x\n", + size += sprintf(&buf[size], "PORT IRQ STAT : 0x%08x\n", readl(dd->port->mmio + PORT_IRQ_STAT)); - size += sprintf(&buf[size], "HOST_IRQ_STAT 0x%08x\n", + size += sprintf(&buf[size], "HOST IRQ STAT : 0x%08x\n", readl(dd->mmio + HOST_IRQ_STAT)); return size; } -static DEVICE_ATTR(registers, S_IRUGO, hw_show_registers, NULL); + +static ssize_t mtip_hw_show_status(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct driver_data *dd = dev_to_disk(dev)->private_data; + int size = 0; + + if (test_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag)) + size += sprintf(buf, "%s", "thermal_shutdown\n"); + else if (test_bit(MTIP_DDF_WRITE_PROTECT_BIT, &dd->dd_flag)) + size += sprintf(buf, "%s", "write_protect\n"); + else + size += sprintf(buf, "%s", "online\n"); + + return size; +} + +static DEVICE_ATTR(registers, S_IRUGO, mtip_hw_show_registers, NULL); +static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL); /* * Create the sysfs related attributes. @@ -2272,7 +2610,10 @@ static int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj) if (sysfs_create_file(kobj, &dev_attr_registers.attr)) dev_warn(&dd->pdev->dev, - "Error creating registers sysfs entry\n"); + "Error creating 'registers' sysfs entry\n"); + if (sysfs_create_file(kobj, &dev_attr_status.attr)) + dev_warn(&dd->pdev->dev, + "Error creating 'status' sysfs entry\n"); return 0; } @@ -2292,6 +2633,7 @@ static int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj) return -EINVAL; sysfs_remove_file(kobj, &dev_attr_registers.attr); + sysfs_remove_file(kobj, &dev_attr_status.attr); return 0; } @@ -2384,10 +2726,12 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd) "FTL rebuild in progress. Polling for completion.\n"); start = jiffies; - dd->ftlrebuildflag = 1; timeout = jiffies + msecs_to_jiffies(MTIP_FTL_REBUILD_TIMEOUT_MS); do { + if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, + &dd->dd_flag))) + return -EFAULT; if (mtip_check_surprise_removal(dd->pdev)) return -EFAULT; @@ -2408,22 +2752,17 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd) dev_warn(&dd->pdev->dev, "FTL rebuild complete (%d secs).\n", jiffies_to_msecs(jiffies - start) / 1000); - dd->ftlrebuildflag = 0; mtip_block_initialize(dd); - break; + return 0; } ssleep(10); } while (time_before(jiffies, timeout)); /* Check for timeout */ - if (dd->ftlrebuildflag) { - dev_err(&dd->pdev->dev, + dev_err(&dd->pdev->dev, "Timed out waiting for FTL rebuild to complete (%d secs).\n", jiffies_to_msecs(jiffies - start) / 1000); - return -EFAULT; - } - - return 0; + return -EFAULT; } /* @@ -2448,14 +2787,17 @@ static int mtip_service_thread(void *data) * is in progress nor error handling is active */ wait_event_interruptible(port->svc_wait, (port->flags) && - !test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) && - !test_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags)); + !(port->flags & MTIP_PF_PAUSE_IO)); if (kthread_should_stop()) break; - set_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags); - if (test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) { + if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, + &dd->dd_flag))) + break; + + set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags); + if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) { slot = 1; /* used to restrict the loop to one iteration */ slot_start = num_cmd_slots; @@ -2480,21 +2822,19 @@ static int mtip_service_thread(void *data) /* Issue the command to the hardware */ mtip_issue_ncq_command(port, slot); - /* Set the command's timeout value.*/ - port->commands[slot].comp_time = jiffies + - msecs_to_jiffies(MTIP_NCQ_COMMAND_TIMEOUT_MS); - clear_bit(slot, port->cmds_to_issue); } - clear_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags); - } else if (test_bit(MTIP_FLAG_REBUILD_BIT, &port->flags)) { - mtip_ftl_rebuild_poll(dd); - clear_bit(MTIP_FLAG_REBUILD_BIT, &port->flags); + clear_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags); + } else if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) { + if (!mtip_ftl_rebuild_poll(dd)) + set_bit(MTIP_DDF_REBUILD_FAILED_BIT, + &dd->dd_flag); + clear_bit(MTIP_PF_REBUILD_BIT, &port->flags); } - clear_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags); + clear_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags); - if (test_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &port->flags)) + if (test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags)) break; } return 0; @@ -2513,6 +2853,9 @@ static int mtip_hw_init(struct driver_data *dd) int i; int rv; unsigned int num_command_slots; + unsigned long timeout, timetaken; + unsigned char *buf; + struct smart_attr attr242; dd->mmio = pcim_iomap_table(dd->pdev)[MTIP_ABAR]; @@ -2547,7 +2890,7 @@ static int mtip_hw_init(struct driver_data *dd) /* Allocate memory for the command list. */ dd->port->command_list = dmam_alloc_coherent(&dd->pdev->dev, - HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2), + HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4), &dd->port->command_list_dma, GFP_KERNEL); if (!dd->port->command_list) { @@ -2560,7 +2903,7 @@ static int mtip_hw_init(struct driver_data *dd) /* Clear the memory we have allocated. */ memset(dd->port->command_list, 0, - HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2)); + HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4)); /* Setup the addresse of the RX FIS. */ dd->port->rxfis = dd->port->command_list + HW_CMD_SLOT_SZ; @@ -2576,10 +2919,19 @@ static int mtip_hw_init(struct driver_data *dd) dd->port->identify_dma = dd->port->command_tbl_dma + HW_CMD_TBL_AR_SZ; - /* Setup the address of the sector buffer. */ + /* Setup the address of the sector buffer - for some non-ncq cmds */ dd->port->sector_buffer = (void *) dd->port->identify + ATA_SECT_SIZE; dd->port->sector_buffer_dma = dd->port->identify_dma + ATA_SECT_SIZE; + /* Setup the address of the log buf - for read log command */ + dd->port->log_buf = (void *)dd->port->sector_buffer + ATA_SECT_SIZE; + dd->port->log_buf_dma = dd->port->sector_buffer_dma + ATA_SECT_SIZE; + + /* Setup the address of the smart buf - for smart read data command */ + dd->port->smart_buf = (void *)dd->port->log_buf + ATA_SECT_SIZE; + dd->port->smart_buf_dma = dd->port->log_buf_dma + ATA_SECT_SIZE; + + /* Point the command headers at the command tables. */ for (i = 0; i < num_command_slots; i++) { dd->port->commands[i].command_header = @@ -2623,14 +2975,43 @@ static int mtip_hw_init(struct driver_data *dd) dd->port->mmio + i*0x80 + PORT_SDBV; } - /* Reset the HBA. */ - if (mtip_hba_reset(dd) < 0) { - dev_err(&dd->pdev->dev, - "Card did not reset within timeout\n"); - rv = -EIO; + timetaken = jiffies; + timeout = jiffies + msecs_to_jiffies(30000); + while (((readl(dd->port->mmio + PORT_SCR_STAT) & 0x0F) != 0x03) && + time_before(jiffies, timeout)) { + mdelay(100); + } + if (unlikely(mtip_check_surprise_removal(dd->pdev))) { + timetaken = jiffies - timetaken; + dev_warn(&dd->pdev->dev, + "Surprise removal detected at %u ms\n", + jiffies_to_msecs(timetaken)); + rv = -ENODEV; + goto out2 ; + } + if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))) { + timetaken = jiffies - timetaken; + dev_warn(&dd->pdev->dev, + "Removal detected at %u ms\n", + jiffies_to_msecs(timetaken)); + rv = -EFAULT; goto out2; } + /* Conditionally reset the HBA. */ + if (!(readl(dd->mmio + HOST_CAP) & HOST_CAP_NZDMA)) { + if (mtip_hba_reset(dd) < 0) { + dev_err(&dd->pdev->dev, + "Card did not reset within timeout\n"); + rv = -EIO; + goto out2; + } + } else { + /* Clear any pending interrupts on the HBA */ + writel(readl(dd->mmio + HOST_IRQ_STAT), + dd->mmio + HOST_IRQ_STAT); + } + mtip_init_port(dd->port); mtip_start_port(dd->port); @@ -2660,6 +3041,12 @@ static int mtip_hw_init(struct driver_data *dd) mod_timer(&dd->port->cmd_timer, jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD)); + + if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)) { + rv = -EFAULT; + goto out3; + } + if (mtip_get_identify(dd->port, NULL) < 0) { rv = -EFAULT; goto out3; @@ -2667,10 +3054,47 @@ static int mtip_hw_init(struct driver_data *dd) if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) == MTIP_FTL_REBUILD_MAGIC) { - set_bit(MTIP_FLAG_REBUILD_BIT, &dd->port->flags); + set_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags); return MTIP_FTL_REBUILD_MAGIC; } mtip_dump_identify(dd->port); + + /* check write protect, over temp and rebuild statuses */ + rv = mtip_read_log_page(dd->port, ATA_LOG_SATA_NCQ, + dd->port->log_buf, + dd->port->log_buf_dma, 1); + if (rv) { + dev_warn(&dd->pdev->dev, + "Error in READ LOG EXT (10h) command\n"); + /* non-critical error, don't fail the load */ + } else { + buf = (unsigned char *)dd->port->log_buf; + if (buf[259] & 0x1) { + dev_info(&dd->pdev->dev, + "Write protect bit is set.\n"); + set_bit(MTIP_DDF_WRITE_PROTECT_BIT, &dd->dd_flag); + } + if (buf[288] == 0xF7) { + dev_info(&dd->pdev->dev, + "Exceeded Tmax, drive in thermal shutdown.\n"); + set_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag); + } + if (buf[288] == 0xBF) { + dev_info(&dd->pdev->dev, + "Drive indicates rebuild has failed.\n"); + /* TODO */ + } + } + + /* get write protect progess */ + memset(&attr242, 0, sizeof(struct smart_attr)); + if (mtip_get_smart_attr(dd->port, 242, &attr242)) + dev_warn(&dd->pdev->dev, + "Unable to check write protect progress\n"); + else + dev_info(&dd->pdev->dev, + "Write protect progress: %d%% (%d blocks)\n", + attr242.cur, attr242.data); return rv; out3: @@ -2688,7 +3112,7 @@ out2: /* Free the command/command header memory. */ dmam_free_coherent(&dd->pdev->dev, - HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2), + HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4), dd->port->command_list, dd->port->command_list_dma); out1: @@ -2712,9 +3136,12 @@ static int mtip_hw_exit(struct driver_data *dd) * Send standby immediate (E0h) to the drive so that it * saves its state. */ - if (atomic_read(&dd->drv_cleanup_done) != true) { + if (!test_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag)) { - mtip_standby_immediate(dd->port); + if (!test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags)) + if (mtip_standby_immediate(dd->port)) + dev_warn(&dd->pdev->dev, + "STANDBY IMMEDIATE failed\n"); /* de-initialize the port. */ mtip_deinit_port(dd->port); @@ -2734,7 +3161,7 @@ static int mtip_hw_exit(struct driver_data *dd) /* Free the command/command header memory. */ dmam_free_coherent(&dd->pdev->dev, - HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2), + HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4), dd->port->command_list, dd->port->command_list_dma); /* Free the memory allocated for the for structure. */ @@ -2892,6 +3319,9 @@ static int mtip_block_ioctl(struct block_device *dev, if (!dd) return -ENOTTY; + if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))) + return -ENOTTY; + switch (cmd) { case BLKFLSBUF: return -ENOTTY; @@ -2927,6 +3357,9 @@ static int mtip_block_compat_ioctl(struct block_device *dev, if (!dd) return -ENOTTY; + if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))) + return -ENOTTY; + switch (cmd) { case BLKFLSBUF: return -ENOTTY; @@ -3049,6 +3482,24 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) int nents = 0; int tag = 0; + if (unlikely(dd->dd_flag & MTIP_DDF_STOP_IO)) { + if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, + &dd->dd_flag))) { + bio_endio(bio, -ENXIO); + return; + } + if (unlikely(test_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag))) { + bio_endio(bio, -ENODATA); + return; + } + if (unlikely(test_bit(MTIP_DDF_WRITE_PROTECT_BIT, + &dd->dd_flag) && + bio_data_dir(bio))) { + bio_endio(bio, -ENODATA); + return; + } + } + if (unlikely(!bio_has_data(bio))) { blk_queue_flush(queue, 0); bio_endio(bio, 0); @@ -3061,7 +3512,7 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) if (unlikely((bio)->bi_vcnt > MTIP_MAX_SG)) { dev_warn(&dd->pdev->dev, - "Maximum number of SGL entries exceeded"); + "Maximum number of SGL entries exceeded\n"); bio_io_error(bio); mtip_hw_release_scatterlist(dd, tag); return; @@ -3210,8 +3661,10 @@ skip_create_disk: kobject_put(kobj); } - if (dd->mtip_svc_handler) + if (dd->mtip_svc_handler) { + set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag); return rv; /* service thread created for handling rebuild */ + } start_service_thread: sprintf(thd_name, "mtip_svc_thd_%02d", index); @@ -3220,12 +3673,15 @@ start_service_thread: dd, thd_name); if (IS_ERR(dd->mtip_svc_handler)) { - printk(KERN_ERR "mtip32xx: service thread failed to start\n"); + dev_err(&dd->pdev->dev, "service thread failed to start\n"); dd->mtip_svc_handler = NULL; rv = -EFAULT; goto kthread_run_error; } + if (wait_for_rebuild == MTIP_FTL_REBUILD_MAGIC) + rv = wait_for_rebuild; + return rv; kthread_run_error: @@ -3266,16 +3722,18 @@ static int mtip_block_remove(struct driver_data *dd) struct kobject *kobj; if (dd->mtip_svc_handler) { - set_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &dd->port->flags); + set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags); wake_up_interruptible(&dd->port->svc_wait); kthread_stop(dd->mtip_svc_handler); } - /* Clean up the sysfs attributes managed by the protocol layer. */ - kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); - if (kobj) { - mtip_hw_sysfs_exit(dd, kobj); - kobject_put(kobj); + /* Clean up the sysfs attributes, if created */ + if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) { + kobj = kobject_get(&disk_to_dev(dd->disk)->kobj); + if (kobj) { + mtip_hw_sysfs_exit(dd, kobj); + kobject_put(kobj); + } } /* @@ -3283,6 +3741,11 @@ static int mtip_block_remove(struct driver_data *dd) * from /dev */ del_gendisk(dd->disk); + + spin_lock(&rssd_index_lock); + ida_remove(&rssd_index_ida, dd->index); + spin_unlock(&rssd_index_lock); + blk_cleanup_queue(dd->queue); dd->disk = NULL; dd->queue = NULL; @@ -3312,6 +3775,11 @@ static int mtip_block_shutdown(struct driver_data *dd) /* Delete our gendisk structure, and cleanup the blk queue. */ del_gendisk(dd->disk); + + spin_lock(&rssd_index_lock); + ida_remove(&rssd_index_ida, dd->index); + spin_unlock(&rssd_index_lock); + blk_cleanup_queue(dd->queue); dd->disk = NULL; dd->queue = NULL; @@ -3359,11 +3827,6 @@ static int mtip_pci_probe(struct pci_dev *pdev, return -ENOMEM; } - /* Set the atomic variable as 1 in case of SRSI */ - atomic_set(&dd->drv_cleanup_done, true); - - atomic_set(&dd->resumeflag, false); - /* Attach the private data to this PCI device. */ pci_set_drvdata(pdev, dd); @@ -3420,7 +3883,8 @@ static int mtip_pci_probe(struct pci_dev *pdev, * instance number. */ instance++; - + if (rv != MTIP_FTL_REBUILD_MAGIC) + set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag); goto done; block_initialize_err: @@ -3434,9 +3898,6 @@ iomap_err: pci_set_drvdata(pdev, NULL); return rv; done: - /* Set the atomic variable as 0 in case of SRSI */ - atomic_set(&dd->drv_cleanup_done, true); - return rv; } @@ -3452,8 +3913,10 @@ static void mtip_pci_remove(struct pci_dev *pdev) struct driver_data *dd = pci_get_drvdata(pdev); int counter = 0; + set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag); + if (mtip_check_surprise_removal(pdev)) { - while (atomic_read(&dd->drv_cleanup_done) == false) { + while (!test_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag)) { counter++; msleep(20); if (counter == 10) { @@ -3463,8 +3926,6 @@ static void mtip_pci_remove(struct pci_dev *pdev) } } } - /* Set the atomic variable as 1 in case of SRSI */ - atomic_set(&dd->drv_cleanup_done, true); /* Clean up the block layer. */ mtip_block_remove(dd); @@ -3493,7 +3954,7 @@ static int mtip_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) return -EFAULT; } - atomic_set(&dd->resumeflag, true); + set_bit(MTIP_DDF_RESUME_BIT, &dd->dd_flag); /* Disable ports & interrupts then send standby immediate */ rv = mtip_block_suspend(dd); @@ -3559,7 +4020,7 @@ static int mtip_pci_resume(struct pci_dev *pdev) dev_err(&pdev->dev, "Unable to resume\n"); err: - atomic_set(&dd->resumeflag, false); + clear_bit(MTIP_DDF_RESUME_BIT, &dd->dd_flag); return rv; } @@ -3608,18 +4069,25 @@ MODULE_DEVICE_TABLE(pci, mtip_pci_tbl); */ static int __init mtip_init(void) { + int error; + printk(KERN_INFO MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n"); /* Allocate a major block device number to use with this driver. */ - mtip_major = register_blkdev(0, MTIP_DRV_NAME); - if (mtip_major < 0) { + error = register_blkdev(0, MTIP_DRV_NAME); + if (error <= 0) { printk(KERN_ERR "Unable to register block device (%d)\n", - mtip_major); + error); return -EBUSY; } + mtip_major = error; /* Register our PCI operations. */ - return pci_register_driver(&mtip_pci_driver); + error = pci_register_driver(&mtip_pci_driver); + if (error) + unregister_blkdev(mtip_major, MTIP_DRV_NAME); + + return error; } /* diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index e0554a8f2233..4ef58336310a 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -34,8 +34,8 @@ /* offset of Device Control register in PCIe extended capabilites space */ #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48 -/* # of times to retry timed out IOs */ -#define MTIP_MAX_RETRIES 5 +/* # of times to retry timed out/failed IOs */ +#define MTIP_MAX_RETRIES 2 /* Various timeout values in ms */ #define MTIP_NCQ_COMMAND_TIMEOUT_MS 5000 @@ -114,12 +114,41 @@ #define __force_bit2int (unsigned int __force) /* below are bit numbers in 'flags' defined in mtip_port */ -#define MTIP_FLAG_IC_ACTIVE_BIT 0 -#define MTIP_FLAG_EH_ACTIVE_BIT 1 -#define MTIP_FLAG_SVC_THD_ACTIVE_BIT 2 -#define MTIP_FLAG_ISSUE_CMDS_BIT 4 -#define MTIP_FLAG_REBUILD_BIT 5 -#define MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT 8 +#define MTIP_PF_IC_ACTIVE_BIT 0 /* pio/ioctl */ +#define MTIP_PF_EH_ACTIVE_BIT 1 /* error handling */ +#define MTIP_PF_SE_ACTIVE_BIT 2 /* secure erase */ +#define MTIP_PF_DM_ACTIVE_BIT 3 /* download microcde */ +#define MTIP_PF_PAUSE_IO ((1 << MTIP_PF_IC_ACTIVE_BIT) | \ + (1 << MTIP_PF_EH_ACTIVE_BIT) | \ + (1 << MTIP_PF_SE_ACTIVE_BIT) | \ + (1 << MTIP_PF_DM_ACTIVE_BIT)) + +#define MTIP_PF_SVC_THD_ACTIVE_BIT 4 +#define MTIP_PF_ISSUE_CMDS_BIT 5 +#define MTIP_PF_REBUILD_BIT 6 +#define MTIP_PF_SVC_THD_STOP_BIT 8 + +/* below are bit numbers in 'dd_flag' defined in driver_data */ +#define MTIP_DDF_REMOVE_PENDING_BIT 1 +#define MTIP_DDF_OVER_TEMP_BIT 2 +#define MTIP_DDF_WRITE_PROTECT_BIT 3 +#define MTIP_DDF_STOP_IO ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \ + (1 << MTIP_DDF_OVER_TEMP_BIT) | \ + (1 << MTIP_DDF_WRITE_PROTECT_BIT)) + +#define MTIP_DDF_CLEANUP_BIT 5 +#define MTIP_DDF_RESUME_BIT 6 +#define MTIP_DDF_INIT_DONE_BIT 7 +#define MTIP_DDF_REBUILD_FAILED_BIT 8 + +__packed struct smart_attr{ + u8 attr_id; + u16 flags; + u8 cur; + u8 worst; + u32 data; + u8 res[3]; +}; /* Register Frame Information Structure (FIS), host to device. */ struct host_to_dev_fis { @@ -345,6 +374,12 @@ struct mtip_port { * when the command slot and all associated data structures * are no longer needed. */ + u16 *log_buf; + dma_addr_t log_buf_dma; + + u8 *smart_buf; + dma_addr_t smart_buf_dma; + unsigned long allocated[SLOTBITS_IN_LONGS]; /* * used to queue commands when an internal command is in progress @@ -368,6 +403,7 @@ struct mtip_port { * Timer used to complete commands that have been active for too long. */ struct timer_list cmd_timer; + unsigned long ic_pause_timer; /* * Semaphore used to block threads if there are no * command slots available. @@ -404,13 +440,9 @@ struct driver_data { unsigned slot_groups; /* number of slot groups the product supports */ - atomic_t drv_cleanup_done; /* Atomic variable for SRSI */ - unsigned long index; /* Index to determine the disk name */ - unsigned int ftlrebuildflag; /* FTL rebuild flag */ - - atomic_t resumeflag; /* Atomic variable to track suspend/resume */ + unsigned long dd_flag; /* NOTE: use atomic bit operations on this */ struct task_struct *mtip_svc_handler; /* task_struct of svc thd */ }; diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index c4a60badf252..0d39f2f4294a 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -351,6 +351,7 @@ static void virtblk_config_changed_work(struct work_struct *work) cap_str_10, cap_str_2); set_capacity(vblk->disk, capacity); + revalidate_disk(vblk->disk); done: mutex_unlock(&vblk->config_lock); } @@ -374,6 +375,34 @@ static int init_vq(struct virtio_blk *vblk) return err; } +/* + * Legacy naming scheme used for virtio devices. We are stuck with it for + * virtio blk but don't ever use it for any new driver. + */ +static int virtblk_name_format(char *prefix, int index, char *buf, int buflen) +{ + const int base = 'z' - 'a' + 1; + char *begin = buf + strlen(prefix); + char *end = buf + buflen; + char *p; + int unit; + + p = end - 1; + *p = '\0'; + unit = base; + do { + if (p == begin) + return -EINVAL; + *--p = 'a' + (index % unit); + index = (index / unit) - 1; + } while (index >= 0); + + memmove(begin, p, end - p); + memcpy(buf, prefix, strlen(prefix)); + + return 0; +} + static int __devinit virtblk_probe(struct virtio_device *vdev) { struct virtio_blk *vblk; @@ -442,18 +471,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) q->queuedata = vblk; - if (index < 26) { - sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26); - } else if (index < (26 + 1) * 26) { - sprintf(vblk->disk->disk_name, "vd%c%c", - 'a' + index / 26 - 1, 'a' + index % 26); - } else { - const unsigned int m1 = (index / 26 - 1) / 26 - 1; - const unsigned int m2 = (index / 26 - 1) % 26; - const unsigned int m3 = index % 26; - sprintf(vblk->disk->disk_name, "vd%c%c%c", - 'a' + m1, 'a' + m2, 'a' + m3); - } + virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN); vblk->disk->major = major; vblk->disk->first_minor = index_to_minor(index); diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 0088bf60f368..73f196ca713f 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -321,6 +321,7 @@ struct seg_buf { static void xen_blkbk_unmap(struct pending_req *req) { struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST]; unsigned int i, invcount = 0; grant_handle_t handle; int ret; @@ -332,25 +333,12 @@ static void xen_blkbk_unmap(struct pending_req *req) gnttab_set_unmap_op(&unmap[invcount], vaddr(req, i), GNTMAP_host_map, handle); pending_handle(req, i) = BLKBACK_INVALID_HANDLE; + pages[invcount] = virt_to_page(vaddr(req, i)); invcount++; } - ret = HYPERVISOR_grant_table_op( - GNTTABOP_unmap_grant_ref, unmap, invcount); + ret = gnttab_unmap_refs(unmap, pages, invcount, false); BUG_ON(ret); - /* - * Note, we use invcount, so nr->pages, so we can't index - * using vaddr(req, i). - */ - for (i = 0; i < invcount; i++) { - ret = m2p_remove_override( - virt_to_page(unmap[i].host_addr), false); - if (ret) { - pr_alert(DRV_PFX "Failed to remove M2P override for %lx\n", - (unsigned long)unmap[i].host_addr); - continue; - } - } } static int xen_blkbk_map(struct blkif_request *req, @@ -378,7 +366,7 @@ static int xen_blkbk_map(struct blkif_request *req, pending_req->blkif->domid); } - ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg); + ret = gnttab_map_refs(map, NULL, &blkbk->pending_page(pending_req, 0), nseg); BUG_ON(ret); /* @@ -398,15 +386,6 @@ static int xen_blkbk_map(struct blkif_request *req, if (ret) continue; - ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr), - blkbk->pending_page(pending_req, i), NULL); - if (ret) { - pr_alert(DRV_PFX "Failed to install M2P override for %lx (ret: %d)\n", - (unsigned long)map[i].dev_bus_addr, ret); - /* We could switch over to GNTTABOP_copy */ - continue; - } - seg[i].buf = map[i].dev_bus_addr | (req->u.rw.seg[i].first_sect << 9); } @@ -419,21 +398,18 @@ static int dispatch_discard_io(struct xen_blkif *blkif, int err = 0; int status = BLKIF_RSP_OKAY; struct block_device *bdev = blkif->vbd.bdev; + unsigned long secure; blkif->st_ds_req++; xen_blkif_get(blkif); - if (blkif->blk_backend_type == BLKIF_BACKEND_PHY || - blkif->blk_backend_type == BLKIF_BACKEND_FILE) { - unsigned long secure = (blkif->vbd.discard_secure && - (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ? - BLKDEV_DISCARD_SECURE : 0; - err = blkdev_issue_discard(bdev, - req->u.discard.sector_number, - req->u.discard.nr_sectors, - GFP_KERNEL, secure); - } else - err = -EOPNOTSUPP; + secure = (blkif->vbd.discard_secure && + (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ? + BLKDEV_DISCARD_SECURE : 0; + + err = blkdev_issue_discard(bdev, req->u.discard.sector_number, + req->u.discard.nr_sectors, + GFP_KERNEL, secure); if (err == -EOPNOTSUPP) { pr_debug(DRV_PFX "discard op failed, not supported\n"); @@ -830,7 +806,7 @@ static int __init xen_blkif_init(void) int i, mmap_pages; int rc = 0; - if (!xen_pv_domain()) + if (!xen_domain()) return -ENODEV; blkbk = kzalloc(sizeof(struct xen_blkbk), GFP_KERNEL); diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index d0ee7edc9be8..773cf27dc23f 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -146,11 +146,6 @@ enum blkif_protocol { BLKIF_PROTOCOL_X86_64 = 3, }; -enum blkif_backend_type { - BLKIF_BACKEND_PHY = 1, - BLKIF_BACKEND_FILE = 2, -}; - struct xen_vbd { /* What the domain refers to this vbd as. */ blkif_vdev_t handle; @@ -177,7 +172,6 @@ struct xen_blkif { unsigned int irq; /* Comms information. */ enum blkif_protocol blk_protocol; - enum blkif_backend_type blk_backend_type; union blkif_back_rings blk_rings; void *blk_ring; /* The VBD attached to this interface. */ diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 24a2fb57e5d0..89860f34a7ec 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -381,72 +381,49 @@ int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, err = xenbus_printf(xbt, dev->nodename, "feature-flush-cache", "%d", state); if (err) - xenbus_dev_fatal(dev, err, "writing feature-flush-cache"); + dev_warn(&dev->dev, "writing feature-flush-cache (%d)", err); return err; } -int xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be) +static void xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be) { struct xenbus_device *dev = be->dev; struct xen_blkif *blkif = be->blkif; - char *type; int err; int state = 0; + struct block_device *bdev = be->blkif->vbd.bdev; + struct request_queue *q = bdev_get_queue(bdev); - type = xenbus_read(XBT_NIL, dev->nodename, "type", NULL); - if (!IS_ERR(type)) { - if (strncmp(type, "file", 4) == 0) { - state = 1; - blkif->blk_backend_type = BLKIF_BACKEND_FILE; + if (blk_queue_discard(q)) { + err = xenbus_printf(xbt, dev->nodename, + "discard-granularity", "%u", + q->limits.discard_granularity); + if (err) { + dev_warn(&dev->dev, "writing discard-granularity (%d)", err); + return; } - if (strncmp(type, "phy", 3) == 0) { - struct block_device *bdev = be->blkif->vbd.bdev; - struct request_queue *q = bdev_get_queue(bdev); - if (blk_queue_discard(q)) { - err = xenbus_printf(xbt, dev->nodename, - "discard-granularity", "%u", - q->limits.discard_granularity); - if (err) { - xenbus_dev_fatal(dev, err, - "writing discard-granularity"); - goto kfree; - } - err = xenbus_printf(xbt, dev->nodename, - "discard-alignment", "%u", - q->limits.discard_alignment); - if (err) { - xenbus_dev_fatal(dev, err, - "writing discard-alignment"); - goto kfree; - } - state = 1; - blkif->blk_backend_type = BLKIF_BACKEND_PHY; - } - /* Optional. */ - err = xenbus_printf(xbt, dev->nodename, - "discard-secure", "%d", - blkif->vbd.discard_secure); - if (err) { - xenbus_dev_fatal(dev, err, - "writting discard-secure"); - goto kfree; - } + err = xenbus_printf(xbt, dev->nodename, + "discard-alignment", "%u", + q->limits.discard_alignment); + if (err) { + dev_warn(&dev->dev, "writing discard-alignment (%d)", err); + return; + } + state = 1; + /* Optional. */ + err = xenbus_printf(xbt, dev->nodename, + "discard-secure", "%d", + blkif->vbd.discard_secure); + if (err) { + dev_warn(dev-dev, "writing discard-secure (%d)", err); + return; } - } else { - err = PTR_ERR(type); - xenbus_dev_fatal(dev, err, "reading type"); - goto out; } - err = xenbus_printf(xbt, dev->nodename, "feature-discard", "%d", state); if (err) - xenbus_dev_fatal(dev, err, "writing feature-discard"); -kfree: - kfree(type); -out: - return err; + dev_warn(&dev->dev, "writing feature-discard (%d)", err); } int xen_blkbk_barrier(struct xenbus_transaction xbt, struct backend_info *be, int state) @@ -457,7 +434,7 @@ int xen_blkbk_barrier(struct xenbus_transaction xbt, err = xenbus_printf(xbt, dev->nodename, "feature-barrier", "%d", state); if (err) - xenbus_dev_fatal(dev, err, "writing feature-barrier"); + dev_warn(&dev->dev, "writing feature-barrier (%d)", err); return err; } @@ -689,14 +666,12 @@ again: return; } - err = xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support); - if (err) - goto abort; + /* If we can't advertise it is OK. */ + xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support); - err = xen_blkbk_discard(xbt, be); + xen_blkbk_discard(xbt, be); - /* If we can't advertise it is OK. */ - err = xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support); + xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support); err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", (unsigned long long)vbd_sz(&be->blkif->vbd)); diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 98cbeba8cd53..4e86393a09cf 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -43,6 +43,7 @@ #include <linux/slab.h> #include <linux/mutex.h> #include <linux/scatterlist.h> +#include <linux/bitmap.h> #include <xen/xen.h> #include <xen/xenbus.h> @@ -81,6 +82,7 @@ static const struct block_device_operations xlvbd_block_fops; */ struct blkfront_info { + spinlock_t io_lock; struct mutex mutex; struct xenbus_device *xbdev; struct gendisk *gd; @@ -105,8 +107,6 @@ struct blkfront_info int is_ready; }; -static DEFINE_SPINLOCK(blkif_io_lock); - static unsigned int nr_minors; static unsigned long *minors; static DEFINE_SPINLOCK(minor_lock); @@ -177,8 +177,7 @@ static int xlbd_reserve_minors(unsigned int minor, unsigned int nr) spin_lock(&minor_lock); if (find_next_bit(minors, end, minor) >= end) { - for (; minor < end; ++minor) - __set_bit(minor, minors); + bitmap_set(minors, minor, nr); rc = 0; } else rc = -EBUSY; @@ -193,8 +192,7 @@ static void xlbd_release_minors(unsigned int minor, unsigned int nr) BUG_ON(end > nr_minors); spin_lock(&minor_lock); - for (; minor < end; ++minor) - __clear_bit(minor, minors); + bitmap_clear(minors, minor, nr); spin_unlock(&minor_lock); } @@ -419,7 +417,7 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) struct request_queue *rq; struct blkfront_info *info = gd->private_data; - rq = blk_init_queue(do_blkif_request, &blkif_io_lock); + rq = blk_init_queue(do_blkif_request, &info->io_lock); if (rq == NULL) return -1; @@ -636,14 +634,14 @@ static void xlvbd_release_gendisk(struct blkfront_info *info) if (info->rq == NULL) return; - spin_lock_irqsave(&blkif_io_lock, flags); + spin_lock_irqsave(&info->io_lock, flags); /* No more blkif_request(). */ blk_stop_queue(info->rq); /* No more gnttab callback work. */ gnttab_cancel_free_callback(&info->callback); - spin_unlock_irqrestore(&blkif_io_lock, flags); + spin_unlock_irqrestore(&info->io_lock, flags); /* Flush gnttab callback work. Must be done with no locks held. */ flush_work_sync(&info->work); @@ -675,16 +673,16 @@ static void blkif_restart_queue(struct work_struct *work) { struct blkfront_info *info = container_of(work, struct blkfront_info, work); - spin_lock_irq(&blkif_io_lock); + spin_lock_irq(&info->io_lock); if (info->connected == BLKIF_STATE_CONNECTED) kick_pending_request_queues(info); - spin_unlock_irq(&blkif_io_lock); + spin_unlock_irq(&info->io_lock); } static void blkif_free(struct blkfront_info *info, int suspend) { /* Prevent new requests being issued until we fix things up. */ - spin_lock_irq(&blkif_io_lock); + spin_lock_irq(&info->io_lock); info->connected = suspend ? BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED; /* No more blkif_request(). */ @@ -692,7 +690,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) blk_stop_queue(info->rq); /* No more gnttab callback work. */ gnttab_cancel_free_callback(&info->callback); - spin_unlock_irq(&blkif_io_lock); + spin_unlock_irq(&info->io_lock); /* Flush gnttab callback work. Must be done with no locks held. */ flush_work_sync(&info->work); @@ -728,10 +726,10 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) struct blkfront_info *info = (struct blkfront_info *)dev_id; int error; - spin_lock_irqsave(&blkif_io_lock, flags); + spin_lock_irqsave(&info->io_lock, flags); if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) { - spin_unlock_irqrestore(&blkif_io_lock, flags); + spin_unlock_irqrestore(&info->io_lock, flags); return IRQ_HANDLED; } @@ -816,7 +814,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) kick_pending_request_queues(info); - spin_unlock_irqrestore(&blkif_io_lock, flags); + spin_unlock_irqrestore(&info->io_lock, flags); return IRQ_HANDLED; } @@ -991,6 +989,7 @@ static int blkfront_probe(struct xenbus_device *dev, } mutex_init(&info->mutex); + spin_lock_init(&info->io_lock); info->xbdev = dev; info->vdevice = vdevice; info->connected = BLKIF_STATE_DISCONNECTED; @@ -1068,7 +1067,7 @@ static int blkif_recover(struct blkfront_info *info) xenbus_switch_state(info->xbdev, XenbusStateConnected); - spin_lock_irq(&blkif_io_lock); + spin_lock_irq(&info->io_lock); /* Now safe for us to use the shared ring */ info->connected = BLKIF_STATE_CONNECTED; @@ -1079,7 +1078,7 @@ static int blkif_recover(struct blkfront_info *info) /* Kick any other new requests queued since we resumed */ kick_pending_request_queues(info); - spin_unlock_irq(&blkif_io_lock); + spin_unlock_irq(&info->io_lock); return 0; } @@ -1277,10 +1276,10 @@ static void blkfront_connect(struct blkfront_info *info) xenbus_switch_state(info->xbdev, XenbusStateConnected); /* Kick pending requests. */ - spin_lock_irq(&blkif_io_lock); + spin_lock_irq(&info->io_lock); info->connected = BLKIF_STATE_CONNECTED; kick_pending_request_queues(info); - spin_unlock_irq(&blkif_io_lock); + spin_unlock_irq(&info->io_lock); add_disk(info->gd); @@ -1410,7 +1409,6 @@ static int blkif_release(struct gendisk *disk, fmode_t mode) mutex_lock(&blkfront_mutex); bdev = bdget_disk(disk, 0); - bdput(bdev); if (bdev->bd_openers) goto out; @@ -1441,6 +1439,7 @@ static int blkif_release(struct gendisk *disk, fmode_t mode) } out: + bdput(bdev); mutex_unlock(&blkfront_mutex); return 0; } diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 48442476ec00..ae9edca7b56d 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -72,7 +72,9 @@ static struct usb_device_id ath3k_table[] = { /* Atheros AR3012 with sflash firmware*/ { USB_DEVICE(0x0CF3, 0x3004) }, + { USB_DEVICE(0x0CF3, 0x311D) }, { USB_DEVICE(0x13d3, 0x3375) }, + { USB_DEVICE(0x04CA, 0x3005) }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, @@ -89,7 +91,9 @@ static struct usb_device_id ath3k_blist_tbl[] = { /* Atheros AR3012 with sflash firmware*/ { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { } /* Terminating entry */ }; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 480cad920048..3311b812a0c6 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -61,7 +61,7 @@ static struct usb_device_id btusb_table[] = { { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, /* Broadcom SoftSailing reporting vendor specific */ - { USB_DEVICE(0x05ac, 0x21e1) }, + { USB_DEVICE(0x0a5c, 0x21e1) }, /* Apple MacBookPro 7,1 */ { USB_DEVICE(0x05ac, 0x8213) }, @@ -103,6 +103,7 @@ static struct usb_device_id btusb_table[] = { /* Broadcom BCM20702A0 */ { USB_DEVICE(0x0a5c, 0x21e3) }, { USB_DEVICE(0x0a5c, 0x21e6) }, + { USB_DEVICE(0x0a5c, 0x21e8) }, { USB_DEVICE(0x0a5c, 0x21f3) }, { USB_DEVICE(0x413c, 0x8197) }, @@ -129,7 +130,9 @@ static struct usb_device_id blacklist_table[] = { /* Atheros 3012 with sflash firmware */ { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index fd5adb408f44..98a8c05d4f23 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -299,11 +299,11 @@ static void hci_uart_tty_close(struct tty_struct *tty) hci_uart_close(hdev); if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { - hu->proto->close(hu); if (hdev) { hci_unregister_dev(hdev); hci_free_dev(hdev); } + hu->proto->close(hu); } kfree(hu); diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 3845ab44c330..dfd7876f127c 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -906,8 +906,8 @@ int hpet_alloc(struct hpet_data *hdp) hpetp->hp_which, hdp->hd_phys_address, hpetp->hp_ntimer > 1 ? "s" : ""); for (i = 0; i < hpetp->hp_ntimer; i++) - printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); - printk("\n"); + printk(KERN_CONT "%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); + printk(KERN_CONT "\n"); temp = hpetp->hp_tick_freq; remainder = do_div(temp, 1000000); diff --git a/drivers/char/random.c b/drivers/char/random.c index 54ca8b23cde3..4ec04a754733 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1260,10 +1260,15 @@ static int proc_do_uuid(ctl_table *table, int write, uuid = table->data; if (!uuid) { uuid = tmp_uuid; - uuid[8] = 0; - } - if (uuid[8] == 0) generate_random_uuid(uuid); + } else { + static DEFINE_SPINLOCK(bootid_spinlock); + + spin_lock(&bootid_spinlock); + if (!uuid[8]) + generate_random_uuid(uuid); + spin_unlock(&bootid_spinlock); + } sprintf(buf, "%pU", uuid); diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index 82e882028fcf..6b5cf02c35c8 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c @@ -23,7 +23,6 @@ #include <linux/init.h> #include <linux/pci.h> #include <linux/delay.h> -#include <linux/async.h> #include <asm/io.h> /* @@ -180,15 +179,17 @@ static int verify_pmtmr_rate(void) /* Number of reads we try to get two different values */ #define ACPI_PM_READ_CHECKS 10000 -static void __init acpi_pm_clocksource_async(void *unused, async_cookie_t cookie) +static int __init init_acpi_pm_clocksource(void) { cycle_t value1, value2; unsigned int i, j = 0; + if (!pmtmr_ioport) + return -ENODEV; /* "verify" this timing source: */ for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) { - usleep_range(100 * j, 100 * j + 100); + udelay(100 * j); value1 = clocksource_acpi_pm.read(&clocksource_acpi_pm); for (i = 0; i < ACPI_PM_READ_CHECKS; i++) { value2 = clocksource_acpi_pm.read(&clocksource_acpi_pm); @@ -202,34 +203,25 @@ static void __init acpi_pm_clocksource_async(void *unused, async_cookie_t cookie " 0x%#llx, 0x%#llx - aborting.\n", value1, value2); pmtmr_ioport = 0; - return; + return -EINVAL; } if (i == ACPI_PM_READ_CHECKS) { printk(KERN_INFO "PM-Timer failed consistency check " " (0x%#llx) - aborting.\n", value1); pmtmr_ioport = 0; - return; + return -ENODEV; } } if (verify_pmtmr_rate() != 0){ pmtmr_ioport = 0; - return; + return -ENODEV; } - clocksource_register_hz(&clocksource_acpi_pm, + return clocksource_register_hz(&clocksource_acpi_pm, PMTMR_TICKS_PER_SEC); } -static int __init init_acpi_pm_clocksource(void) -{ - if (!pmtmr_ioport) - return -ENODEV; - - async_schedule(acpi_pm_clocksource_async, NULL); - return 0; -} - /* We use fs_initcall because we want the PCI fixups to have run * but we still need to load before device_initcall */ diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index ffbb44685915..5961e6415f08 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -4,6 +4,7 @@ config ARM_OMAP2PLUS_CPUFREQ bool "TI OMAP2+" + depends on ARCH_OMAP2PLUS default ARCH_OMAP2PLUS select CPU_FREQ_TABLE diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 767bcc31b365..2397f6f451b1 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -332,6 +332,20 @@ struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type) } EXPORT_SYMBOL(dma_find_channel); +/* + * net_dma_find_channel - find a channel for net_dma + * net_dma has alignment requirements + */ +struct dma_chan *net_dma_find_channel(void) +{ + struct dma_chan *chan = dma_find_channel(DMA_MEMCPY); + if (chan && !is_dma_copy_aligned(chan->device, 1, 1, 1)) + return NULL; + + return chan; +} +EXPORT_SYMBOL(net_dma_find_channel); + /** * dma_issue_pending_all - flush all pending operations across all channels */ diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 31493d80e0e9..73b2b65cb1de 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -546,9 +546,9 @@ void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags, PCI_DMA_TODEVICE, flags, 0); } -unsigned long ioat_get_current_completion(struct ioat_chan_common *chan) +dma_addr_t ioat_get_current_completion(struct ioat_chan_common *chan) { - unsigned long phys_complete; + dma_addr_t phys_complete; u64 completion; completion = *chan->completion; @@ -569,7 +569,7 @@ unsigned long ioat_get_current_completion(struct ioat_chan_common *chan) } bool ioat_cleanup_preamble(struct ioat_chan_common *chan, - unsigned long *phys_complete) + dma_addr_t *phys_complete) { *phys_complete = ioat_get_current_completion(chan); if (*phys_complete == chan->last_completion) @@ -580,14 +580,14 @@ bool ioat_cleanup_preamble(struct ioat_chan_common *chan, return true; } -static void __cleanup(struct ioat_dma_chan *ioat, unsigned long phys_complete) +static void __cleanup(struct ioat_dma_chan *ioat, dma_addr_t phys_complete) { struct ioat_chan_common *chan = &ioat->base; struct list_head *_desc, *n; struct dma_async_tx_descriptor *tx; - dev_dbg(to_dev(chan), "%s: phys_complete: %lx\n", - __func__, phys_complete); + dev_dbg(to_dev(chan), "%s: phys_complete: %llx\n", + __func__, (unsigned long long) phys_complete); list_for_each_safe(_desc, n, &ioat->used_desc) { struct ioat_desc_sw *desc; @@ -652,7 +652,7 @@ static void __cleanup(struct ioat_dma_chan *ioat, unsigned long phys_complete) static void ioat1_cleanup(struct ioat_dma_chan *ioat) { struct ioat_chan_common *chan = &ioat->base; - unsigned long phys_complete; + dma_addr_t phys_complete; prefetch(chan->completion); @@ -698,7 +698,7 @@ static void ioat1_timer_event(unsigned long data) mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT); spin_unlock_bh(&ioat->desc_lock); } else if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) { - unsigned long phys_complete; + dma_addr_t phys_complete; spin_lock_bh(&ioat->desc_lock); /* if we haven't made progress and we have already diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index c7888bccd974..5e8fe01ba69d 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -88,7 +88,7 @@ struct ioatdma_device { struct ioat_chan_common { struct dma_chan common; void __iomem *reg_base; - unsigned long last_completion; + dma_addr_t last_completion; spinlock_t cleanup_lock; unsigned long state; #define IOAT_COMPLETION_PENDING 0 @@ -310,7 +310,7 @@ int __devinit ioat_dma_self_test(struct ioatdma_device *device); void __devexit ioat_dma_remove(struct ioatdma_device *device); struct dca_provider * __devinit ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase); -unsigned long ioat_get_current_completion(struct ioat_chan_common *chan); +dma_addr_t ioat_get_current_completion(struct ioat_chan_common *chan); void ioat_init_channel(struct ioatdma_device *device, struct ioat_chan_common *chan, int idx); enum dma_status ioat_dma_tx_status(struct dma_chan *c, dma_cookie_t cookie, @@ -318,7 +318,7 @@ enum dma_status ioat_dma_tx_status(struct dma_chan *c, dma_cookie_t cookie, void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags, size_t len, struct ioat_dma_descriptor *hw); bool ioat_cleanup_preamble(struct ioat_chan_common *chan, - unsigned long *phys_complete); + dma_addr_t *phys_complete); void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type); void ioat_kobject_del(struct ioatdma_device *device); extern const struct sysfs_ops ioat_sysfs_ops; diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index e8e110ff3d96..86895760b598 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c @@ -128,7 +128,7 @@ static void ioat2_start_null_desc(struct ioat2_dma_chan *ioat) spin_unlock_bh(&ioat->prep_lock); } -static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete) +static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete) { struct ioat_chan_common *chan = &ioat->base; struct dma_async_tx_descriptor *tx; @@ -179,7 +179,7 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete) static void ioat2_cleanup(struct ioat2_dma_chan *ioat) { struct ioat_chan_common *chan = &ioat->base; - unsigned long phys_complete; + dma_addr_t phys_complete; spin_lock_bh(&chan->cleanup_lock); if (ioat_cleanup_preamble(chan, &phys_complete)) @@ -260,7 +260,7 @@ int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo) static void ioat2_restart_channel(struct ioat2_dma_chan *ioat) { struct ioat_chan_common *chan = &ioat->base; - unsigned long phys_complete; + dma_addr_t phys_complete; ioat2_quiesce(chan, 0); if (ioat_cleanup_preamble(chan, &phys_complete)) @@ -275,7 +275,7 @@ void ioat2_timer_event(unsigned long data) struct ioat_chan_common *chan = &ioat->base; if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) { - unsigned long phys_complete; + dma_addr_t phys_complete; u64 status; status = ioat_chansts(chan); @@ -572,9 +572,9 @@ bool reshape_ring(struct ioat2_dma_chan *ioat, int order) */ struct ioat_chan_common *chan = &ioat->base; struct dma_chan *c = &chan->common; - const u16 curr_size = ioat2_ring_size(ioat); + const u32 curr_size = ioat2_ring_size(ioat); const u16 active = ioat2_ring_active(ioat); - const u16 new_size = 1 << order; + const u32 new_size = 1 << order; struct ioat_ring_ent **ring; u16 i; diff --git a/drivers/dma/ioat/dma_v2.h b/drivers/dma/ioat/dma_v2.h index a2c413b2b8d8..be2a55b95c23 100644 --- a/drivers/dma/ioat/dma_v2.h +++ b/drivers/dma/ioat/dma_v2.h @@ -74,7 +74,7 @@ static inline struct ioat2_dma_chan *to_ioat2_chan(struct dma_chan *c) return container_of(chan, struct ioat2_dma_chan, base); } -static inline u16 ioat2_ring_size(struct ioat2_dma_chan *ioat) +static inline u32 ioat2_ring_size(struct ioat2_dma_chan *ioat) { return 1 << ioat->alloc_order; } @@ -91,7 +91,7 @@ static inline u16 ioat2_ring_pending(struct ioat2_dma_chan *ioat) return CIRC_CNT(ioat->head, ioat->issued, ioat2_ring_size(ioat)); } -static inline u16 ioat2_ring_space(struct ioat2_dma_chan *ioat) +static inline u32 ioat2_ring_space(struct ioat2_dma_chan *ioat) { return ioat2_ring_size(ioat) - ioat2_ring_active(ioat); } diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index 2c4476c0e405..f7f1dc62c15c 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -257,7 +257,7 @@ static bool desc_has_ext(struct ioat_ring_ent *desc) * The difference from the dma_v2.c __cleanup() is that this routine * handles extended descriptors and dma-unmapping raid operations. */ -static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete) +static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete) { struct ioat_chan_common *chan = &ioat->base; struct ioat_ring_ent *desc; @@ -314,7 +314,7 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete) static void ioat3_cleanup(struct ioat2_dma_chan *ioat) { struct ioat_chan_common *chan = &ioat->base; - unsigned long phys_complete; + dma_addr_t phys_complete; spin_lock_bh(&chan->cleanup_lock); if (ioat_cleanup_preamble(chan, &phys_complete)) @@ -333,7 +333,7 @@ static void ioat3_cleanup_event(unsigned long data) static void ioat3_restart_channel(struct ioat2_dma_chan *ioat) { struct ioat_chan_common *chan = &ioat->base; - unsigned long phys_complete; + dma_addr_t phys_complete; ioat2_quiesce(chan, 0); if (ioat_cleanup_preamble(chan, &phys_complete)) @@ -348,7 +348,7 @@ static void ioat3_timer_event(unsigned long data) struct ioat_chan_common *chan = &ioat->base; if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) { - unsigned long phys_complete; + dma_addr_t phys_complete; u64 status; status = ioat_chansts(chan); @@ -1149,6 +1149,44 @@ static int ioat3_reset_hw(struct ioat_chan_common *chan) return ioat2_reset_sync(chan, msecs_to_jiffies(200)); } +static bool is_jf_ioat(struct pci_dev *pdev) +{ + switch (pdev->device) { + case PCI_DEVICE_ID_INTEL_IOAT_JSF0: + case PCI_DEVICE_ID_INTEL_IOAT_JSF1: + case PCI_DEVICE_ID_INTEL_IOAT_JSF2: + case PCI_DEVICE_ID_INTEL_IOAT_JSF3: + case PCI_DEVICE_ID_INTEL_IOAT_JSF4: + case PCI_DEVICE_ID_INTEL_IOAT_JSF5: + case PCI_DEVICE_ID_INTEL_IOAT_JSF6: + case PCI_DEVICE_ID_INTEL_IOAT_JSF7: + case PCI_DEVICE_ID_INTEL_IOAT_JSF8: + case PCI_DEVICE_ID_INTEL_IOAT_JSF9: + return true; + default: + return false; + } +} + +static bool is_snb_ioat(struct pci_dev *pdev) +{ + switch (pdev->device) { + case PCI_DEVICE_ID_INTEL_IOAT_SNB0: + case PCI_DEVICE_ID_INTEL_IOAT_SNB1: + case PCI_DEVICE_ID_INTEL_IOAT_SNB2: + case PCI_DEVICE_ID_INTEL_IOAT_SNB3: + case PCI_DEVICE_ID_INTEL_IOAT_SNB4: + case PCI_DEVICE_ID_INTEL_IOAT_SNB5: + case PCI_DEVICE_ID_INTEL_IOAT_SNB6: + case PCI_DEVICE_ID_INTEL_IOAT_SNB7: + case PCI_DEVICE_ID_INTEL_IOAT_SNB8: + case PCI_DEVICE_ID_INTEL_IOAT_SNB9: + return true; + default: + return false; + } +} + int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) { struct pci_dev *pdev = device->pdev; @@ -1169,6 +1207,9 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) dma->device_alloc_chan_resources = ioat2_alloc_chan_resources; dma->device_free_chan_resources = ioat2_free_chan_resources; + if (is_jf_ioat(pdev) || is_snb_ioat(pdev)) + dma->copy_align = 6; + dma_cap_set(DMA_INTERRUPT, dma->cap_mask); dma->device_prep_dma_interrupt = ioat3_prep_interrupt_lock; diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index da6c4c2c066a..79e3eba29702 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c @@ -1252,8 +1252,8 @@ iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device) struct page **pq_hw = &pq[IOP_ADMA_NUM_SRC_TEST+2]; /* address conversion buffers (dma_map / page_address) */ void *pq_sw[IOP_ADMA_NUM_SRC_TEST+2]; - dma_addr_t pq_src[IOP_ADMA_NUM_SRC_TEST]; - dma_addr_t pq_dest[2]; + dma_addr_t pq_src[IOP_ADMA_NUM_SRC_TEST+2]; + dma_addr_t *pq_dest = &pq_src[IOP_ADMA_NUM_SRC_TEST]; int i; struct dma_async_tx_descriptor *tx; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index edadbdad31d0..e03653d69357 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -430,7 +430,7 @@ config GPIO_ML_IOH config GPIO_SODAVILLE bool "Intel Sodaville GPIO support" - depends on X86 && PCI && OF && BROKEN + depends on X86 && PCI && OF select GPIO_GENERIC select GENERIC_IRQ_CHIP help diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c index 9ad1703d1408..ae5d7f12ce66 100644 --- a/drivers/gpio/gpio-adp5588.c +++ b/drivers/gpio/gpio-adp5588.c @@ -252,7 +252,7 @@ static irqreturn_t adp5588_irq_handler(int irq, void *devid) if (ret < 0) memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat)); - for (bank = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO); + for (bank = 0, bit = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO); bank++, bit = 0) { pending = dev->irq_stat[bank] & dev->irq_mask[bank]; diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 46277877b7ec..19d6fc0229c3 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -2382,8 +2382,8 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = { #endif }; -static struct samsung_gpio_chip exynos5_gpios_1[] = { #ifdef CONFIG_ARCH_EXYNOS5 +static struct samsung_gpio_chip exynos5_gpios_1[] = { { .chip = { .base = EXYNOS5_GPA0(0), @@ -2541,11 +2541,11 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = { .to_irq = samsung_gpiolib_to_irq, }, }, -#endif }; +#endif -static struct samsung_gpio_chip exynos5_gpios_2[] = { #ifdef CONFIG_ARCH_EXYNOS5 +static struct samsung_gpio_chip exynos5_gpios_2[] = { { .chip = { .base = EXYNOS5_GPE0(0), @@ -2602,11 +2602,11 @@ static struct samsung_gpio_chip exynos5_gpios_2[] = { }, }, -#endif }; +#endif -static struct samsung_gpio_chip exynos5_gpios_3[] = { #ifdef CONFIG_ARCH_EXYNOS5 +static struct samsung_gpio_chip exynos5_gpios_3[] = { { .chip = { .base = EXYNOS5_GPV0(0), @@ -2638,11 +2638,11 @@ static struct samsung_gpio_chip exynos5_gpios_3[] = { .label = "GPV4", }, }, -#endif }; +#endif -static struct samsung_gpio_chip exynos5_gpios_4[] = { #ifdef CONFIG_ARCH_EXYNOS5 +static struct samsung_gpio_chip exynos5_gpios_4[] = { { .chip = { .base = EXYNOS5_GPZ(0), @@ -2650,8 +2650,8 @@ static struct samsung_gpio_chip exynos5_gpios_4[] = { .label = "GPZ", }, }, -#endif }; +#endif #if defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF) diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c index 9ba15d31d242..031e5d24837d 100644 --- a/drivers/gpio/gpio-sodaville.c +++ b/drivers/gpio/gpio-sodaville.c @@ -41,7 +41,7 @@ struct sdv_gpio_chip_data { int irq_base; void __iomem *gpio_pub_base; - struct irq_domain id; + struct irq_domain *id; struct irq_chip_generic *gc; struct bgpio_chip bgpio; }; @@ -51,10 +51,9 @@ static int sdv_gpio_pub_set_type(struct irq_data *d, unsigned int type) struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct sdv_gpio_chip_data *sd = gc->private; void __iomem *type_reg; - u32 irq_offs = d->irq - sd->irq_base; u32 reg; - if (irq_offs < 8) + if (d->hwirq < 8) type_reg = sd->gpio_pub_base + GPIT1R0; else type_reg = sd->gpio_pub_base + GPIT1R1; @@ -63,11 +62,11 @@ static int sdv_gpio_pub_set_type(struct irq_data *d, unsigned int type) switch (type) { case IRQ_TYPE_LEVEL_HIGH: - reg &= ~BIT(4 * (irq_offs % 8)); + reg &= ~BIT(4 * (d->hwirq % 8)); break; case IRQ_TYPE_LEVEL_LOW: - reg |= BIT(4 * (irq_offs % 8)); + reg |= BIT(4 * (d->hwirq % 8)); break; default: @@ -91,7 +90,7 @@ static irqreturn_t sdv_gpio_pub_irq_handler(int irq, void *data) u32 irq_bit = __fls(irq_stat); irq_stat &= ~BIT(irq_bit); - generic_handle_irq(sd->irq_base + irq_bit); + generic_handle_irq(irq_find_mapping(sd->id, irq_bit)); } return IRQ_HANDLED; @@ -127,7 +126,7 @@ static int sdv_xlate(struct irq_domain *h, struct device_node *node, } static struct irq_domain_ops irq_domain_sdv_ops = { - .dt_translate = sdv_xlate, + .xlate = sdv_xlate, }; static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, @@ -149,10 +148,6 @@ static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, if (ret) goto out_free_desc; - sd->id.irq_base = sd->irq_base; - sd->id.of_node = of_node_get(pdev->dev.of_node); - sd->id.ops = &irq_domain_sdv_ops; - /* * This gpio irq controller latches level irqs. Testing shows that if * we unmask & ACK the IRQ before the source of the interrupt is gone @@ -179,7 +174,10 @@ static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); - irq_domain_add(&sd->id); + sd->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS, + sd->irq_base, 0, &irq_domain_sdv_ops, sd); + if (!sd->id) + goto out_free_irq; return 0; out_free_irq: free_irq(pdev->irq, sd); @@ -260,7 +258,6 @@ static void sdv_gpio_remove(struct pci_dev *pdev) { struct sdv_gpio_chip_data *sd = pci_get_drvdata(pdev); - irq_domain_del(&sd->id); free_irq(pdev->irq, sd); irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS); diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c index 4a3a5f72ed4a..de8d2090bce3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c @@ -34,14 +34,14 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, unsigned int flags, struct exynos_drm_gem_buf *buf) { - dma_addr_t start_addr, end_addr; + dma_addr_t start_addr; unsigned int npages, page_size, i = 0; struct scatterlist *sgl; int ret = 0; DRM_DEBUG_KMS("%s\n", __FILE__); - if (flags & EXYNOS_BO_NONCONTIG) { + if (IS_NONCONTIG_BUFFER(flags)) { DRM_DEBUG_KMS("not support allocation type.\n"); return -EINVAL; } @@ -52,13 +52,13 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, } if (buf->size >= SZ_1M) { - npages = (buf->size >> SECTION_SHIFT) + 1; + npages = buf->size >> SECTION_SHIFT; page_size = SECTION_SIZE; } else if (buf->size >= SZ_64K) { - npages = (buf->size >> 16) + 1; + npages = buf->size >> 16; page_size = SZ_64K; } else { - npages = (buf->size >> PAGE_SHIFT) + 1; + npages = buf->size >> PAGE_SHIFT; page_size = PAGE_SIZE; } @@ -76,26 +76,13 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, return -ENOMEM; } - buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size, - &buf->dma_addr, GFP_KERNEL); - if (!buf->kvaddr) { - DRM_ERROR("failed to allocate buffer.\n"); - ret = -ENOMEM; - goto err1; - } - - start_addr = buf->dma_addr; - end_addr = buf->dma_addr + buf->size; - - buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL); - if (!buf->pages) { - DRM_ERROR("failed to allocate pages.\n"); - ret = -ENOMEM; - goto err2; - } - - start_addr = buf->dma_addr; - end_addr = buf->dma_addr + buf->size; + buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size, + &buf->dma_addr, GFP_KERNEL); + if (!buf->kvaddr) { + DRM_ERROR("failed to allocate buffer.\n"); + ret = -ENOMEM; + goto err1; + } buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL); if (!buf->pages) { @@ -105,23 +92,17 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, } sgl = buf->sgt->sgl; + start_addr = buf->dma_addr; while (i < npages) { buf->pages[i] = phys_to_page(start_addr); sg_set_page(sgl, buf->pages[i], page_size, 0); sg_dma_address(sgl) = start_addr; start_addr += page_size; - if (end_addr - start_addr < page_size) - break; sgl = sg_next(sgl); i++; } - buf->pages[i] = phys_to_page(start_addr); - - sgl = sg_next(sgl); - sg_set_page(sgl, buf->pages[i+1], end_addr - start_addr, 0); - DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", (unsigned long)buf->kvaddr, (unsigned long)buf->dma_addr, @@ -150,7 +131,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev, * non-continuous memory would be released by exynos * gem framework. */ - if (flags & EXYNOS_BO_NONCONTIG) { + if (IS_NONCONTIG_BUFFER(flags)) { DRM_DEBUG_KMS("not support allocation type.\n"); return; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c index 411832e8e17a..eaf630dc5dba 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_core.c +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c @@ -54,16 +54,18 @@ static int exynos_drm_subdrv_probe(struct drm_device *dev, * * P.S. note that this driver is considered for modularization. */ - ret = subdrv->probe(dev, subdrv->manager.dev); + ret = subdrv->probe(dev, subdrv->dev); if (ret) return ret; } - if (subdrv->is_local) + if (!subdrv->manager) return 0; + subdrv->manager->dev = subdrv->dev; + /* create and initialize a encoder for this sub driver. */ - encoder = exynos_drm_encoder_create(dev, &subdrv->manager, + encoder = exynos_drm_encoder_create(dev, subdrv->manager, (1 << MAX_CRTC) - 1); if (!encoder) { DRM_ERROR("failed to create encoder\n"); @@ -186,7 +188,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file) list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) { if (subdrv->open) { - ret = subdrv->open(dev, subdrv->manager.dev, file); + ret = subdrv->open(dev, subdrv->dev, file); if (ret) goto err; } @@ -197,7 +199,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file) err: list_for_each_entry_reverse(subdrv, &subdrv->list, list) { if (subdrv->close) - subdrv->close(dev, subdrv->manager.dev, file); + subdrv->close(dev, subdrv->dev, file); } return ret; } @@ -209,7 +211,7 @@ void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file) list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) { if (subdrv->close) - subdrv->close(dev, subdrv->manager.dev, file); + subdrv->close(dev, subdrv->dev, file); } } EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index fbd0a232c93d..1d814175cd49 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -225,24 +225,25 @@ struct exynos_drm_private { * Exynos drm sub driver structure. * * @list: sub driver has its own list object to register to exynos drm driver. + * @dev: pointer to device object for subdrv device driver. * @drm_dev: pointer to drm_device and this pointer would be set * when sub driver calls exynos_drm_subdrv_register(). - * @is_local: appear encoder and connector disrelated device. + * @manager: subdrv has its own manager to control a hardware appropriately + * and we can access a hardware drawing on this manager. * @probe: this callback would be called by exynos drm driver after * subdrv is registered to it. * @remove: this callback is used to release resources created * by probe callback. * @open: this would be called with drm device file open. * @close: this would be called with drm device file close. - * @manager: subdrv has its own manager to control a hardware appropriately - * and we can access a hardware drawing on this manager. * @encoder: encoder object owned by this sub driver. * @connector: connector object owned by this sub driver. */ struct exynos_drm_subdrv { struct list_head list; + struct device *dev; struct drm_device *drm_dev; - bool is_local; + struct exynos_drm_manager *manager; int (*probe)(struct drm_device *drm_dev, struct device *dev); void (*remove)(struct drm_device *dev); @@ -251,7 +252,6 @@ struct exynos_drm_subdrv { void (*close)(struct drm_device *drm_dev, struct device *dev, struct drm_file *file); - struct exynos_drm_manager manager; struct drm_encoder *encoder; struct drm_connector *connector; }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index ecb6db229700..29fdbfeb43cb 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -172,7 +172,7 @@ static void fimd_dpms(struct device *subdrv_dev, int mode) static void fimd_apply(struct device *subdrv_dev) { struct fimd_context *ctx = get_fimd_context(subdrv_dev); - struct exynos_drm_manager *mgr = &ctx->subdrv.manager; + struct exynos_drm_manager *mgr = ctx->subdrv.manager; struct exynos_drm_manager_ops *mgr_ops = mgr->ops; struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops; struct fimd_win_data *win_data; @@ -577,6 +577,13 @@ static struct exynos_drm_overlay_ops fimd_overlay_ops = { .disable = fimd_win_disable, }; +static struct exynos_drm_manager fimd_manager = { + .pipe = -1, + .ops = &fimd_manager_ops, + .overlay_ops = &fimd_overlay_ops, + .display_ops = &fimd_display_ops, +}; + static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc) { struct exynos_drm_private *dev_priv = drm_dev->dev_private; @@ -628,7 +635,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id) struct fimd_context *ctx = (struct fimd_context *)dev_id; struct exynos_drm_subdrv *subdrv = &ctx->subdrv; struct drm_device *drm_dev = subdrv->drm_dev; - struct exynos_drm_manager *manager = &subdrv->manager; + struct exynos_drm_manager *manager = subdrv->manager; u32 val; val = readl(ctx->regs + VIDINTCON1); @@ -744,7 +751,7 @@ static void fimd_clear_win(struct fimd_context *ctx, int win) static int fimd_power_on(struct fimd_context *ctx, bool enable) { struct exynos_drm_subdrv *subdrv = &ctx->subdrv; - struct device *dev = subdrv->manager.dev; + struct device *dev = subdrv->dev; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -867,13 +874,10 @@ static int __devinit fimd_probe(struct platform_device *pdev) subdrv = &ctx->subdrv; + subdrv->dev = dev; + subdrv->manager = &fimd_manager; subdrv->probe = fimd_subdrv_probe; subdrv->remove = fimd_subdrv_remove; - subdrv->manager.pipe = -1; - subdrv->manager.ops = &fimd_manager_ops; - subdrv->manager.overlay_ops = &fimd_overlay_ops; - subdrv->manager.display_ops = &fimd_display_ops; - subdrv->manager.dev = dev; mutex_init(&ctx->lock); diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index fa1aa94a3d8e..26d51979116b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -56,9 +56,28 @@ static unsigned int convert_to_vm_err_msg(int msg) return out_msg; } -static unsigned int mask_gem_flags(unsigned int flags) +static int check_gem_flags(unsigned int flags) { - return flags &= EXYNOS_BO_NONCONTIG; + if (flags & ~(EXYNOS_BO_MASK)) { + DRM_ERROR("invalid flags.\n"); + return -EINVAL; + } + + return 0; +} + +static unsigned long roundup_gem_size(unsigned long size, unsigned int flags) +{ + if (!IS_NONCONTIG_BUFFER(flags)) { + if (size >= SZ_1M) + return roundup(size, SECTION_SIZE); + else if (size >= SZ_64K) + return roundup(size, SZ_64K); + else + goto out; + } +out: + return roundup(size, PAGE_SIZE); } static struct page **exynos_gem_get_pages(struct drm_gem_object *obj, @@ -319,10 +338,17 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, struct exynos_drm_gem_buf *buf; int ret; - size = roundup(size, PAGE_SIZE); - DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size); + if (!size) { + DRM_ERROR("invalid size.\n"); + return ERR_PTR(-EINVAL); + } - flags = mask_gem_flags(flags); + size = roundup_gem_size(size, flags); + DRM_DEBUG_KMS("%s\n", __FILE__); + + ret = check_gem_flags(flags); + if (ret) + return ERR_PTR(ret); buf = exynos_drm_init_buf(dev, size); if (!buf) @@ -331,7 +357,7 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, exynos_gem_obj = exynos_drm_gem_init(dev, size); if (!exynos_gem_obj) { ret = -ENOMEM; - goto err; + goto err_fini_buf; } exynos_gem_obj->buffer = buf; @@ -347,18 +373,19 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base); if (ret < 0) { drm_gem_object_release(&exynos_gem_obj->base); - goto err; + goto err_fini_buf; } } else { ret = exynos_drm_alloc_buf(dev, buf, flags); if (ret < 0) { drm_gem_object_release(&exynos_gem_obj->base); - goto err; + goto err_fini_buf; } } return exynos_gem_obj; -err: + +err_fini_buf: exynos_drm_fini_buf(dev, buf); return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index e40fbad8b705..4ed842039505 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h @@ -29,6 +29,8 @@ #define to_exynos_gem_obj(x) container_of(x,\ struct exynos_drm_gem_obj, base) +#define IS_NONCONTIG_BUFFER(f) (f & EXYNOS_BO_NONCONTIG) + /* * exynos drm gem buffer structure. * diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 14eb26b0ba1c..3424463676e0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -30,9 +30,8 @@ struct drm_hdmi_context, subdrv); /* these callback points shoud be set by specific drivers. */ -static struct exynos_hdmi_display_ops *hdmi_display_ops; -static struct exynos_hdmi_manager_ops *hdmi_manager_ops; -static struct exynos_hdmi_overlay_ops *hdmi_overlay_ops; +static struct exynos_hdmi_ops *hdmi_ops; +static struct exynos_mixer_ops *mixer_ops; struct drm_hdmi_context { struct exynos_drm_subdrv subdrv; @@ -40,31 +39,20 @@ struct drm_hdmi_context { struct exynos_drm_hdmi_context *mixer_ctx; }; -void exynos_drm_display_ops_register(struct exynos_hdmi_display_ops - *display_ops) +void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops) { DRM_DEBUG_KMS("%s\n", __FILE__); - if (display_ops) - hdmi_display_ops = display_ops; + if (ops) + hdmi_ops = ops; } -void exynos_drm_manager_ops_register(struct exynos_hdmi_manager_ops - *manager_ops) +void exynos_mixer_ops_register(struct exynos_mixer_ops *ops) { DRM_DEBUG_KMS("%s\n", __FILE__); - if (manager_ops) - hdmi_manager_ops = manager_ops; -} - -void exynos_drm_overlay_ops_register(struct exynos_hdmi_overlay_ops - *overlay_ops) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (overlay_ops) - hdmi_overlay_ops = overlay_ops; + if (ops) + mixer_ops = ops; } static bool drm_hdmi_is_connected(struct device *dev) @@ -73,8 +61,8 @@ static bool drm_hdmi_is_connected(struct device *dev) DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_display_ops && hdmi_display_ops->is_connected) - return hdmi_display_ops->is_connected(ctx->hdmi_ctx->ctx); + if (hdmi_ops && hdmi_ops->is_connected) + return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx); return false; } @@ -86,9 +74,9 @@ static int drm_hdmi_get_edid(struct device *dev, DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_display_ops && hdmi_display_ops->get_edid) - return hdmi_display_ops->get_edid(ctx->hdmi_ctx->ctx, - connector, edid, len); + if (hdmi_ops && hdmi_ops->get_edid) + return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid, + len); return 0; } @@ -99,9 +87,8 @@ static int drm_hdmi_check_timing(struct device *dev, void *timing) DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_display_ops && hdmi_display_ops->check_timing) - return hdmi_display_ops->check_timing(ctx->hdmi_ctx->ctx, - timing); + if (hdmi_ops && hdmi_ops->check_timing) + return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing); return 0; } @@ -112,8 +99,8 @@ static int drm_hdmi_power_on(struct device *dev, int mode) DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_display_ops && hdmi_display_ops->power_on) - return hdmi_display_ops->power_on(ctx->hdmi_ctx->ctx, mode); + if (hdmi_ops && hdmi_ops->power_on) + return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode); return 0; } @@ -130,13 +117,13 @@ static int drm_hdmi_enable_vblank(struct device *subdrv_dev) { struct drm_hdmi_context *ctx = to_context(subdrv_dev); struct exynos_drm_subdrv *subdrv = &ctx->subdrv; - struct exynos_drm_manager *manager = &subdrv->manager; + struct exynos_drm_manager *manager = subdrv->manager; DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_overlay_ops && hdmi_overlay_ops->enable_vblank) - return hdmi_overlay_ops->enable_vblank(ctx->mixer_ctx->ctx, - manager->pipe); + if (mixer_ops && mixer_ops->enable_vblank) + return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx, + manager->pipe); return 0; } @@ -147,8 +134,8 @@ static void drm_hdmi_disable_vblank(struct device *subdrv_dev) DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_overlay_ops && hdmi_overlay_ops->disable_vblank) - return hdmi_overlay_ops->disable_vblank(ctx->mixer_ctx->ctx); + if (mixer_ops && mixer_ops->disable_vblank) + return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx); } static void drm_hdmi_mode_fixup(struct device *subdrv_dev, @@ -160,9 +147,9 @@ static void drm_hdmi_mode_fixup(struct device *subdrv_dev, DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_manager_ops && hdmi_manager_ops->mode_fixup) - hdmi_manager_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector, - mode, adjusted_mode); + if (hdmi_ops && hdmi_ops->mode_fixup) + hdmi_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector, mode, + adjusted_mode); } static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode) @@ -171,8 +158,8 @@ static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode) DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_manager_ops && hdmi_manager_ops->mode_set) - hdmi_manager_ops->mode_set(ctx->hdmi_ctx->ctx, mode); + if (hdmi_ops && hdmi_ops->mode_set) + hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode); } static void drm_hdmi_get_max_resol(struct device *subdrv_dev, @@ -182,9 +169,8 @@ static void drm_hdmi_get_max_resol(struct device *subdrv_dev, DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_manager_ops && hdmi_manager_ops->get_max_resol) - hdmi_manager_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, - height); + if (hdmi_ops && hdmi_ops->get_max_resol) + hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height); } static void drm_hdmi_commit(struct device *subdrv_dev) @@ -193,8 +179,8 @@ static void drm_hdmi_commit(struct device *subdrv_dev) DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_manager_ops && hdmi_manager_ops->commit) - hdmi_manager_ops->commit(ctx->hdmi_ctx->ctx); + if (hdmi_ops && hdmi_ops->commit) + hdmi_ops->commit(ctx->hdmi_ctx->ctx); } static void drm_hdmi_dpms(struct device *subdrv_dev, int mode) @@ -209,8 +195,8 @@ static void drm_hdmi_dpms(struct device *subdrv_dev, int mode) case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - if (hdmi_manager_ops && hdmi_manager_ops->disable) - hdmi_manager_ops->disable(ctx->hdmi_ctx->ctx); + if (hdmi_ops && hdmi_ops->disable) + hdmi_ops->disable(ctx->hdmi_ctx->ctx); break; default: DRM_DEBUG_KMS("unkown dps mode: %d\n", mode); @@ -235,8 +221,8 @@ static void drm_mixer_mode_set(struct device *subdrv_dev, DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_overlay_ops && hdmi_overlay_ops->win_mode_set) - hdmi_overlay_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay); + if (mixer_ops && mixer_ops->win_mode_set) + mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay); } static void drm_mixer_commit(struct device *subdrv_dev, int zpos) @@ -245,8 +231,8 @@ static void drm_mixer_commit(struct device *subdrv_dev, int zpos) DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_overlay_ops && hdmi_overlay_ops->win_commit) - hdmi_overlay_ops->win_commit(ctx->mixer_ctx->ctx, zpos); + if (mixer_ops && mixer_ops->win_commit) + mixer_ops->win_commit(ctx->mixer_ctx->ctx, zpos); } static void drm_mixer_disable(struct device *subdrv_dev, int zpos) @@ -255,8 +241,8 @@ static void drm_mixer_disable(struct device *subdrv_dev, int zpos) DRM_DEBUG_KMS("%s\n", __FILE__); - if (hdmi_overlay_ops && hdmi_overlay_ops->win_disable) - hdmi_overlay_ops->win_disable(ctx->mixer_ctx->ctx, zpos); + if (mixer_ops && mixer_ops->win_disable) + mixer_ops->win_disable(ctx->mixer_ctx->ctx, zpos); } static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = { @@ -265,6 +251,12 @@ static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = { .disable = drm_mixer_disable, }; +static struct exynos_drm_manager hdmi_manager = { + .pipe = -1, + .ops = &drm_hdmi_manager_ops, + .overlay_ops = &drm_hdmi_overlay_ops, + .display_ops = &drm_hdmi_display_ops, +}; static int hdmi_subdrv_probe(struct drm_device *drm_dev, struct device *dev) @@ -332,12 +324,9 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev) subdrv = &ctx->subdrv; + subdrv->dev = dev; + subdrv->manager = &hdmi_manager; subdrv->probe = hdmi_subdrv_probe; - subdrv->manager.pipe = -1; - subdrv->manager.ops = &drm_hdmi_manager_ops; - subdrv->manager.overlay_ops = &drm_hdmi_overlay_ops; - subdrv->manager.display_ops = &drm_hdmi_display_ops; - subdrv->manager.dev = dev; platform_set_drvdata(pdev, subdrv); diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index 44497cfb6c74..f3ae192c8dcf 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h @@ -38,15 +38,15 @@ struct exynos_drm_hdmi_context { void *ctx; }; -struct exynos_hdmi_display_ops { +struct exynos_hdmi_ops { + /* display */ bool (*is_connected)(void *ctx); int (*get_edid)(void *ctx, struct drm_connector *connector, u8 *edid, int len); int (*check_timing)(void *ctx, void *timing); int (*power_on)(void *ctx, int mode); -}; -struct exynos_hdmi_manager_ops { + /* manager */ void (*mode_fixup)(void *ctx, struct drm_connector *connector, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); @@ -57,22 +57,17 @@ struct exynos_hdmi_manager_ops { void (*disable)(void *ctx); }; -struct exynos_hdmi_overlay_ops { +struct exynos_mixer_ops { + /* manager */ int (*enable_vblank)(void *ctx, int pipe); void (*disable_vblank)(void *ctx); + + /* overlay */ void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay); void (*win_commit)(void *ctx, int zpos); void (*win_disable)(void *ctx, int zpos); }; -extern struct platform_driver hdmi_driver; -extern struct platform_driver mixer_driver; - -void exynos_drm_display_ops_register(struct exynos_hdmi_display_ops - *display_ops); -void exynos_drm_manager_ops_register(struct exynos_hdmi_manager_ops - *manager_ops); -void exynos_drm_overlay_ops_register(struct exynos_hdmi_overlay_ops - *overlay_ops); - +void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops); +void exynos_mixer_ops_register(struct exynos_mixer_ops *ops); #endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index c277a3a445f5..f92fe4c6174a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -24,6 +24,10 @@ struct exynos_plane { static const uint32_t formats[] = { DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_NV12, + DRM_FORMAT_NV12M, + DRM_FORMAT_NV12MT, }; static int diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 8e1339f9fe1f..7b9c153dceb6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -199,7 +199,7 @@ static void vidi_dpms(struct device *subdrv_dev, int mode) static void vidi_apply(struct device *subdrv_dev) { struct vidi_context *ctx = get_vidi_context(subdrv_dev); - struct exynos_drm_manager *mgr = &ctx->subdrv.manager; + struct exynos_drm_manager *mgr = ctx->subdrv.manager; struct exynos_drm_manager_ops *mgr_ops = mgr->ops; struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops; struct vidi_win_data *win_data; @@ -374,6 +374,13 @@ static struct exynos_drm_overlay_ops vidi_overlay_ops = { .disable = vidi_win_disable, }; +static struct exynos_drm_manager vidi_manager = { + .pipe = -1, + .ops = &vidi_manager_ops, + .overlay_ops = &vidi_overlay_ops, + .display_ops = &vidi_display_ops, +}; + static void vidi_finish_pageflip(struct drm_device *drm_dev, int crtc) { struct exynos_drm_private *dev_priv = drm_dev->dev_private; @@ -425,7 +432,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work) struct vidi_context *ctx = container_of(work, struct vidi_context, work); struct exynos_drm_subdrv *subdrv = &ctx->subdrv; - struct exynos_drm_manager *manager = &subdrv->manager; + struct exynos_drm_manager *manager = subdrv->manager; if (manager->pipe < 0) return; @@ -471,7 +478,7 @@ static void vidi_subdrv_remove(struct drm_device *drm_dev) static int vidi_power_on(struct vidi_context *ctx, bool enable) { struct exynos_drm_subdrv *subdrv = &ctx->subdrv; - struct device *dev = subdrv->manager.dev; + struct device *dev = subdrv->dev; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -611,13 +618,10 @@ static int __devinit vidi_probe(struct platform_device *pdev) ctx->raw_edid = (struct edid *)fake_edid_info; subdrv = &ctx->subdrv; + subdrv->dev = dev; + subdrv->manager = &vidi_manager; subdrv->probe = vidi_subdrv_probe; subdrv->remove = vidi_subdrv_remove; - subdrv->manager.pipe = -1; - subdrv->manager.ops = &vidi_manager_ops; - subdrv->manager.overlay_ops = &vidi_overlay_ops; - subdrv->manager.display_ops = &vidi_display_ops; - subdrv->manager.dev = dev; mutex_init(&ctx->lock); diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 575a8cbd3533..b00353876458 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -40,7 +40,6 @@ #include "exynos_hdmi.h" -#define HDMI_OVERLAY_NUMBER 3 #define MAX_WIDTH 1920 #define MAX_HEIGHT 1080 #define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev)) @@ -1194,7 +1193,7 @@ static int hdmi_conf_index(struct hdmi_context *hdata, static bool hdmi_is_connected(void *ctx) { - struct hdmi_context *hdata = (struct hdmi_context *)ctx; + struct hdmi_context *hdata = ctx; u32 val = hdmi_reg_read(hdata, HDMI_HPD_STATUS); if (val) @@ -1207,7 +1206,7 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector, u8 *edid, int len) { struct edid *raw_edid; - struct hdmi_context *hdata = (struct hdmi_context *)ctx; + struct hdmi_context *hdata = ctx; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -1275,7 +1274,7 @@ static int hdmi_v14_check_timing(struct fb_videomode *check_timing) static int hdmi_check_timing(void *ctx, void *timing) { - struct hdmi_context *hdata = (struct hdmi_context *)ctx; + struct hdmi_context *hdata = ctx; struct fb_videomode *check_timing = timing; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -1312,13 +1311,6 @@ static int hdmi_display_power_on(void *ctx, int mode) return 0; } -static struct exynos_hdmi_display_ops display_ops = { - .is_connected = hdmi_is_connected, - .get_edid = hdmi_get_edid, - .check_timing = hdmi_check_timing, - .power_on = hdmi_display_power_on, -}; - static void hdmi_set_acr(u32 freq, u8 *acr) { u32 n, cts; @@ -1914,7 +1906,7 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, struct drm_display_mode *adjusted_mode) { struct drm_display_mode *m; - struct hdmi_context *hdata = (struct hdmi_context *)ctx; + struct hdmi_context *hdata = ctx; int index; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -1951,7 +1943,7 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, static void hdmi_mode_set(void *ctx, void *mode) { - struct hdmi_context *hdata = (struct hdmi_context *)ctx; + struct hdmi_context *hdata = ctx; int conf_idx; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -1974,7 +1966,7 @@ static void hdmi_get_max_resol(void *ctx, unsigned int *width, static void hdmi_commit(void *ctx) { - struct hdmi_context *hdata = (struct hdmi_context *)ctx; + struct hdmi_context *hdata = ctx; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -1985,7 +1977,7 @@ static void hdmi_commit(void *ctx) static void hdmi_disable(void *ctx) { - struct hdmi_context *hdata = (struct hdmi_context *)ctx; + struct hdmi_context *hdata = ctx; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -1996,7 +1988,14 @@ static void hdmi_disable(void *ctx) } } -static struct exynos_hdmi_manager_ops manager_ops = { +static struct exynos_hdmi_ops hdmi_ops = { + /* display */ + .is_connected = hdmi_is_connected, + .get_edid = hdmi_get_edid, + .check_timing = hdmi_check_timing, + .power_on = hdmi_display_power_on, + + /* manager */ .mode_fixup = hdmi_mode_fixup, .mode_set = hdmi_mode_set, .get_max_resol = hdmi_get_max_resol, @@ -2020,7 +2019,7 @@ static void hdmi_hotplug_func(struct work_struct *work) static irqreturn_t hdmi_irq_handler(int irq, void *arg) { struct exynos_drm_hdmi_context *ctx = arg; - struct hdmi_context *hdata = (struct hdmi_context *)ctx->ctx; + struct hdmi_context *hdata = ctx->ctx; u32 intc_flag; intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG); @@ -2173,7 +2172,7 @@ static int hdmi_runtime_suspend(struct device *dev) DRM_DEBUG_KMS("%s\n", __func__); - hdmi_resource_poweroff((struct hdmi_context *)ctx->ctx); + hdmi_resource_poweroff(ctx->ctx); return 0; } @@ -2184,7 +2183,7 @@ static int hdmi_runtime_resume(struct device *dev) DRM_DEBUG_KMS("%s\n", __func__); - hdmi_resource_poweron((struct hdmi_context *)ctx->ctx); + hdmi_resource_poweron(ctx->ctx); return 0; } @@ -2322,8 +2321,7 @@ static int __devinit hdmi_probe(struct platform_device *pdev) hdata->irq = res->start; /* register specific callbacks to common hdmi. */ - exynos_drm_display_ops_register(&display_ops); - exynos_drm_manager_ops_register(&manager_ops); + exynos_hdmi_ops_register(&hdmi_ops); hdmi_resource_poweron(hdata); @@ -2351,7 +2349,7 @@ err_data: static int __devexit hdmi_remove(struct platform_device *pdev) { struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev); - struct hdmi_context *hdata = (struct hdmi_context *)ctx->ctx; + struct hdmi_context *hdata = ctx->ctx; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 4d5f41e19527..e15438c01129 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -37,7 +37,8 @@ #include "exynos_drm_drv.h" #include "exynos_drm_hdmi.h" -#define HDMI_OVERLAY_NUMBER 3 +#define MIXER_WIN_NR 3 +#define MIXER_DEFAULT_WIN 0 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev)) @@ -75,16 +76,12 @@ struct mixer_resources { }; struct mixer_context { - struct fb_videomode *default_timing; - unsigned int default_win; - unsigned int default_bpp; unsigned int irq; int pipe; bool interlace; - bool vp_enabled; struct mixer_resources mixer_res; - struct hdmi_win_data win_data[HDMI_OVERLAY_NUMBER]; + struct hdmi_win_data win_data[MIXER_WIN_NR]; }; static const u8 filter_y_horiz_tap8[] = { @@ -643,9 +640,9 @@ static void mixer_win_mode_set(void *ctx, win = overlay->zpos; if (win == DEFAULT_ZPOS) - win = mixer_ctx->default_win; + win = MIXER_DEFAULT_WIN; - if (win < 0 || win > HDMI_OVERLAY_NUMBER) { + if (win < 0 || win > MIXER_WIN_NR) { DRM_ERROR("overlay plane[%d] is wrong\n", win); return; } @@ -683,9 +680,9 @@ static void mixer_win_commit(void *ctx, int zpos) DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); if (win == DEFAULT_ZPOS) - win = mixer_ctx->default_win; + win = MIXER_DEFAULT_WIN; - if (win < 0 || win > HDMI_OVERLAY_NUMBER) { + if (win < 0 || win > MIXER_WIN_NR) { DRM_ERROR("overlay plane[%d] is wrong\n", win); return; } @@ -706,9 +703,9 @@ static void mixer_win_disable(void *ctx, int zpos) DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); if (win == DEFAULT_ZPOS) - win = mixer_ctx->default_win; + win = MIXER_DEFAULT_WIN; - if (win < 0 || win > HDMI_OVERLAY_NUMBER) { + if (win < 0 || win > MIXER_WIN_NR) { DRM_ERROR("overlay plane[%d] is wrong\n", win); return; } @@ -722,9 +719,12 @@ static void mixer_win_disable(void *ctx, int zpos) spin_unlock_irqrestore(&res->reg_slock, flags); } -static struct exynos_hdmi_overlay_ops overlay_ops = { +static struct exynos_mixer_ops mixer_ops = { + /* manager */ .enable_vblank = mixer_enable_vblank, .disable_vblank = mixer_disable_vblank, + + /* overlay */ .win_mode_set = mixer_win_mode_set, .win_commit = mixer_win_commit, .win_disable = mixer_win_disable, @@ -771,8 +771,7 @@ static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc) static irqreturn_t mixer_irq_handler(int irq, void *arg) { struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg; - struct mixer_context *ctx = - (struct mixer_context *)drm_hdmi_ctx->ctx; + struct mixer_context *ctx = drm_hdmi_ctx->ctx; struct mixer_resources *res = &ctx->mixer_res; u32 val, val_base; @@ -902,7 +901,7 @@ static int mixer_runtime_resume(struct device *dev) DRM_DEBUG_KMS("resume - start\n"); - mixer_resource_poweron((struct mixer_context *)ctx->ctx); + mixer_resource_poweron(ctx->ctx); return 0; } @@ -913,7 +912,7 @@ static int mixer_runtime_suspend(struct device *dev) DRM_DEBUG_KMS("suspend - start\n"); - mixer_resource_poweroff((struct mixer_context *)ctx->ctx); + mixer_resource_poweroff(ctx->ctx); return 0; } @@ -926,8 +925,7 @@ static const struct dev_pm_ops mixer_pm_ops = { static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx, struct platform_device *pdev) { - struct mixer_context *mixer_ctx = - (struct mixer_context *)ctx->ctx; + struct mixer_context *mixer_ctx = ctx->ctx; struct device *dev = &pdev->dev; struct mixer_resources *mixer_res = &mixer_ctx->mixer_res; struct resource *res; @@ -1076,7 +1074,7 @@ static int __devinit mixer_probe(struct platform_device *pdev) goto fail; /* register specific callback point to common hdmi. */ - exynos_drm_overlay_ops_register(&overlay_ops); + exynos_mixer_ops_register(&mixer_ops); mixer_resource_poweron(ctx); @@ -1093,7 +1091,7 @@ static int mixer_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; struct exynos_drm_hdmi_context *drm_hdmi_ctx = platform_get_drvdata(pdev); - struct mixer_context *ctx = (struct mixer_context *)drm_hdmi_ctx->ctx; + struct mixer_context *ctx = drm_hdmi_ctx->ctx; dev_info(dev, "remove successful\n"); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index dfa55e7478fb..ae8a64f9f845 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -64,7 +64,7 @@ MODULE_PARM_DESC(semaphores, "Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))"); int i915_enable_rc6 __read_mostly = -1; -module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600); +module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0400); MODULE_PARM_DESC(i915_enable_rc6, "Enable power-saving render C-state 6. " "Different stages can be selected via bitmask values " diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4c65c639f772..0e3c6acde955 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1493,6 +1493,7 @@ i915_gem_object_move_off_active(struct drm_i915_gem_object *obj) { list_del_init(&obj->ring_list); obj->last_rendering_seqno = 0; + obj->last_fenced_seqno = 0; } static void @@ -1521,6 +1522,7 @@ i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj) BUG_ON(!list_empty(&obj->gpu_write_list)); BUG_ON(!obj->active); obj->ring = NULL; + obj->last_fenced_ring = NULL; i915_gem_object_move_off_active(obj); obj->fenced_gpu_access = false; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2abf4eb94039..b4bb1ef77ddc 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3728,6 +3728,9 @@ #define GT_FIFO_FREE_ENTRIES 0x120008 #define GT_FIFO_NUM_RESERVED_ENTRIES 20 +#define GEN6_UCGCTL1 0x9400 +# define GEN6_BLBUNIT_CLOCK_GATE_DISABLE (1 << 5) + #define GEN6_UCGCTL2 0x9404 # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13) # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 91b35fd1db8c..bae38acf44dc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2245,6 +2245,33 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, } static int +intel_finish_fb(struct drm_framebuffer *old_fb) +{ + struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj; + struct drm_i915_private *dev_priv = obj->base.dev->dev_private; + bool was_interruptible = dev_priv->mm.interruptible; + int ret; + + wait_event(dev_priv->pending_flip_queue, + atomic_read(&dev_priv->mm.wedged) || + atomic_read(&obj->pending_flip) == 0); + + /* Big Hammer, we also need to ensure that any pending + * MI_WAIT_FOR_EVENT inside a user batch buffer on the + * current scanout is retired before unpinning the old + * framebuffer. + * + * This should only fail upon a hung GPU, in which case we + * can safely continue. + */ + dev_priv->mm.interruptible = false; + ret = i915_gem_object_finish_gpu(obj); + dev_priv->mm.interruptible = was_interruptible; + + return ret; +} + +static int intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { @@ -2282,25 +2309,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return ret; } - if (old_fb) { - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj; - - wait_event(dev_priv->pending_flip_queue, - atomic_read(&dev_priv->mm.wedged) || - atomic_read(&obj->pending_flip) == 0); - - /* Big Hammer, we also need to ensure that any pending - * MI_WAIT_FOR_EVENT inside a user batch buffer on the - * current scanout is retired before unpinning the old - * framebuffer. - * - * This should only fail upon a hung GPU, in which case we - * can safely continue. - */ - ret = i915_gem_object_finish_gpu(obj); - (void) ret; - } + if (old_fb) + intel_finish_fb(old_fb); ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y, LEAVE_ATOMIC_MODE_SET); @@ -3371,6 +3381,23 @@ static void intel_crtc_disable(struct drm_crtc *crtc) struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; struct drm_device *dev = crtc->dev; + /* Flush any pending WAITs before we disable the pipe. Note that + * we need to drop the struct_mutex in order to acquire it again + * during the lowlevel dpms routines around a couple of the + * operations. It does not look trivial nor desirable to move + * that locking higher. So instead we leave a window for the + * submission of further commands on the fb before we can actually + * disable it. This race with userspace exists anyway, and we can + * only rely on the pipe being disabled by userspace after it + * receives the hotplug notification and has flushed any pending + * batches. + */ + if (crtc->fb) { + mutex_lock(&dev->struct_mutex); + intel_finish_fb(crtc->fb); + mutex_unlock(&dev->struct_mutex); + } + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); @@ -8529,6 +8556,10 @@ static void gen6_init_clock_gating(struct drm_device *dev) I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0); + I915_WRITE(GEN6_UCGCTL1, + I915_READ(GEN6_UCGCTL1) | + GEN6_BLBUNIT_CLOCK_GATE_DISABLE); + /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock * gating disable must be set. Failure to set it results in * flickering pixels due to Z write ordering failures after diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 110552ff302c..4b637919f74f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -219,14 +219,38 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) return (max_link_clock * max_lanes * 8) / 10; } +static bool +intel_dp_adjust_dithering(struct intel_dp *intel_dp, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); + int max_lanes = intel_dp_max_lane_count(intel_dp); + int max_rate, mode_rate; + + mode_rate = intel_dp_link_required(mode->clock, 24); + max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); + + if (mode_rate > max_rate) { + mode_rate = intel_dp_link_required(mode->clock, 18); + if (mode_rate > max_rate) + return false; + + if (adjusted_mode) + adjusted_mode->private_flags + |= INTEL_MODE_DP_FORCE_6BPC; + + return true; + } + + return true; +} + static int intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct intel_dp *intel_dp = intel_attached_dp(connector); - int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); - int max_lanes = intel_dp_max_lane_count(intel_dp); - int max_rate, mode_rate; if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay) @@ -236,16 +260,8 @@ intel_dp_mode_valid(struct drm_connector *connector, return MODE_PANEL; } - mode_rate = intel_dp_link_required(mode->clock, 24); - max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); - - if (mode_rate > max_rate) { - mode_rate = intel_dp_link_required(mode->clock, 18); - if (mode_rate > max_rate) - return MODE_CLOCK_HIGH; - else - mode->private_flags |= INTEL_MODE_DP_FORCE_6BPC; - } + if (!intel_dp_adjust_dithering(intel_dp, mode, NULL)) + return MODE_CLOCK_HIGH; if (mode->clock < 10000) return MODE_CLOCK_LOW; @@ -672,7 +688,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, int lane_count, clock; int max_lane_count = intel_dp_max_lane_count(intel_dp); int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0; - int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; + int bpp; static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { @@ -686,6 +702,11 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, mode->clock = intel_dp->panel_fixed_mode->clock; } + if (!intel_dp_adjust_dithering(intel_dp, mode, adjusted_mode)) + return false; + + bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; + for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { for (clock = 0; clock <= max_clock; clock++) { int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 601c86e664af..8fdc95700218 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -390,7 +390,7 @@ int intel_setup_gmbus(struct drm_device *dev) bus->has_gpio = intel_gpio_setup(bus, i); /* XXX force bit banging until GMBUS is fully debugged */ - if (bus->has_gpio && IS_GEN2(dev)) + if (bus->has_gpio) bus->force_bit = true; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e25581a9f60f..f75806e5bff5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1038,7 +1038,7 @@ int intel_init_ring_buffer(struct drm_device *dev, * of the buffer. */ ring->effective_size = ring->size; - if (IS_I830(ring->dev)) + if (IS_I830(ring->dev) || IS_845G(ring->dev)) ring->effective_size -= 128; return 0; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index a464771a7240..e90dfb625c42 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -95,7 +95,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, /* must disable */ sprctl |= SPRITE_TRICKLE_FEED_DISABLE; sprctl |= SPRITE_ENABLE; - sprctl |= SPRITE_DEST_KEY; /* Sizes are 0 based */ src_w--; diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index e607c4d7dd98..2d39f9977e00 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -230,6 +230,10 @@ atombios_dvo_setup(struct drm_encoder *encoder, int action) if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) return; + /* some R4xx chips have the wrong frev */ + if (rdev->family <= CHIP_RV410) + frev = 1; + switch (frev) { case 1: switch (crev) { diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 81801c176aa5..fe33d35dae8c 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -2553,7 +2553,7 @@ static void r100_pll_errata_after_data(struct radeon_device *rdev) * or the chip could hang on a subsequent access */ if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) { - udelay(5000); + mdelay(5); } /* This function is required to workaround a hardware bug in some (all?) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 391bd2636a80..de71243b591f 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2839,7 +2839,7 @@ void r600_rlc_stop(struct radeon_device *rdev) /* r7xx asics need to soft reset RLC before halting */ WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC); RREG32(SRBM_SOFT_RESET); - udelay(15000); + mdelay(15); WREG32(SRBM_SOFT_RESET, 0); RREG32(SRBM_SOFT_RESET); } diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c index 84c546250955..75ed17c96115 100644 --- a/drivers/gpu/drm/radeon/r600_cp.c +++ b/drivers/gpu/drm/radeon/r600_cp.c @@ -407,7 +407,7 @@ static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv) RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP); RADEON_READ(R600_GRBM_SOFT_RESET); - DRM_UDELAY(15000); + mdelay(15); RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); fw_data = (const __be32 *)dev_priv->me_fw->data; @@ -500,7 +500,7 @@ static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv) RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP); RADEON_READ(R600_GRBM_SOFT_RESET); - DRM_UDELAY(15000); + mdelay(15); RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); fw_data = (const __be32 *)dev_priv->pfp_fw->data; @@ -1797,7 +1797,7 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev, RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP); RADEON_READ(R600_GRBM_SOFT_RESET); - DRM_UDELAY(15000); + mdelay(15); RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index 6ae0c75f016a..9c6b29a41927 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -633,7 +633,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) tmp &= ~(R300_SCLK_FORCE_VAP); tmp |= RADEON_SCLK_FORCE_CP; WREG32_PLL(RADEON_SCLK_CNTL, tmp); - udelay(15000); + mdelay(15); tmp = RREG32_PLL(R300_SCLK_CNTL2); tmp &= ~(R300_SCLK_FORCE_TCL | @@ -651,12 +651,12 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) tmp |= (RADEON_ENGIN_DYNCLK_MODE | (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT)); WREG32_PLL(RADEON_CLK_PWRMGT_CNTL, tmp); - udelay(15000); + mdelay(15); tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL); tmp |= RADEON_SCLK_DYN_START_CNTL; WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp); - udelay(15000); + mdelay(15); /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200 to lockup randomly, leave them as set by BIOS. @@ -696,7 +696,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) tmp |= RADEON_SCLK_MORE_FORCEON; } WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); - udelay(15000); + mdelay(15); } /* RV200::A11 A12, RV250::A11 A12 */ @@ -709,7 +709,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) tmp |= RADEON_TCL_BYPASS_DISABLE; WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp); } - udelay(15000); + mdelay(15); /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK) */ tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); @@ -722,14 +722,14 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) RADEON_PIXCLK_TMDS_ALWAYS_ONb); WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); - udelay(15000); + mdelay(15); tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); tmp |= (RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb); WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); - udelay(15000); + mdelay(15); } } else { /* Turn everything OFF (ForceON to everything) */ @@ -861,7 +861,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) } WREG32_PLL(RADEON_SCLK_CNTL, tmp); - udelay(16000); + mdelay(16); if ((rdev->family == CHIP_R300) || (rdev->family == CHIP_R350)) { @@ -870,7 +870,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) R300_SCLK_FORCE_GA | R300_SCLK_FORCE_CBA); WREG32_PLL(R300_SCLK_CNTL2, tmp); - udelay(16000); + mdelay(16); } if (rdev->flags & RADEON_IS_IGP) { @@ -878,7 +878,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) tmp &= ~(RADEON_FORCEON_MCLKA | RADEON_FORCEON_YCLKA); WREG32_PLL(RADEON_MCLK_CNTL, tmp); - udelay(16000); + mdelay(16); } if ((rdev->family == CHIP_RV200) || @@ -887,7 +887,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); tmp |= RADEON_SCLK_MORE_FORCEON; WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); - udelay(16000); + mdelay(16); } tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); @@ -900,7 +900,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) RADEON_PIXCLK_TMDS_ALWAYS_ONb); WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); - udelay(16000); + mdelay(16); tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 81fc100be7e1..2cad9fde92fc 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -2845,7 +2845,7 @@ bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder) case 4: val = RBIOS16(index); index += 2; - udelay(val * 1000); + mdelay(val); break; case 6: slave_addr = id & 0xff; @@ -3044,7 +3044,7 @@ static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset) udelay(150); break; case 2: - udelay(1000); + mdelay(1); break; case 3: while (tmp--) { @@ -3075,13 +3075,13 @@ static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset) /*mclk_cntl |= 0x00001111;*//* ??? */ WREG32_PLL(RADEON_MCLK_CNTL, mclk_cntl); - udelay(10000); + mdelay(10); #endif WREG32_PLL (RADEON_CLK_PWRMGT_CNTL, tmp & ~RADEON_CG_NO1_DEBUG_0); - udelay(10000); + mdelay(10); } break; default: diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 85bcfc8923a7..3edec1c198e3 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -900,6 +900,10 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, struct radeon_i2c_chan *i2c; int ret; + /* don't add the mm_i2c bus unless hw_i2c is enabled */ + if (rec->mm_i2c && (radeon_hw_i2c == 0)) + return NULL; + i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL); if (i2c == NULL) return NULL; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 2f46e0c8df53..42db254f6bb0 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -88,7 +88,7 @@ static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode) lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); lvds_pll_cntl |= RADEON_LVDS_PLL_EN; WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); - udelay(1000); + mdelay(1); lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; @@ -101,7 +101,7 @@ static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode) (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT)); if (is_mac) lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN; - udelay(panel_pwr_delay * 1000); + mdelay(panel_pwr_delay); WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); break; case DRM_MODE_DPMS_STANDBY: @@ -118,10 +118,10 @@ static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode) WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON); } - udelay(panel_pwr_delay * 1000); + mdelay(panel_pwr_delay); WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); - udelay(panel_pwr_delay * 1000); + mdelay(panel_pwr_delay); break; } @@ -656,7 +656,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc WREG32(RADEON_DAC_MACRO_CNTL, tmp); - udelay(2000); + mdelay(2); if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) found = connector_status_connected; @@ -1499,7 +1499,7 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN; WREG32(RADEON_DAC_CNTL2, tmp); - udelay(10000); + mdelay(10); if (ASIC_IS_R300(rdev)) { if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) diff --git a/drivers/gpu/drm/savage/savage_state.c b/drivers/gpu/drm/savage/savage_state.c index 031aaaf79ac2..b6d8608375cd 100644 --- a/drivers/gpu/drm/savage/savage_state.c +++ b/drivers/gpu/drm/savage/savage_state.c @@ -988,7 +988,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ * for locking on FreeBSD. */ if (cmdbuf->size) { - kcmd_addr = kmalloc(cmdbuf->size * 8, GFP_KERNEL); + kcmd_addr = kmalloc_array(cmdbuf->size, 8, GFP_KERNEL); if (kcmd_addr == NULL) return -ENOMEM; @@ -1015,8 +1015,8 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ cmdbuf->vb_addr = kvb_addr; } if (cmdbuf->nbox) { - kbox_addr = kmalloc(cmdbuf->nbox * sizeof(struct drm_clip_rect), - GFP_KERNEL); + kbox_addr = kmalloc_array(cmdbuf->nbox, sizeof(struct drm_clip_rect), + GFP_KERNEL); if (kbox_addr == NULL) { ret = -ENOMEM; goto done; diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 145f13580ff0..9140236a0182 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -391,6 +391,7 @@ static ssize_t show_str(struct device *dev, break; default: BUG(); + val = ""; } return sprintf(buf, "%s\n", val); diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index be51037363c8..29b319db573e 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -710,13 +710,13 @@ static u16 pmbus_data2reg(struct pmbus_data *data, * If a negative value is stored in any of the referenced registers, this value * reflects an error code which will be returned. */ -static int pmbus_get_boolean(struct pmbus_data *data, int index, int *val) +static int pmbus_get_boolean(struct pmbus_data *data, int index) { u8 s1 = (index >> 24) & 0xff; u8 s2 = (index >> 16) & 0xff; u8 reg = (index >> 8) & 0xff; u8 mask = index & 0xff; - int status; + int ret, status; u8 regval; status = data->status[reg]; @@ -725,7 +725,7 @@ static int pmbus_get_boolean(struct pmbus_data *data, int index, int *val) regval = status & mask; if (!s1 && !s2) - *val = !!regval; + ret = !!regval; else { long v1, v2; struct pmbus_sensor *sensor1, *sensor2; @@ -739,9 +739,9 @@ static int pmbus_get_boolean(struct pmbus_data *data, int index, int *val) v1 = pmbus_reg2data(data, sensor1); v2 = pmbus_reg2data(data, sensor2); - *val = !!(regval && v1 >= v2); + ret = !!(regval && v1 >= v2); } - return 0; + return ret; } static ssize_t pmbus_show_boolean(struct device *dev, @@ -750,11 +750,10 @@ static ssize_t pmbus_show_boolean(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct pmbus_data *data = pmbus_update_device(dev); int val; - int err; - err = pmbus_get_boolean(data, attr->index, &val); - if (err) - return err; + val = pmbus_get_boolean(data, attr->index); + if (val < 0) + return val; return snprintf(buf, PAGE_SIZE, "%d\n", val); } diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index d3b778da3f86..c5f6be478bad 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c @@ -343,10 +343,11 @@ exit: return err; } -static int __init smsc47b397_find(unsigned short *addr) +static int __init smsc47b397_find(void) { u8 id, rev; char *name; + unsigned short addr; superio_enter(); id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID); @@ -370,14 +371,14 @@ static int __init smsc47b397_find(unsigned short *addr) rev = superio_inb(SUPERIO_REG_DEVREV); superio_select(SUPERIO_REG_LD8); - *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8) + addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8) | superio_inb(SUPERIO_REG_BASE_LSB); pr_info("found SMSC %s (base address 0x%04x, revision %u)\n", - name, *addr, rev); + name, addr, rev); superio_exit(); - return 0; + return addr; } static int __init smsc47b397_init(void) @@ -385,9 +386,10 @@ static int __init smsc47b397_init(void) unsigned short address; int ret; - ret = smsc47b397_find(&address); - if (ret) + ret = smsc47b397_find(); + if (ret < 0) return ret; + address = ret; ret = platform_driver_register(&smsc47b397_driver); if (ret) diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index c590c1469793..b5aa38dd7ab9 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -491,10 +491,10 @@ static const struct attribute_group smsc47m1_group = { .attrs = smsc47m1_attributes, }; -static int __init smsc47m1_find(unsigned short *addr, - struct smsc47m1_sio_data *sio_data) +static int __init smsc47m1_find(struct smsc47m1_sio_data *sio_data) { u8 val; + unsigned short addr; superio_enter(); val = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID); @@ -546,9 +546,9 @@ static int __init smsc47m1_find(unsigned short *addr, } superio_select(); - *addr = (superio_inb(SUPERIO_REG_BASE) << 8) + addr = (superio_inb(SUPERIO_REG_BASE) << 8) | superio_inb(SUPERIO_REG_BASE + 1); - if (*addr == 0) { + if (addr == 0) { pr_info("Device address not set, will not use\n"); superio_exit(); return -ENODEV; @@ -565,7 +565,7 @@ static int __init smsc47m1_find(unsigned short *addr, } superio_exit(); - return 0; + return addr; } /* Restore device to its initial state */ @@ -938,13 +938,15 @@ static int __init sm_smsc47m1_init(void) unsigned short address; struct smsc47m1_sio_data sio_data; - if (smsc47m1_find(&address, &sio_data)) - return -ENODEV; + err = smsc47m1_find(&sio_data); + if (err < 0) + return err; + address = err; /* Sets global pdev as a side effect */ err = smsc47m1_device_add(address, &sio_data); if (err) - goto exit; + return err; err = platform_driver_probe(&smsc47m1_driver, smsc47m1_probe); if (err) @@ -955,7 +957,6 @@ static int __init sm_smsc47m1_init(void) exit_device: platform_device_unregister(pdev); smsc47m1_restore(&sio_data); -exit: return err; } diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 83b720ef6c34..246fdc151652 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -179,7 +179,7 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused, { struct ib_port_attr attr; char *speed = ""; - int rate = -1; /* in deci-Gb/sec */ + int rate; /* in deci-Gb/sec */ ssize_t ret; ret = ib_query_port(p->ibdev, p->port_num, &attr); @@ -187,9 +187,6 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused, return ret; switch (attr.active_speed) { - case IB_SPEED_SDR: - rate = 25; - break; case IB_SPEED_DDR: speed = " DDR"; rate = 50; @@ -210,6 +207,10 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused, speed = " EDR"; rate = 250; break; + case IB_SPEED_SDR: + default: /* default to SDR for invalid rates */ + rate = 25; + break; } rate *= ib_width_enum_to_int(attr.active_width); diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 75d305629300..669673e81439 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -253,6 +253,11 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port, if (out_mad->data[15] & 0x1) props->active_speed = IB_SPEED_FDR10; } + + /* Avoid wrong speed value returned by FW if the IB link is down. */ + if (props->state == IB_PORT_DOWN) + props->active_speed = IB_SPEED_SDR; + out: kfree(in_mad); kfree(out_mad); diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 69e2ad06e515..daf21b899999 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -3232,6 +3232,7 @@ static void srpt_add_one(struct ib_device *device) srq_attr.attr.max_wr = sdev->srq_size; srq_attr.attr.max_sge = 1; srq_attr.attr.srq_limit = 0; + srq_attr.srq_type = IB_SRQT_BASIC; sdev->srq = ib_create_srq(sdev->pd, &srq_attr); if (IS_ERR(sdev->srq)) diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c index 34aebb8cd080..3c843cd725fa 100644 --- a/drivers/input/misc/da9052_onkey.c +++ b/drivers/input/misc/da9052_onkey.c @@ -95,7 +95,8 @@ static int __devinit da9052_onkey_probe(struct platform_device *pdev) input_dev = input_allocate_device(); if (!onkey || !input_dev) { dev_err(&pdev->dev, "Failed to allocate memory\n"); - return -ENOMEM; + error = -ENOMEM; + goto err_free_mem; } onkey->input = input_dev; diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index d2c0db159b18..479011004a11 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -486,7 +486,6 @@ static void elantech_input_sync_v4(struct psmouse *psmouse) unsigned char *packet = psmouse->packet; input_report_key(dev, BTN_LEFT, packet[0] & 0x01); - input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); input_mt_report_pointer_emulation(dev, true); input_sync(dev); } @@ -967,6 +966,7 @@ static int elantech_set_input_params(struct psmouse *psmouse) if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) return -1; + __set_bit(INPUT_PROP_POINTER, dev->propbit); __set_bit(EV_KEY, dev->evbit); __set_bit(EV_ABS, dev->evbit); __clear_bit(EV_REL, dev->evbit); @@ -1017,7 +1017,9 @@ static int elantech_set_input_params(struct psmouse *psmouse) */ psmouse_warn(psmouse, "couldn't query resolution data.\n"); } - + /* v4 is clickpad, with only one button. */ + __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); + __clear_bit(BTN_RIGHT, dev->keybit); __set_bit(BTN_TOOL_QUADTAP, dev->keybit); /* For X to recognize me as touchpad. */ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); @@ -1245,6 +1247,8 @@ static void elantech_disconnect(struct psmouse *psmouse) */ static int elantech_reconnect(struct psmouse *psmouse) { + psmouse_reset(psmouse); + if (elantech_detect(psmouse, 0)) return -1; @@ -1324,6 +1328,8 @@ int elantech_init(struct psmouse *psmouse) if (!etd) return -ENOMEM; + psmouse_reset(psmouse); + etd->parity[0] = 1; for (i = 1; i < 256; i++) etd->parity[i] = etd->parity[i & (i - 1)] ^ 1; diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index a9ad8e1402be..39fe9b737cae 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -12,9 +12,9 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/input-polldev.h> +#include <linux/gpio.h> #include <linux/gpio_mouse.h> -#include <asm/gpio.h> /* * Timer function which is run every scan_ms ms when the device is opened. diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index a977bfaa6821..661a0ca3b3d6 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -741,6 +741,14 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) } } else { /* SFAC packet */ + if ((packet[0] & (FSP_PB0_LBTN|FSP_PB0_PHY_BTN)) == + FSP_PB0_LBTN) { + /* On-pad click in SFAC mode should be handled + * by userspace. On-pad clicks in MFMC mode + * are real clickpad clicks, and not ignored. + */ + packet[0] &= ~FSP_PB0_LBTN; + } /* no multi-finger information */ ad->last_mt_fgr = 0; diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 22b218018137..f3102494237d 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -304,7 +304,7 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) return 0; if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) { - printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n"); + psmouse_warn(psmouse, "failed to get extended button data\n"); button_info = 0; } @@ -326,16 +326,18 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) error = sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group); if (error) { - printk(KERN_ERR - "trackpoint.c: failed to create sysfs attributes, error: %d\n", - error); + psmouse_err(psmouse, + "failed to create sysfs attributes, error: %d\n", + error); kfree(psmouse->private); psmouse->private = NULL; return -1; } - printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n", - firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f); + psmouse_info(psmouse, + "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n", + firmware_id, + (button_info & 0xf0) >> 4, button_info & 0x0f); return 0; } diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c index 6c6f6d8ea9b4..f7eda3d00fad 100644 --- a/drivers/input/touchscreen/tps6507x-ts.c +++ b/drivers/input/touchscreen/tps6507x-ts.c @@ -1,6 +1,4 @@ /* - * drivers/input/touchscreen/tps6507x_ts.c - * * Touchscreen driver for the tps6507x chip. * * Copyright (c) 2009 RidgeRun (todd.fischer@ridgerun.com) @@ -376,4 +374,4 @@ module_platform_driver(tps6507x_ts_driver); MODULE_AUTHOR("Todd Fischer <todd.fischer@ridgerun.com>"); MODULE_DESCRIPTION("TPS6507x - TouchScreen driver"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:tps6507x-tsc"); +MODULE_ALIAS("platform:tps6507x-ts"); diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index b3d6ac17272d..a6d9fd2858f7 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -176,7 +176,7 @@ static void if_close(struct tty_struct *tty, struct file *filp) struct cardstate *cs = tty->driver_data; if (!cs) { /* happens if we didn't find cs in open */ - printk(KERN_DEBUG "%s: no cardstate\n", __func__); + gig_dbg(DEBUG_IF, "%s: no cardstate", __func__); return; } diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 3d0dfa7a89a2..97e73e555d11 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -539,9 +539,6 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap) bitmap->events_cleared = bitmap->mddev->events; sb->events_cleared = cpu_to_le64(bitmap->mddev->events); - bitmap->flags |= BITMAP_HOSTENDIAN; - sb->version = cpu_to_le32(BITMAP_MAJOR_HOSTENDIAN); - kunmap_atomic(sb); return 0; @@ -1788,7 +1785,9 @@ int bitmap_load(struct mddev *mddev) * re-add of a missing device */ start = mddev->recovery_cp; + mutex_lock(&mddev->bitmap_info.mutex); err = bitmap_init_from_disk(bitmap, start); + mutex_unlock(&mddev->bitmap_info.mutex); if (err) goto out; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d35e4c991e38..15dd59b84e94 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1712,6 +1712,7 @@ static int process_checks(struct r1bio *r1_bio) struct r1conf *conf = mddev->private; int primary; int i; + int vcnt; for (primary = 0; primary < conf->raid_disks * 2; primary++) if (r1_bio->bios[primary]->bi_end_io == end_sync_read && @@ -1721,9 +1722,9 @@ static int process_checks(struct r1bio *r1_bio) break; } r1_bio->read_disk = primary; + vcnt = (r1_bio->sectors + PAGE_SIZE / 512 - 1) >> (PAGE_SHIFT - 9); for (i = 0; i < conf->raid_disks * 2; i++) { int j; - int vcnt = r1_bio->sectors >> (PAGE_SHIFT- 9); struct bio *pbio = r1_bio->bios[primary]; struct bio *sbio = r1_bio->bios[i]; int size; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index fff782189e48..c8dbb84d5357 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1788,6 +1788,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) struct r10conf *conf = mddev->private; int i, first; struct bio *tbio, *fbio; + int vcnt; atomic_set(&r10_bio->remaining, 1); @@ -1802,10 +1803,10 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) first = i; fbio = r10_bio->devs[i].bio; + vcnt = (r10_bio->sectors + (PAGE_SIZE >> 9) - 1) >> (PAGE_SHIFT - 9); /* now find blocks with errors */ for (i=0 ; i < conf->copies ; i++) { int j, d; - int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9); tbio = r10_bio->devs[i].bio; @@ -1871,7 +1872,6 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) */ for (i = 0; i < conf->copies; i++) { int j, d; - int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9); tbio = r10_bio->devs[i].repl_bio; if (!tbio || !tbio->bi_end_io) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 4555baa383b2..39696c6a4ed7 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -143,10 +143,12 @@ struct dvb_frontend_private { static void dvb_frontend_wakeup(struct dvb_frontend *fe); static int dtv_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p_out); +static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p); static bool has_get_frontend(struct dvb_frontend *fe) { - return fe->ops.get_frontend; + return fe->ops.get_frontend != NULL; } /* @@ -697,6 +699,7 @@ restart: fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; fepriv->delay = HZ / 2; } + dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); fe->ops.read_status(fe, &s); if (s != fepriv->status) { dvb_frontend_add_event(fe, s); /* update event list */ @@ -1833,6 +1836,13 @@ static int dtv_set_frontend(struct dvb_frontend *fe) return -EINVAL; /* + * Initialize output parameters to match the values given by + * the user. FE_SET_FRONTEND triggers an initial frontend event + * with status = 0, which copies output parameters to userspace. + */ + dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); + + /* * Be sure that the bandwidth will be filled for all * non-satellite systems, as tuners need to know what * low pass/Nyquist half filter should be applied, in diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c index 3b7b102f20ae..482d249ca7f3 100644 --- a/drivers/media/dvb/dvb-usb/it913x.c +++ b/drivers/media/dvb/dvb-usb/it913x.c @@ -238,12 +238,27 @@ static int it913x_read_reg(struct usb_device *udev, u32 reg) static u32 it913x_query(struct usb_device *udev, u8 pro) { - int ret; + int ret, i; u8 data[4]; - ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ, - 0x1222, 0, &data[0], 3); + u8 ver; + + for (i = 0; i < 5; i++) { + ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ, + 0x1222, 0, &data[0], 3); + ver = data[0]; + if (ver > 0 && ver < 3) + break; + msleep(100); + } - it913x_config.chip_ver = data[0]; + if (ver < 1 || ver > 2) { + info("Failed to identify chip version applying 1"); + it913x_config.chip_ver = 0x1; + it913x_config.chip_type = 0x9135; + return 0; + } + + it913x_config.chip_ver = ver; it913x_config.chip_type = (u16)(data[2] << 8) + data[1]; info("Chip Version=%02x Chip Type=%04x", it913x_config.chip_ver, @@ -660,30 +675,41 @@ static int it913x_download_firmware(struct usb_device *udev, if ((packet_size > min_pkt) || (i == fw->size)) { fw_data = (u8 *)(fw->data + pos); pos += packet_size; - if (packet_size > 0) - ret |= it913x_io(udev, WRITE_DATA, + if (packet_size > 0) { + ret = it913x_io(udev, WRITE_DATA, DEV_0, CMD_SCATTER_WRITE, 0, 0, fw_data, packet_size); + if (ret < 0) + break; + } udelay(1000); } } i++; } - ret |= it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0); - - msleep(100); - if (ret < 0) - info("FRM Firmware Download Failed (%04x)" , ret); + info("FRM Firmware Download Failed (%d)" , ret); else info("FRM Firmware Download Completed - Resetting Device"); - ret |= it913x_return_status(udev); + msleep(30); + + ret = it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0); + if (ret < 0) + info("FRM Device not responding to reboot"); + + ret = it913x_return_status(udev); + if (ret == 0) { + info("FRM Failed to reboot device"); + return -ENODEV; + } msleep(30); - ret |= it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400); + ret = it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400); + + msleep(30); /* Tuner function */ if (it913x_config.dual_mode) @@ -901,5 +927,5 @@ module_usb_driver(it913x_driver); MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); MODULE_DESCRIPTION("it913x USB 2 Driver"); -MODULE_VERSION("1.27"); +MODULE_VERSION("1.28"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 5452beef8e11..989e556913ed 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1763,13 +1763,13 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); if (iarg > AUDIO_STEREO_SWAPPED) return -EINVAL; - return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg); + return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1); case AUDIO_BILINGUAL_CHANNEL_SELECT: IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); if (iarg > AUDIO_STEREO_SWAPPED) return -EINVAL; - return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg); + return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1); default: return -EINVAL; diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 4a44f9a1bae0..b76b0ac0958f 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -468,22 +468,30 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf, spin_unlock_irqrestore(&stream->clock.lock, flags); } -static int uvc_video_clock_init(struct uvc_streaming *stream) +static void uvc_video_clock_reset(struct uvc_streaming *stream) { struct uvc_clock *clock = &stream->clock; - spin_lock_init(&clock->lock); clock->head = 0; clock->count = 0; - clock->size = 32; clock->last_sof = -1; clock->sof_offset = -1; +} + +static int uvc_video_clock_init(struct uvc_streaming *stream) +{ + struct uvc_clock *clock = &stream->clock; + + spin_lock_init(&clock->lock); + clock->size = 32; clock->samples = kmalloc(clock->size * sizeof(*clock->samples), GFP_KERNEL); if (clock->samples == NULL) return -ENOMEM; + uvc_video_clock_reset(stream); + return 0; } @@ -1424,8 +1432,6 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) if (free_buffers) uvc_free_urb_buffers(stream); - - uvc_video_clock_cleanup(stream); } /* @@ -1555,10 +1561,6 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) uvc_video_stats_start(stream); - ret = uvc_video_clock_init(stream); - if (ret < 0) - return ret; - if (intf->num_altsetting > 1) { struct usb_host_endpoint *best_ep = NULL; unsigned int best_psize = 3 * 1024; @@ -1683,6 +1685,8 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset) stream->frozen = 0; + uvc_video_clock_reset(stream); + ret = uvc_commit_video(stream, &stream->ctrl); if (ret < 0) { uvc_queue_enable(&stream->queue, 0); @@ -1819,25 +1823,35 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable) uvc_uninit_video(stream, 1); usb_set_interface(stream->dev->udev, stream->intfnum, 0); uvc_queue_enable(&stream->queue, 0); + uvc_video_clock_cleanup(stream); return 0; } - ret = uvc_queue_enable(&stream->queue, 1); + ret = uvc_video_clock_init(stream); if (ret < 0) return ret; + ret = uvc_queue_enable(&stream->queue, 1); + if (ret < 0) + goto error_queue; + /* Commit the streaming parameters. */ ret = uvc_commit_video(stream, &stream->ctrl); - if (ret < 0) { - uvc_queue_enable(&stream->queue, 0); - return ret; - } + if (ret < 0) + goto error_commit; ret = uvc_init_video(stream, GFP_KERNEL); - if (ret < 0) { - usb_set_interface(stream->dev->udev, stream->intfnum, 0); - uvc_queue_enable(&stream->queue, 0); - } + if (ret < 0) + goto error_video; + + return 0; + +error_video: + usb_set_interface(stream->dev->udev, stream->intfnum, 0); +error_commit: + uvc_queue_enable(&stream->queue, 0); +error_queue: + uvc_video_clock_cleanup(stream); return ret; } diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index ebc1e8658226..5be32489714f 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -2788,6 +2788,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { .constraints = { .name = "db8500-vape", .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .always_on = true, }, .consumer_supplies = db8500_vape_consumers, .num_consumer_supplies = ARRAY_SIZE(db8500_vape_consumers), diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 94eb05b1afdf..58fc65f5c817 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -106,16 +106,14 @@ static int mtdchar_open(struct inode *inode, struct file *file) } if (mtd->type == MTD_ABSENT) { - put_mtd_device(mtd); ret = -ENODEV; - goto out; + goto out1; } mtd_ino = iget_locked(mnt->mnt_sb, devnum); if (!mtd_ino) { - put_mtd_device(mtd); ret = -ENOMEM; - goto out; + goto out1; } if (mtd_ino->i_state & I_NEW) { mtd_ino->i_private = mtd; @@ -127,23 +125,25 @@ static int mtdchar_open(struct inode *inode, struct file *file) /* You can't open it RW if it's not a writeable device */ if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { - iput(mtd_ino); - put_mtd_device(mtd); ret = -EACCES; - goto out; + goto out2; } mfi = kzalloc(sizeof(*mfi), GFP_KERNEL); if (!mfi) { - iput(mtd_ino); - put_mtd_device(mtd); ret = -ENOMEM; - goto out; + goto out2; } mfi->ino = mtd_ino; mfi->mtd = mtd; file->private_data = mfi; + mutex_unlock(&mtd_mutex); + return 0; +out2: + iput(mtd_ino); +out1: + put_mtd_device(mtd); out: mutex_unlock(&mtd_mutex); simple_release_fs(&mnt, &count); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 215eb2536b1e..2504ab005589 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -118,15 +118,13 @@ void ath9k_ps_restore(struct ath_softc *sc) if (--sc->ps_usecount != 0) goto unlock; - if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) - goto unlock; - - if (sc->ps_idle) + if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK)) mode = ATH9K_PM_FULL_SLEEP; else if (sc->ps_enabled && !(sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | - PS_WAIT_FOR_PSPOLL_DATA))) + PS_WAIT_FOR_PSPOLL_DATA | + PS_WAIT_FOR_TX_ACK))) mode = ATH9K_PM_NETWORK_SLEEP; else goto unlock; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index fc9901e027c1..90cc5e772650 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1062,11 +1062,6 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags); - /* - * Register the extra components. - */ - rt2x00rfkill_register(rt2x00dev); - return 0; } @@ -1210,6 +1205,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) rt2x00link_register(rt2x00dev); rt2x00leds_register(rt2x00dev); rt2x00debug_register(rt2x00dev); + rt2x00rfkill_register(rt2x00dev); return 0; diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 510023554e5f..e54488db0e10 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -838,7 +838,10 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, __le16 fc = hdr->frame_control; txrate = ieee80211_get_tx_rate(hw, info); - tcb_desc->hw_rate = txrate->hw_value; + if (txrate) + tcb_desc->hw_rate = txrate->hw_value; + else + tcb_desc->hw_rate = 0; if (ieee80211_is_data(fc)) { /* diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 07dd38efe62a..288b035a3579 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -912,8 +912,13 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); ring = &rtlpci->tx_ring[BEACON_QUEUE]; pskb = __skb_dequeue(&ring->queue); - if (pskb) + if (pskb) { + struct rtl_tx_desc *entry = &ring->desc[ring->idx]; + pci_unmap_single(rtlpci->pdev, rtlpriv->cfg->ops->get_desc( + (u8 *) entry, true, HW_DESC_TXBUFF_ADDR), + pskb->len, PCI_DMA_TODEVICE); kfree_skb(pskb); + } /*NB: the beacon data buffer must be 32-bit aligned. */ pskb = ieee80211_beacon_get(hw, mac->vif); diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index 4898c502974d..480862c07f92 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c @@ -91,7 +91,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) u8 tid; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - static int header_print; rtlpriv->dm.dm_initialgain_enable = true; rtlpriv->dm.dm_flag = 0; @@ -171,10 +170,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) for (tid = 0; tid < 8; tid++) skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); - /* Only load firmware for first MAC */ - if (header_print) - return 0; - /* for firmware buf */ rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); if (!rtlpriv->rtlhal.pfirmware) { @@ -186,7 +181,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->max_fw_size = 0x8000; pr_info("Driver for Realtek RTL8192DE WLAN interface\n"); pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); - header_print++; /* request fw */ err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 2e1e352864bb..d04dbda13f5a 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -124,46 +124,38 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request, return status; } -static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len) +static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len) { + struct device *dev = rtlpriv->io.dev; + struct usb_device *udev = to_usb_device(dev); u8 request; u16 wvalue; u16 index; - u32 *data; - u32 ret; + __le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; - data = kmalloc(sizeof(u32), GFP_KERNEL); - if (!data) - return -ENOMEM; request = REALTEK_USB_VENQT_CMD_REQ; index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ wvalue = (u16)addr; _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len); - ret = le32_to_cpu(*data); - kfree(data); - return ret; + if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) + rtlpriv->usb_data_index = 0; + return le32_to_cpu(*data); } static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr) { - struct device *dev = rtlpriv->io.dev; - - return (u8)_usb_read_sync(to_usb_device(dev), addr, 1); + return (u8)_usb_read_sync(rtlpriv, addr, 1); } static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr) { - struct device *dev = rtlpriv->io.dev; - - return (u16)_usb_read_sync(to_usb_device(dev), addr, 2); + return (u16)_usb_read_sync(rtlpriv, addr, 2); } static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr) { - struct device *dev = rtlpriv->io.dev; - - return _usb_read_sync(to_usb_device(dev), addr, 4); + return _usb_read_sync(rtlpriv, addr, 4); } static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val, @@ -955,6 +947,11 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, return -ENOMEM; } rtlpriv = hw->priv; + rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32), + GFP_KERNEL); + if (!rtlpriv->usb_data) + return -ENOMEM; + rtlpriv->usb_data_index = 0; init_completion(&rtlpriv->firmware_loading_complete); SET_IEEE80211_DEV(hw, &intf->dev); udev = interface_to_usbdev(intf); @@ -1025,6 +1022,7 @@ void rtl_usb_disconnect(struct usb_interface *intf) /* rtl_deinit_rfkill(hw); */ rtl_usb_deinit(hw); rtl_deinit_core(hw); + kfree(rtlpriv->usb_data); rtlpriv->cfg->ops->deinit_sw_leds(hw); rtlpriv->cfg->ops->deinit_sw_vars(hw); _rtl_usb_io_handler_release(hw); diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index b591614c3b9b..28ebc69218a3 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -67,7 +67,7 @@ #define QOS_QUEUE_NUM 4 #define RTL_MAC80211_NUM_QUEUE 5 #define REALTEK_USB_VENQT_MAX_BUF_SIZE 254 - +#define RTL_USB_MAX_RX_COUNT 100 #define QBSS_LOAD_SIZE 5 #define MAX_WMMELE_LENGTH 64 @@ -1629,6 +1629,10 @@ struct rtl_priv { interface or hardware */ unsigned long status; + /* data buffer pointer for USB reads */ + __le32 *usb_data; + int usb_data_index; + /*This must be the last item so that it points to the data allocated beyond this structure like: diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c index bba81216b4db..bf984b6dc477 100644 --- a/drivers/of/gpio.c +++ b/drivers/of/gpio.c @@ -140,7 +140,7 @@ int of_gpio_simple_xlate(struct gpio_chip *gc, if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) return -EINVAL; - if (gpiospec->args[0] > gc->ngpio) + if (gpiospec->args[0] >= gc->ngpio) return -EINVAL; if (flags) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 815674415267..111569ccab43 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -967,16 +967,59 @@ pci_save_state(struct pci_dev *dev) return 0; } +static void pci_restore_config_dword(struct pci_dev *pdev, int offset, + u32 saved_val, int retry) +{ + u32 val; + + pci_read_config_dword(pdev, offset, &val); + if (val == saved_val) + return; + + for (;;) { + dev_dbg(&pdev->dev, "restoring config space at offset " + "%#x (was %#x, writing %#x)\n", offset, val, saved_val); + pci_write_config_dword(pdev, offset, saved_val); + if (retry-- <= 0) + return; + + pci_read_config_dword(pdev, offset, &val); + if (val == saved_val) + return; + + mdelay(1); + } +} + +static void pci_restore_config_space_range(struct pci_dev *pdev, + int start, int end, int retry) +{ + int index; + + for (index = end; index >= start; index--) + pci_restore_config_dword(pdev, 4 * index, + pdev->saved_config_space[index], + retry); +} + +static void pci_restore_config_space(struct pci_dev *pdev) +{ + if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL) { + pci_restore_config_space_range(pdev, 10, 15, 0); + /* Restore BARs before the command register. */ + pci_restore_config_space_range(pdev, 4, 9, 10); + pci_restore_config_space_range(pdev, 0, 3, 0); + } else { + pci_restore_config_space_range(pdev, 0, 15, 0); + } +} + /** * pci_restore_state - Restore the saved state of a PCI device * @dev: - PCI device that we're dealing with */ void pci_restore_state(struct pci_dev *dev) { - int i; - u32 val; - int tries; - if (!dev->state_saved) return; @@ -984,24 +1027,8 @@ void pci_restore_state(struct pci_dev *dev) pci_restore_pcie_state(dev); pci_restore_ats_state(dev); - /* - * The Base Address register should be programmed before the command - * register(s) - */ - for (i = 15; i >= 0; i--) { - pci_read_config_dword(dev, i * 4, &val); - tries = 10; - while (tries && val != dev->saved_config_space[i]) { - dev_dbg(&dev->dev, "restoring config " - "space at offset %#x (was %#x, writing %#x)\n", - i, val, (int)dev->saved_config_space[i]); - pci_write_config_dword(dev,i * 4, - dev->saved_config_space[i]); - pci_read_config_dword(dev, i * 4, &val); - mdelay(10); - tries--; - } - } + pci_restore_config_space(dev); + pci_restore_pcix_state(dev); pci_restore_msi_state(dev); pci_restore_iov_state(dev); diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c index 550292304b0f..c9f890b088da 100644 --- a/drivers/rtc/rtc-efi.c +++ b/drivers/rtc/rtc-efi.c @@ -213,7 +213,6 @@ static struct platform_driver efi_rtc_driver = { .name = "rtc-efi", .owner = THIS_MODULE, }, - .probe = efi_rtc_probe, .remove = __exit_p(efi_rtc_remove), }; diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 692de7360e94..684ef4bbfce4 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -339,8 +339,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision); /* Enable the clockwatch on ST Variants */ - if ((ldata->hw_designer == AMBA_VENDOR_ST) && - (ldata->hw_revision > 1)) + if (ldata->hw_designer == AMBA_VENDOR_ST) writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, ldata->base + RTC_CR); diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c index 7f8e6c247935..33b6ba0afa0d 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c @@ -122,6 +122,7 @@ static const struct rtc_class_ops r9701_rtc_ops = { static int __devinit r9701_probe(struct spi_device *spi) { struct rtc_device *rtc; + struct rtc_time dt; unsigned char tmp; int res; @@ -132,6 +133,27 @@ static int __devinit r9701_probe(struct spi_device *spi) return -ENODEV; } + /* + * The device seems to be present. Now check if the registers + * contain invalid values. If so, try to write a default date: + * 2000/1/1 00:00:00 + */ + r9701_get_datetime(&spi->dev, &dt); + if (rtc_valid_tm(&dt)) { + dev_info(&spi->dev, "trying to repair invalid date/time\n"); + dt.tm_sec = 0; + dt.tm_min = 0; + dt.tm_hour = 0; + dt.tm_mday = 1; + dt.tm_mon = 0; + dt.tm_year = 100; + + if (r9701_set_datetime(&spi->dev, &dt)) { + dev_err(&spi->dev, "cannot repair RTC register\n"); + return -ENODEV; + } + } + rtc = rtc_device_register("r9701", &spi->dev, &r9701_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 9ccea134a996..3f3a29752369 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -40,6 +40,10 @@ enum s3c_cpu_type { TYPE_S3C64XX, }; +struct s3c_rtc_drv_data { + int cpu_type; +}; + /* I have yet to find an S3C implementation with more than one * of these rtc blocks in */ @@ -446,10 +450,12 @@ static const struct of_device_id s3c_rtc_dt_match[]; static inline int s3c_rtc_get_driver_data(struct platform_device *pdev) { #ifdef CONFIG_OF + struct s3c_rtc_drv_data *data; if (pdev->dev.of_node) { const struct of_device_id *match; match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node); - return match->data; + data = (struct s3c_rtc_drv_data *) match->data; + return data->cpu_type; } #endif return platform_get_device_id(pdev)->driver_data; @@ -664,20 +670,27 @@ static int s3c_rtc_resume(struct platform_device *pdev) #define s3c_rtc_resume NULL #endif +static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = { + [TYPE_S3C2410] = { TYPE_S3C2410 }, + [TYPE_S3C2416] = { TYPE_S3C2416 }, + [TYPE_S3C2443] = { TYPE_S3C2443 }, + [TYPE_S3C64XX] = { TYPE_S3C64XX }, +}; + #ifdef CONFIG_OF static const struct of_device_id s3c_rtc_dt_match[] = { { - .compatible = "samsung,s3c2410-rtc" - .data = TYPE_S3C2410, + .compatible = "samsung,s3c2410-rtc", + .data = &s3c_rtc_drv_data_array[TYPE_S3C2410], }, { - .compatible = "samsung,s3c2416-rtc" - .data = TYPE_S3C2416, + .compatible = "samsung,s3c2416-rtc", + .data = &s3c_rtc_drv_data_array[TYPE_S3C2416], }, { - .compatible = "samsung,s3c2443-rtc" - .data = TYPE_S3C2443, + .compatible = "samsung,s3c2443-rtc", + .data = &s3c_rtc_drv_data_array[TYPE_S3C2443], }, { - .compatible = "samsung,s3c6410-rtc" - .data = TYPE_S3C64XX, + .compatible = "samsung,s3c6410-rtc", + .data = &s3c_rtc_drv_data_array[TYPE_S3C64XX], }, {}, }; diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 4c2c6df2a9ef..258abeabf624 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -112,6 +112,7 @@ static const u8 twl6030_rtc_reg_map[] = { #define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10 #define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20 #define BIT_RTC_CTRL_REG_GET_TIME_M 0x40 +#define BIT_RTC_CTRL_REG_RTC_V_OPT 0x80 /* RTC_STATUS_REG bitfields */ #define BIT_RTC_STATUS_REG_RUN_M 0x02 @@ -235,25 +236,57 @@ static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm) unsigned char rtc_data[ALL_TIME_REGS + 1]; int ret; u8 save_control; + u8 rtc_control; ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); - if (ret < 0) + if (ret < 0) { + dev_err(dev, "%s: reading CTRL_REG, error %d\n", __func__, ret); return ret; + } + /* for twl6030/32 make sure BIT_RTC_CTRL_REG_GET_TIME_M is clear */ + if (twl_class_is_6030()) { + if (save_control & BIT_RTC_CTRL_REG_GET_TIME_M) { + save_control &= ~BIT_RTC_CTRL_REG_GET_TIME_M; + ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + if (ret < 0) { + dev_err(dev, "%s clr GET_TIME, error %d\n", + __func__, ret); + return ret; + } + } + } - save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; + /* Copy RTC counting registers to static registers or latches */ + rtc_control = save_control | BIT_RTC_CTRL_REG_GET_TIME_M; - ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); - if (ret < 0) + /* for twl6030/32 enable read access to static shadowed registers */ + if (twl_class_is_6030()) + rtc_control |= BIT_RTC_CTRL_REG_RTC_V_OPT; + + ret = twl_rtc_write_u8(rtc_control, REG_RTC_CTRL_REG); + if (ret < 0) { + dev_err(dev, "%s: writing CTRL_REG, error %d\n", __func__, ret); return ret; + } ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); if (ret < 0) { - dev_err(dev, "rtc_read_time error %d\n", ret); + dev_err(dev, "%s: reading data, error %d\n", __func__, ret); return ret; } + /* for twl6030 restore original state of rtc control register */ + if (twl_class_is_6030()) { + ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + if (ret < 0) { + dev_err(dev, "%s: restore CTRL_REG, error %d\n", + __func__, ret); + return ret; + } + } + tm->tm_sec = bcd2bin(rtc_data[0]); tm->tm_min = bcd2bin(rtc_data[1]); tm->tm_hour = bcd2bin(rtc_data[2]); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index c21871a4e73d..bc2e8a7c265b 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -2844,6 +2844,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( sector_t recid, trkid; unsigned int offs; unsigned int count, count_to_trk_end; + int ret; basedev = block->base; if (rq_data_dir(req) == READ) { @@ -2884,8 +2885,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( itcw = itcw_init(cqr->data, itcw_size, itcw_op, 0, ctidaw, 0); if (IS_ERR(itcw)) { - dasd_sfree_request(cqr, startdev); - return ERR_PTR(-EINVAL); + ret = -EINVAL; + goto out_error; } cqr->cpaddr = itcw_get_tcw(itcw); if (prepare_itcw(itcw, first_trk, last_trk, @@ -2897,8 +2898,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( /* Clock not in sync and XRC is enabled. * Try again later. */ - dasd_sfree_request(cqr, startdev); - return ERR_PTR(-EAGAIN); + ret = -EAGAIN; + goto out_error; } len_to_track_end = 0; /* @@ -2937,8 +2938,10 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( tidaw_flags = 0; last_tidaw = itcw_add_tidaw(itcw, tidaw_flags, dst, part_len); - if (IS_ERR(last_tidaw)) - return ERR_PTR(-EINVAL); + if (IS_ERR(last_tidaw)) { + ret = -EINVAL; + goto out_error; + } dst += part_len; } } @@ -2947,8 +2950,10 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( dst = page_address(bv->bv_page) + bv->bv_offset; last_tidaw = itcw_add_tidaw(itcw, 0x00, dst, bv->bv_len); - if (IS_ERR(last_tidaw)) - return ERR_PTR(-EINVAL); + if (IS_ERR(last_tidaw)) { + ret = -EINVAL; + goto out_error; + } } } last_tidaw->flags |= TIDAW_FLAGS_LAST; @@ -2968,6 +2973,9 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( cqr->buildclk = get_clock(); cqr->status = DASD_CQR_FILLED; return cqr; +out_error: + dasd_sfree_request(cqr, startdev); + return ERR_PTR(ret); } static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index 85f4a9a5d12e..73bef0bd394c 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c @@ -903,7 +903,7 @@ static int ur_set_online(struct ccw_device *cdev) goto fail_urdev_put; } - cdev_init(urd->char_device, &ur_fops); + urd->char_device->ops = &ur_fops; urd->char_device->dev = MKDEV(major, minor); urd->char_device->owner = ur_fops.owner; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 2cfcbffa41fd..386f0c53bea7 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -835,7 +835,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, scsi_eh_restore_cmnd(scmd, &ses); - if (sdrv->eh_action) + if (sdrv && sdrv->eh_action) rtn = sdrv->eh_action(scmd, cmnd, cmnd_size, rtn); return rtn; diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 31bfba805cf4..9b2901feaf78 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -653,7 +653,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n", rx_buf_count); if (t->tx_buf) - dma_unmap_single(NULL, t->tx_dma, t->len, + dma_unmap_single(&spi->dev, t->tx_dma, t->len, DMA_TO_DEVICE); return -ENOMEM; } @@ -692,10 +692,10 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) if (spicfg->io_type == SPI_IO_TYPE_DMA) { if (t->tx_buf) - dma_unmap_single(NULL, t->tx_dma, t->len, + dma_unmap_single(&spi->dev, t->tx_dma, t->len, DMA_TO_DEVICE); - dma_unmap_single(NULL, t->rx_dma, rx_buf_count, + dma_unmap_single(&spi->dev, t->rx_dma, rx_buf_count, DMA_FROM_DEVICE); clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN); diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 24cacff57786..5f748c0d96bd 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -139,10 +139,12 @@ static void fsl_spi_change_mode(struct spi_device *spi) static void fsl_spi_chipselect(struct spi_device *spi, int value) { struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); - struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data; + struct fsl_spi_platform_data *pdata; bool pol = spi->mode & SPI_CS_HIGH; struct spi_mpc8xxx_cs *cs = spi->controller_state; + pdata = spi->dev.parent->parent->platform_data; + if (value == BITBANG_CS_INACTIVE) { if (pdata->cs_control) pdata->cs_control(spi, !pol); diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 31054e3de4c1..570f22053be8 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -83,7 +83,7 @@ struct spi_imx_data { struct spi_bitbang bitbang; struct completion xfer_done; - void *base; + void __iomem *base; int irq; struct clk *clk; unsigned long spi_clk; @@ -766,8 +766,12 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) } ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs); - if (ret < 0) - num_cs = mxc_platform_info->num_chipselect; + if (ret < 0) { + if (mxc_platform_info) + num_cs = mxc_platform_info->num_chipselect; + else + return ret; + } master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data) + sizeof(int) * num_cs); @@ -784,7 +788,7 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) for (i = 0; i < master->num_chipselect; i++) { int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); - if (cs_gpio < 0) + if (cs_gpio < 0 && mxc_platform_info) cs_gpio = mxc_platform_info->chipselect[i]; spi_imx->chipselect[i] = cs_gpio; diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 96f0da66b185..09c925aaf320 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2195,7 +2195,6 @@ static int pl022_runtime_suspend(struct device *dev) struct pl022 *pl022 = dev_get_drvdata(dev); clk_disable(pl022->clk); - amba_vcore_disable(pl022->adev); return 0; } @@ -2204,7 +2203,6 @@ static int pl022_runtime_resume(struct device *dev) { struct pl022 *pl022 = dev_get_drvdata(dev); - amba_vcore_enable(pl022->adev); clk_enable(pl022->clk); return 0; diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 08a3b1133d29..eb1dee26bda3 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -27,13 +27,14 @@ config ANDROID_LOGGER config ANDROID_PERSISTENT_RAM bool + depends on HAVE_MEMBLOCK select REED_SOLOMON select REED_SOLOMON_ENC8 select REED_SOLOMON_DEC8 config ANDROID_RAM_CONSOLE bool "Android RAM buffer console" - depends on !S390 && !UML + depends on !S390 && !UML && HAVE_MEMBLOCK select ANDROID_PERSISTENT_RAM default n diff --git a/drivers/staging/android/persistent_ram.c b/drivers/staging/android/persistent_ram.c index e08f2574e30a..8d8c1e33e0ff 100644 --- a/drivers/staging/android/persistent_ram.c +++ b/drivers/staging/android/persistent_ram.c @@ -399,12 +399,12 @@ static __init struct persistent_ram_zone *__persistent_ram_init(struct device *dev, bool ecc) { struct persistent_ram_zone *prz; - int ret; + int ret = -ENOMEM; prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL); if (!prz) { pr_err("persistent_ram: failed to allocate persistent ram zone\n"); - return ERR_PTR(-ENOMEM); + goto err; } INIT_LIST_HEAD(&prz->node); @@ -412,13 +412,13 @@ struct persistent_ram_zone *__persistent_ram_init(struct device *dev, bool ecc) ret = persistent_ram_buffer_init(dev_name(dev), prz); if (ret) { pr_err("persistent_ram: failed to initialize buffer\n"); - return ERR_PTR(ret); + goto err; } prz->ecc = ecc; ret = persistent_ram_init_ecc(prz, prz->buffer_size); if (ret) - return ERR_PTR(ret); + goto err; if (prz->buffer->sig == PERSISTENT_RAM_SIG) { if (buffer_size(prz) > prz->buffer_size || @@ -442,6 +442,9 @@ struct persistent_ram_zone *__persistent_ram_init(struct device *dev, bool ecc) atomic_set(&prz->buffer->size, 0); return prz; +err: + kfree(prz); + return ERR_PTR(ret); } struct persistent_ram_zone * __init diff --git a/drivers/staging/android/timed_gpio.c b/drivers/staging/android/timed_gpio.c index bc723eff11af..45c522cbe784 100644 --- a/drivers/staging/android/timed_gpio.c +++ b/drivers/staging/android/timed_gpio.c @@ -85,7 +85,7 @@ static int timed_gpio_probe(struct platform_device *pdev) struct timed_gpio_platform_data *pdata = pdev->dev.platform_data; struct timed_gpio *cur_gpio; struct timed_gpio_data *gpio_data, *gpio_dat; - int i, j, ret = 0; + int i, ret; if (!pdata) return -EBUSY; @@ -108,18 +108,12 @@ static int timed_gpio_probe(struct platform_device *pdev) gpio_dat->dev.get_time = gpio_get_time; gpio_dat->dev.enable = gpio_enable; ret = gpio_request(cur_gpio->gpio, cur_gpio->name); - if (ret >= 0) { - ret = timed_output_dev_register(&gpio_dat->dev); - if (ret < 0) - gpio_free(cur_gpio->gpio); - } + if (ret < 0) + goto err_out; + ret = timed_output_dev_register(&gpio_dat->dev); if (ret < 0) { - for (j = 0; j < i; j++) { - timed_output_dev_unregister(&gpio_data[i].dev); - gpio_free(gpio_data[i].gpio); - } - kfree(gpio_data); - return ret; + gpio_free(cur_gpio->gpio); + goto err_out; } gpio_dat->gpio = cur_gpio->gpio; @@ -131,6 +125,15 @@ static int timed_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gpio_data); return 0; + +err_out: + while (--i >= 0) { + timed_output_dev_unregister(&gpio_data[i].dev); + gpio_free(gpio_data[i].gpio); + } + kfree(gpio_data); + + return ret; } static int timed_gpio_remove(struct platform_device *pdev) diff --git a/drivers/staging/iio/inkern.c b/drivers/staging/iio/inkern.c index de2c8ea64965..ef07a02bf542 100644 --- a/drivers/staging/iio/inkern.c +++ b/drivers/staging/iio/inkern.c @@ -82,6 +82,7 @@ int iio_map_array_unregister(struct iio_dev *indio_dev, ret = -ENODEV; goto error_ret; } + i++; } error_ret: mutex_unlock(&iio_map_list_lock); diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c index d5ddac3d8831..ebc2d0840caf 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/staging/iio/magnetometer/ak8975.c @@ -108,7 +108,8 @@ static const int ak8975_index_to_reg[] = { static int ak8975_write_data(struct i2c_client *client, u8 reg, u8 val, u8 mask, u8 shift) { - struct ak8975_data *data = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ak8975_data *data = iio_priv(indio_dev); u8 regval; int ret; @@ -159,7 +160,8 @@ static int ak8975_read_data(struct i2c_client *client, */ static int ak8975_setup(struct i2c_client *client) { - struct ak8975_data *data = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ak8975_data *data = iio_priv(indio_dev); u8 device_id; int ret; @@ -509,6 +511,7 @@ static int ak8975_probe(struct i2c_client *client, goto exit_gpio; } data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); /* Perform some basic start-of-day setup of the device. */ err = ak8975_setup(client); if (err < 0) { @@ -516,7 +519,6 @@ static int ak8975_probe(struct i2c_client *client, goto exit_free_iio; } - i2c_set_clientdata(client, indio_dev); data->client = client; mutex_init(&data->lock); data->eoc_irq = client->irq; diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 91dd3da70cb4..e00b416c4d33 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -521,7 +521,9 @@ static int hmc5843_detect(struct i2c_client *client, /* Called when we have found a new HMC5843. */ static void hmc5843_init_client(struct i2c_client *client) { - struct hmc5843_data *data = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct hmc5843_data *data = iio_priv(indio_dev); + hmc5843_set_meas_conf(client, data->meas_conf); hmc5843_set_rate(client, data->rate); hmc5843_configure(client, data->operating_mode); diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c index 43ebc43e6b9a..1075fb1df0d9 100644 --- a/drivers/staging/media/as102/as102_fw.c +++ b/drivers/staging/media/as102/as102_fw.c @@ -165,7 +165,7 @@ error: int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap) { int errno = -EFAULT; - const struct firmware *firmware; + const struct firmware *firmware = NULL; unsigned char *cmd_buf = NULL; char *fw1, *fw2; struct usb_device *dev = bus_adap->usb_dev; diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index 3df5b4c58ecd..620b8d54223d 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c @@ -803,9 +803,6 @@ static void pdev_shutdown(struct platform_device *device) static int pdev_probe(struct platform_device *device) { DBG("%s", device->name); - if (platform_driver_register(&omap_dmm_driver)) - dev_err(&device->dev, "DMM registration failed\n"); - return drm_platform_init(&omap_drm_driver, device); } @@ -833,6 +830,10 @@ struct platform_driver pdev = { static int __init omap_drm_init(void) { DBG("init"); + if (platform_driver_register(&omap_dmm_driver)) { + /* we can continue on without DMM.. so not fatal */ + dev_err(NULL, "DMM registration failed\n"); + } return platform_driver_register(&pdev); } diff --git a/drivers/staging/ozwpan/TODO b/drivers/staging/ozwpan/TODO index f7a9c122f596..c2d30a7112f3 100644 --- a/drivers/staging/ozwpan/TODO +++ b/drivers/staging/ozwpan/TODO @@ -8,5 +8,7 @@ TODO: - code review by USB developer community. - testing with as many devices as possible. -Please send any patches for this driver to Chris Kelly <ckelly@ozmodevices.com> +Please send any patches for this driver to +Rupesh Gujare <rgujare@ozmodevices.com> +Chris Kelly <ckelly@ozmodevices.com> and Greg Kroah-Hartman <gregkh@linuxfoundation.org>. diff --git a/drivers/staging/ramster/Kconfig b/drivers/staging/ramster/Kconfig index 8b57b87edda4..4af1f8d4b953 100644 --- a/drivers/staging/ramster/Kconfig +++ b/drivers/staging/ramster/Kconfig @@ -1,10 +1,6 @@ -# Dependency on CONFIG_BROKEN is because there is a commit dependency -# on a cleancache naming change to be submitted by Konrad Wilk -# a39c00ded70339603ffe1b0ffdf3ade85bcf009a "Merge branch 'stable/cleancache.v13' -# into linux-next. Once this commit is present, BROKEN can be removed config RAMSTER bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem" - depends on (CLEANCACHE || FRONTSWAP) && CONFIGFS_FS=y && !ZCACHE && !XVMALLOC && !HIGHMEM && BROKEN + depends on (CLEANCACHE || FRONTSWAP) && CONFIGFS_FS=y && !ZCACHE && !XVMALLOC && !HIGHMEM select LZO_COMPRESS select LZO_DECOMPRESS default n diff --git a/drivers/staging/rts_pstor/ms.c b/drivers/staging/rts_pstor/ms.c index 66341dff8c99..f9a4498984cc 100644 --- a/drivers/staging/rts_pstor/ms.c +++ b/drivers/staging/rts_pstor/ms.c @@ -3498,7 +3498,8 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 log_blk++; - for (seg_no = 0; seg_no < sizeof(ms_start_idx)/2; seg_no++) { + for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; + seg_no++) { if (log_blk < ms_start_idx[seg_no+1]) break; } diff --git a/drivers/staging/rts_pstor/rtsx.c b/drivers/staging/rts_pstor/rtsx.c index a7feb3e328a0..1dccd933a7e4 100644 --- a/drivers/staging/rts_pstor/rtsx.c +++ b/drivers/staging/rts_pstor/rtsx.c @@ -1000,6 +1000,11 @@ static int __devinit rtsx_probe(struct pci_dev *pci, rtsx_init_chip(dev->chip); + /* set the supported max_lun and max_id for the scsi host + * NOTE: the minimal value of max_id is 1 */ + host->max_id = 1; + host->max_lun = dev->chip->max_lun; + /* Start up our control thread */ th = kthread_run(rtsx_control_thread, dev, CR_DRIVER_NAME); if (IS_ERR(th)) { diff --git a/drivers/staging/rts_pstor/rtsx_transport.c b/drivers/staging/rts_pstor/rtsx_transport.c index 4e3d2c106af0..9b2e5c99870f 100644 --- a/drivers/staging/rts_pstor/rtsx_transport.c +++ b/drivers/staging/rts_pstor/rtsx_transport.c @@ -335,6 +335,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, int sg_cnt, i, resid; int err = 0; long timeleft; + struct scatterlist *sg_ptr; u32 val = TRIG_DMA; if ((sg == NULL) || (num_sg <= 0) || !offset || !index) @@ -371,7 +372,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, sg_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir); resid = size; - + sg_ptr = sg; chip->sgi = 0; /* Usually the next entry will be @sg@ + 1, but if this sg element * is part of a chained scatterlist, it could jump to the start of @@ -379,14 +380,14 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, * the proper sg */ for (i = 0; i < *index; i++) - sg = sg_next(sg); + sg_ptr = sg_next(sg_ptr); for (i = *index; i < sg_cnt; i++) { dma_addr_t addr; unsigned int len; u8 option; - addr = sg_dma_address(sg); - len = sg_dma_len(sg); + addr = sg_dma_address(sg_ptr); + len = sg_dma_len(sg_ptr); RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n", (unsigned int)addr, len); @@ -415,7 +416,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, if (!resid) break; - sg = sg_next(sg); + sg_ptr = sg_next(sg_ptr); } RTSX_DEBUGP("SG table count = %d\n", chip->sgi); diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c index ad54c2e5c932..f1701bc6e312 100644 --- a/drivers/staging/sep/sep_main.c +++ b/drivers/staging/sep/sep_main.c @@ -3114,7 +3114,7 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) current->pid); if (1 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, &call_status->status)) { - dev_warn(&sep->pdev->dev, + dev_dbg(&sep->pdev->dev, "[PID%d] dcb prep needed before send msg\n", current->pid); error = -EPROTO; @@ -3122,9 +3122,9 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } if (!arg) { - dev_warn(&sep->pdev->dev, + dev_dbg(&sep->pdev->dev, "[PID%d] dcb null arg\n", current->pid); - error = EINVAL; + error = -EINVAL; goto end_function; } diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c index 9fedc442a779..573c80003f0c 100644 --- a/drivers/staging/vme/devices/vme_pio2_core.c +++ b/drivers/staging/vme/devices/vme_pio2_core.c @@ -35,10 +35,10 @@ static int vector[PIO2_CARDS_MAX]; static int vector_num; static int level[PIO2_CARDS_MAX]; static int level_num; -static const char *variant[PIO2_CARDS_MAX]; +static char *variant[PIO2_CARDS_MAX]; static int variant_num; -static int loopback; +static bool loopback; static int pio2_match(struct vme_dev *); static int __devinit pio2_probe(struct vme_dev *); diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index 0ff8d7bbf2a7..774b0d4a7e06 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -655,6 +655,9 @@ bool KeybSetDefaultKey ( return (false); } + if (uKeyLength > MAX_KEY_LEN) + return false; + pTable->KeyTable[MAX_KEY_TABLE-1].bInUse = true; for(ii=0;ii<ETH_ALEN;ii++) pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID[ii] = 0xFF; diff --git a/drivers/staging/vt6656/ioctl.c b/drivers/staging/vt6656/ioctl.c index 1463d76895f0..d59456c29df1 100644 --- a/drivers/staging/vt6656/ioctl.c +++ b/drivers/staging/vt6656/ioctl.c @@ -565,7 +565,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) result = -ENOMEM; break; } - pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC); + pNodeList = kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC); if (pNodeList == NULL) { result = -ENOMEM; break; @@ -601,6 +601,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq) } } if (copy_to_user(pReq->data, pNodeList, sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)))) { + kfree(pNodeList); result = -EFAULT; break; } diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c index 27bb523c8a97..ee62a06a75f4 100644 --- a/drivers/staging/vt6656/key.c +++ b/drivers/staging/vt6656/key.c @@ -684,6 +684,9 @@ BOOL KeybSetDefaultKey( return (FALSE); } + if (uKeyLength > MAX_KEY_LEN) + return false; + pTable->KeyTable[MAX_KEY_TABLE-1].bInUse = TRUE; for (ii = 0; ii < ETH_ALEN; ii++) pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID[ii] = 0xFF; diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 94d5c35e22fb..3650bbff7686 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -61,7 +61,7 @@ XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension, } temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B); /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */ - if ((temp & 0x88) == 0x80) + if (((temp & 0x88) == 0x80) || ((temp & 0x88) == 0x08)) data = 0; /* DDR */ else data = 1; /* DDRII */ diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 2919924213c4..60d4adf99923 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -152,6 +152,7 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) pVBInfo->pXGINew_CR97 = &XG20_CR97; if (ChipType == XG27) { + unsigned char temp; pVBInfo->MCLKData = (struct SiS_MCLKData *) XGI27New_MCLKData; pVBInfo->CR40 = XGI27_cr41; @@ -162,7 +163,13 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) pVBInfo->pCRDE = XG27_CRDE; pVBInfo->pSR40 = &XG27_SR40; pVBInfo->pSR41 = &XG27_SR41; + pVBInfo->SR15 = XG27_SR13; + /*Z11m DDR*/ + temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B); + /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */ + if (((temp & 0x88) == 0x80) || ((temp & 0x88) == 0x08)) + pVBInfo->pXGINew_CR97 = &Z11m_CR97; } if (ChipType >= XG20) { diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index dddf261ed53d..e8d6f674b274 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -33,6 +33,13 @@ static struct XGI_ECLKDataStruct XGI340_ECLKData[] = { {0x5c, 0x23, 0x01, 166} }; +static unsigned char XG27_SR13[4][8] = { + {0x35, 0x45, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR13 */ + {0x41, 0x51, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR14 */ + {0x32, 0x32, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR18 */ + {0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00} /* SR1B */ +}; + static unsigned char XGI340_SR13[4][8] = { {0x35, 0x45, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR13 */ {0x41, 0x51, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR14 */ @@ -71,7 +78,7 @@ static unsigned char XGI27_cr41[24][8] = { {0x20, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0 CR41 */ {0xC4, 0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 1 CR8A */ {0xC4, 0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 2 CR8B */ - {0xB5, 0x13, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 3 CR40[7], + {0xB3, 0x13, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 3 CR40[7], CR99[2:0], CR45[3:0]*/ {0xf0, 0xf5, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 4 CR59 */ @@ -2803,6 +2810,8 @@ static unsigned char XG27_CRDE[2]; static unsigned char XG27_SR40 = 0x04 ; static unsigned char XG27_SR41 = 0x00 ; +static unsigned char Z11m_CR97 = 0x80 ; + static struct XGI330_VCLKDataStruct XGI_VCLKData[] = { /* SR2B,SR2C,SR2D */ {0x1B, 0xE1, 25}, /* 00 (25.175MHz) */ diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index 09caa4f2687e..917461c66014 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -267,33 +267,39 @@ static unsigned long obj_idx_to_offset(struct page *page, return off + obj_idx * class_size; } +static void reset_page(struct page *page) +{ + clear_bit(PG_private, &page->flags); + clear_bit(PG_private_2, &page->flags); + set_page_private(page, 0); + page->mapping = NULL; + page->freelist = NULL; + reset_page_mapcount(page); +} + static void free_zspage(struct page *first_page) { - struct page *nextp, *tmp; + struct page *nextp, *tmp, *head_extra; BUG_ON(!is_first_page(first_page)); BUG_ON(first_page->inuse); - nextp = (struct page *)page_private(first_page); + head_extra = (struct page *)page_private(first_page); - clear_bit(PG_private, &first_page->flags); - clear_bit(PG_private_2, &first_page->flags); - set_page_private(first_page, 0); - first_page->mapping = NULL; - first_page->freelist = NULL; - reset_page_mapcount(first_page); + reset_page(first_page); __free_page(first_page); /* zspage with only 1 system page */ - if (!nextp) + if (!head_extra) return; - list_for_each_entry_safe(nextp, tmp, &nextp->lru, lru) { + list_for_each_entry_safe(nextp, tmp, &head_extra->lru, lru) { list_del(&nextp->lru); - clear_bit(PG_private_2, &nextp->flags); - nextp->index = 0; + reset_page(nextp); __free_page(nextp); } + reset_page(head_extra); + __free_page(head_extra); } /* Initialize a newly allocated zspage */ diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 5b149b466ec8..5c27f7e6c9f1 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -1572,13 +1572,11 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) do { struct uart_8250_port *up; struct uart_port *port; - bool skip; up = list_entry(l, struct uart_8250_port, list); port = &up->port; - skip = pass_counter && up->port.flags & UPF_IIR_ONCE; - if (!skip && port->handle_irq(port)) { + if (port->handle_irq(port)) { handled = 1; end = NULL; } else if (end == NULL) @@ -2037,10 +2035,12 @@ static int serial8250_startup(struct uart_port *port) spin_unlock_irqrestore(&port->lock, flags); /* - * If the interrupt is not reasserted, setup a timer to - * kick the UART on a regular basis. + * If the interrupt is not reasserted, or we otherwise + * don't trust the iir, setup a timer to kick the UART + * on a regular basis. */ - if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) { + if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) || + up->port.flags & UPF_BUG_THRE) { up->bugs |= UART_BUG_THRE; pr_debug("ttyS%d - using backup timer\n", serial_index(port)); diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index da2b0b0a183f..858dca865d6a 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1096,7 +1096,7 @@ static int kt_serial_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_port *port, int idx) { - port->flags |= UPF_IIR_ONCE; + port->flags |= UPF_BUG_THRE; return skip_tx_en_setup(priv, board, port, idx); } @@ -1118,18 +1118,6 @@ pci_xr17c154_setup(struct serial_private *priv, return pci_default_setup(priv, board, port, idx); } -static int try_enable_msi(struct pci_dev *dev) -{ - /* use msi if available, but fallback to legacy otherwise */ - pci_enable_msi(dev); - return 0; -} - -static void disable_msi(struct pci_dev *dev) -{ - pci_disable_msi(dev); -} - #define PCI_VENDOR_ID_SBSMODULARIO 0x124B #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B #define PCI_DEVICE_ID_OCTPRO 0x0001 @@ -1249,9 +1237,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .device = PCI_DEVICE_ID_INTEL_PATSBURG_KT, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .init = try_enable_msi, .setup = kt_serial_setup, - .exit = disable_msi, }, /* * ITE diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 665beb68f670..070b442c1f81 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1041,7 +1041,7 @@ config SERIAL_OMAP config SERIAL_OMAP_CONSOLE bool "Console on OMAP serial port" - depends on SERIAL_OMAP + depends on SERIAL_OMAP=y select SERIAL_CORE_CONSOLE help Select this option if you would like to use omap serial port as diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index e7903751e058..1f0330915d5a 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c @@ -556,7 +556,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res_mem) port->mapbase = res_mem->start; - else if (platp->mapbase) + else if (platp) port->mapbase = platp->mapbase; else return -EINVAL; @@ -564,7 +564,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res_irq) port->irq = res_irq->start; - else if (platp->irq) + else if (platp) port->irq = platp->irq; /* Check platform data first so we can override device node data */ diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 0c65c9e66986..3d569cd68f58 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1946,10 +1946,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) goto unmap; } - /* Ensure interrupts from this UART are masked and cleared */ - writew(0, uap->port.membase + UART011_IMSC); - writew(0xffff, uap->port.membase + UART011_ICR); - uap->vendor = vendor; uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx; @@ -1967,6 +1963,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->port.line = i; pl011_dma_probe(uap); + /* Ensure interrupts from this UART are masked and cleared */ + writew(0, uap->port.membase + UART011_IMSC); + writew(0xffff, uap->port.membase + UART011_ICR); + snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev)); amba_ports[i] = uap; diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index f9a6be7a9bed..3d7e1ee2fa57 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -389,6 +389,8 @@ static void atmel_start_rx(struct uart_port *port) { UART_PUT_CR(port, ATMEL_US_RSTSTA); /* reset status and receiver */ + UART_PUT_CR(port, ATMEL_US_RXEN); + if (atmel_use_dma_rx(port)) { /* enable PDC controller */ UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | @@ -404,6 +406,8 @@ static void atmel_start_rx(struct uart_port *port) */ static void atmel_stop_rx(struct uart_port *port) { + UART_PUT_CR(port, ATMEL_US_RXDIS); + if (atmel_use_dma_rx(port)) { /* disable PDC receive */ UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS); diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 0121486ac4fa..d00b38eb268e 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1381,29 +1381,24 @@ static int serial_omap_probe(struct platform_device *pdev) return -ENODEV; } - if (!request_mem_region(mem->start, resource_size(mem), + if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), pdev->dev.driver->name)) { dev_err(&pdev->dev, "memory region already claimed\n"); return -EBUSY; } dma_rx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); - if (!dma_rx) { - ret = -EINVAL; - goto err; - } + if (!dma_rx) + return -ENXIO; dma_tx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); - if (!dma_tx) { - ret = -EINVAL; - goto err; - } + if (!dma_tx) + return -ENXIO; + + up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL); + if (!up) + return -ENOMEM; - up = kzalloc(sizeof(*up), GFP_KERNEL); - if (up == NULL) { - ret = -ENOMEM; - goto do_release_region; - } up->pdev = pdev; up->port.dev = &pdev->dev; up->port.type = PORT_OMAP; @@ -1423,16 +1418,17 @@ static int serial_omap_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", up->port.line); ret = -ENODEV; - goto err; + goto err_port_line; } sprintf(up->name, "OMAP UART%d", up->port.line); up->port.mapbase = mem->start; - up->port.membase = ioremap(mem->start, resource_size(mem)); + up->port.membase = devm_ioremap(&pdev->dev, mem->start, + resource_size(mem)); if (!up->port.membase) { dev_err(&pdev->dev, "can't ioremap UART\n"); ret = -ENOMEM; - goto err; + goto err_ioremap; } up->port.flags = omap_up_info->flags; @@ -1478,16 +1474,19 @@ static int serial_omap_probe(struct platform_device *pdev) ret = uart_add_one_port(&serial_omap_reg, &up->port); if (ret != 0) - goto do_release_region; + goto err_add_port; pm_runtime_put(&pdev->dev); platform_set_drvdata(pdev, up); return 0; -err: + +err_add_port: + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); +err_ioremap: +err_port_line: dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n", pdev->id, __func__, ret); -do_release_region: - release_mem_region(mem->start, resource_size(mem)); return ret; } @@ -1499,8 +1498,6 @@ static int serial_omap_remove(struct platform_device *dev) pm_runtime_disable(&up->pdev->dev); uart_remove_one_port(&serial_omap_reg, &up->port); pm_qos_remove_request(&up->pm_qos_request); - - kfree(up); } platform_set_drvdata(dev, NULL); diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 08b9962b8fda..bbbec4a74cfb 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -210,6 +210,7 @@ enum { #define CMITC_UARTCLK 192000000 /* 192.0000 MHz */ #define FRI2_64_UARTCLK 64000000 /* 64.0000 MHz */ #define FRI2_48_UARTCLK 48000000 /* 48.0000 MHz */ +#define NTC1_UARTCLK 64000000 /* 64.0000 MHz */ struct pch_uart_buffer { unsigned char *buf; @@ -384,6 +385,12 @@ static int pch_uart_get_uartclk(void) if (cmp && strstr(cmp, "Fish River Island II")) return FRI2_48_UARTCLK; + /* Kontron COMe-mTT10 (nanoETXexpress-TT) */ + cmp = dmi_get_system_info(DMI_BOARD_NAME); + if (cmp && (strstr(cmp, "COMe-mTT") || + strstr(cmp, "nanoETXexpress-TT"))) + return NTC1_UARTCLK; + return DEFAULT_UARTCLK; } @@ -1651,6 +1658,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, } pci_enable_msi(pdev); + pci_set_master(pdev); iobase = pci_resource_start(pdev, 0); mapbase = pci_resource_start(pdev, 1); diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index de249d265bec..d8b0aee35632 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -982,6 +982,7 @@ static void s3c24xx_serial_resetport(struct uart_port *port, ucon &= ucon_mask; wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); + wr_regl(port, S3C2410_ULCON, cfg->ulcon); /* reset both fifos */ wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 3bdd4b19dd06..2156188db4a6 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2932,11 +2932,10 @@ static int __init con_init(void) gotoxy(vc, vc->vc_x, vc->vc_y); csi_J(vc, 0); update_screen(vc); - pr_info("Console: %s %s %dx%d", + pr_info("Console: %s %s %dx%d\n", vc->vc_can_do_color ? "colour" : "mono", display_desc, vc->vc_cols, vc->vc_rows); printable = 1; - printk("\n"); console_unlock(); diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index cbd8f5f80596..76316a33061b 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -2,14 +2,6 @@ # USB device configuration # -menuconfig USB_SUPPORT - bool "USB support" - depends on HAS_IOMEM - default y - ---help--- - This option adds core support for Universal Serial Bus (USB). - You will also need drivers from the following menu to make use of it. - # many non-PCI SOC chips embed OHCI config USB_ARCH_HAS_OHCI boolean @@ -63,6 +55,14 @@ config USB_ARCH_HAS_XHCI boolean default PCI +menuconfig USB_SUPPORT + bool "USB support" + depends on HAS_IOMEM + default y + ---help--- + This option adds core support for Universal Serial Bus (USB). + You will also need drivers from the following menu to make use of it. + if USB_SUPPORT config USB_COMMON diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index f8e2d6d52e5c..9a56635dc19c 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1189,8 +1189,13 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) if (status == 0) { status = usb_suspend_device(udev, msg); - /* Again, ignore errors during system sleep transitions */ - if (!PMSG_IS_AUTO(msg)) + /* + * Ignore errors from non-root-hub devices during + * system sleep transitions. For the most part, + * these devices should go to low power anyway when + * the entire bus is suspended. + */ + if (udev->parent && !PMSG_IS_AUTO(msg)) status = 0; } diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 9d7fc9a39933..140d3e11f212 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1978,6 +1978,18 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) if (status == 0) { usb_set_device_state(rhdev, USB_STATE_SUSPENDED); hcd->state = HC_STATE_SUSPENDED; + + /* Did we race with a root-hub wakeup event? */ + if (rhdev->do_remote_wakeup) { + char buffer[6]; + + status = hcd->driver->hub_status_data(hcd, buffer); + if (status != 0) { + dev_dbg(&rhdev->dev, "suspend raced with wakeup event\n"); + hcd_bus_resume(rhdev, PMSG_AUTO_RESUME); + status = -EBUSY; + } + } } else { spin_lock_irq(&hcd_root_hub_lock); if (!HCD_DEAD(hcd)) { diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 28664eb7f555..a2aa9d652c67 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3163,6 +3163,22 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, if (retval) goto fail; + /* + * Some superspeed devices have finished the link training process + * and attached to a superspeed hub port, but the device descriptor + * got from those devices show they aren't superspeed devices. Warm + * reset the port attached by the devices can fix them. + */ + if ((udev->speed == USB_SPEED_SUPER) && + (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { + dev_err(&udev->dev, "got a wrong device descriptor, " + "warm reset device\n"); + hub_port_reset(hub, port1, udev, + HUB_BH_RESET_TIME, true); + retval = -EINVAL; + goto fail; + } + if (udev->descriptor.bMaxPacketSize0 == 0xff || udev->speed == USB_SPEED_SUPER) i = 512; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index b3bdfede45e6..aed3e07942d4 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -308,7 +308,8 @@ static void sg_complete(struct urb *urb) retval = usb_unlink_urb(io->urbs [i]); if (retval != -EINPROGRESS && retval != -ENODEV && - retval != -EBUSY) + retval != -EBUSY && + retval != -EIDRM) dev_err(&io->dev->dev, "%s, unlink --> %d\n", __func__, retval); @@ -317,7 +318,6 @@ static void sg_complete(struct urb *urb) } spin_lock(&io->lock); } - urb->dev = NULL; /* on the last completion, signal usb_sg_wait() */ io->bytes += urb->actual_length; @@ -524,7 +524,6 @@ void usb_sg_wait(struct usb_sg_request *io) case -ENXIO: /* hc didn't queue this one */ case -EAGAIN: case -ENOMEM: - io->urbs[i]->dev = NULL; retval = 0; yield(); break; @@ -542,7 +541,6 @@ void usb_sg_wait(struct usb_sg_request *io) /* fail any uncompleted urbs */ default: - io->urbs[i]->dev = NULL; io->urbs[i]->status = retval; dev_dbg(&io->dev->dev, "%s, submit --> %d\n", __func__, retval); @@ -593,7 +591,10 @@ void usb_sg_cancel(struct usb_sg_request *io) if (!io->urbs [i]->dev) continue; retval = usb_unlink_urb(io->urbs [i]); - if (retval != -EINPROGRESS && retval != -EBUSY) + if (retval != -EINPROGRESS + && retval != -ENODEV + && retval != -EBUSY + && retval != -EIDRM) dev_warn(&io->dev->dev, "%s, unlink --> %d\n", __func__, retval); } diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 7239a73c1b8c..cd9b3a2cd8a7 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -539,6 +539,10 @@ EXPORT_SYMBOL_GPL(usb_submit_urb); * never submitted, or it was unlinked before, or the hardware is already * finished with it), even if the completion handler has not yet run. * + * The URB must not be deallocated while this routine is running. In + * particular, when a driver calls this routine, it must insure that the + * completion handler cannot deallocate the URB. + * * Unlinking and Endpoint Queues: * * [The behaviors and guarantees described below do not apply to virtual @@ -603,6 +607,10 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb); * with error -EPERM. Thus even if the URB's completion handler always * tries to resubmit, it will not succeed and the URB will become idle. * + * The URB must not be deallocated while this routine is running. In + * particular, when a driver calls this routine, it must insure that the + * completion handler cannot deallocate the URB. + * * This routine may not be used in an interrupt context (such as a bottom * half or a completion handler), or when holding a spinlock, or in other * situations where the caller can't schedule(). @@ -640,6 +648,10 @@ EXPORT_SYMBOL_GPL(usb_kill_urb); * with error -EPERM. Thus even if the URB's completion handler always * tries to resubmit, it will not succeed and the URB will become idle. * + * The URB must not be deallocated while this routine is running. In + * particular, when a driver calls this routine, it must insure that the + * completion handler cannot deallocate the URB. + * * This routine may not be used in an interrupt context (such as a bottom * half or a completion handler), or when holding a spinlock, or in other * situations where the caller can't schedule(). diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 8793f32bab11..e58b16442971 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1574,7 +1574,6 @@ static void destroy_ep_files (struct dev_data *dev) DBG (dev, "%s %d\n", __func__, dev->state); /* dev->state must prevent interference */ -restart: spin_lock_irq (&dev->lock); while (!list_empty(&dev->epfiles)) { struct ep_data *ep; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 057cdda7a489..806cc95317aa 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -347,6 +347,8 @@ static int ehci_reset (struct ehci_hcd *ehci) if (ehci->debug) dbgp_external_startup(); + ehci->port_c_suspend = ehci->suspended_ports = + ehci->resuming_ports = 0; return retval; } @@ -939,6 +941,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) * like usb_port_resume() does. */ ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); + set_bit(i, &ehci->resuming_ports); ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); mod_timer(&hcd->rh_timer, ehci->reset_done[i]); } diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 256fbd42e48c..38fe07623152 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -223,15 +223,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) * remote wakeup, we must fail the suspend. */ if (hcd->self.root_hub->do_remote_wakeup) { - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - if (ehci->reset_done[port] != 0) { - spin_unlock_irq(&ehci->lock); - ehci_dbg(ehci, "suspend failed because " - "port %d is resuming\n", - port + 1); - return -EBUSY; - } + if (ehci->resuming_ports) { + spin_unlock_irq(&ehci->lock); + ehci_dbg(ehci, "suspend failed because a port is resuming\n"); + return -EBUSY; } } @@ -554,16 +549,12 @@ static int ehci_hub_status_data (struct usb_hcd *hcd, char *buf) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 temp, status = 0; + u32 temp, status; u32 mask; int ports, i, retval = 1; unsigned long flags; u32 ppcd = 0; - /* if !USB_SUSPEND, root hub timers won't get shut down ... */ - if (ehci->rh_state != EHCI_RH_RUNNING) - return 0; - /* init status to no-changes */ buf [0] = 0; ports = HCS_N_PORTS (ehci->hcs_params); @@ -572,6 +563,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) retval++; } + /* Inform the core about resumes-in-progress by returning + * a non-zero value even if there are no status changes. + */ + status = ehci->resuming_ports; + /* Some boards (mostly VIA?) report bogus overcurrent indications, * causing massive log spam unless we completely ignore them. It * may be relevant that VIA VT8235 controllers, where PORT_POWER is @@ -846,6 +842,7 @@ static int ehci_hub_control ( ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESUME), status_reg); + clear_bit(wIndex, &ehci->resuming_ports); retval = handshake(ehci, status_reg, PORT_RESUME, 0, 2000 /* 2msec */); if (retval != 0) { @@ -864,6 +861,7 @@ static int ehci_hub_control ( ehci->reset_done[wIndex])) { status |= USB_PORT_STAT_C_RESET << 16; ehci->reset_done [wIndex] = 0; + clear_bit(wIndex, &ehci->resuming_ports); /* force reset to complete */ ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET), @@ -884,8 +882,10 @@ static int ehci_hub_control ( ehci_readl(ehci, status_reg)); } - if (!(temp & (PORT_RESUME|PORT_RESET))) + if (!(temp & (PORT_RESUME|PORT_RESET))) { ehci->reset_done[wIndex] = 0; + clear_bit(wIndex, &ehci->resuming_ports); + } /* transfer dedicated ports to the companion hc */ if ((temp & PORT_CONNECT) && @@ -920,6 +920,7 @@ static int ehci_hub_control ( status |= USB_PORT_STAT_SUSPEND; } else if (test_bit(wIndex, &ehci->suspended_ports)) { clear_bit(wIndex, &ehci->suspended_ports); + clear_bit(wIndex, &ehci->resuming_ports); ehci->reset_done[wIndex] = 0; if (temp & PORT_PE) set_bit(wIndex, &ehci->port_c_suspend); diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 3de48a2d7955..73544bd440bd 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -224,6 +224,7 @@ static int tegra_ehci_hub_control( temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); /* start resume signalling */ ehci_writel(ehci, temp | PORT_RESUME, status_reg); + set_bit(wIndex-1, &ehci->resuming_ports); spin_unlock_irqrestore(&ehci->lock, flags); msleep(20); @@ -236,6 +237,7 @@ static int tegra_ehci_hub_control( pr_err("%s: timeout waiting for SUSPEND\n", __func__); ehci->reset_done[wIndex-1] = 0; + clear_bit(wIndex-1, &ehci->resuming_ports); tegra->port_resuming = 1; goto done; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 8f9acbc96fde..2694ed6558d2 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -117,6 +117,8 @@ struct ehci_hcd { /* one per controller */ the change-suspend feature turned on */ unsigned long suspended_ports; /* which ports are suspended */ + unsigned long resuming_ports; /* which ports have + started to resume */ /* per-HC memory pools (could be per-bus, but ...) */ struct dma_pool *qh_pool; /* qh per active urb */ diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 11de5f1be981..32dada8c8b4f 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -825,9 +825,13 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) } } - /* Disable any BIOS SMIs */ - writel(XHCI_LEGACY_DISABLE_SMI, - base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); + val = readl(base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); + /* Mask off (turn off) any enabled SMIs */ + val &= XHCI_LEGACY_DISABLE_SMI; + /* Mask all SMI events bits, RW1C */ + val |= XHCI_LEGACY_SMI_EVENTS; + /* Disable any BIOS SMIs and clear all SMI events*/ + writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); if (usb_is_intel_switchable_xhci(pdev)) usb_enable_xhci_ports(pdev); diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 045cde4cbc3d..768d54295a20 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -196,11 +196,12 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) status = get_hub_status_data(uhci, buf); switch (uhci->rh_state) { - case UHCI_RH_SUSPENDING: case UHCI_RH_SUSPENDED: /* if port change, ask to be resumed */ - if (status || uhci->resuming_ports) + if (status || uhci->resuming_ports) { + status = 1; usb_hcd_resume_root_hub(hcd); + } break; case UHCI_RH_AUTO_STOPPED: diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index e9b0f043455d..4b436f5a4171 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -119,7 +119,7 @@ static void xhci_print_command_reg(struct xhci_hcd *xhci) xhci_dbg(xhci, " Event Interrupts %s\n", (temp & CMD_EIE) ? "enabled " : "disabled"); xhci_dbg(xhci, " Host System Error Interrupts %s\n", - (temp & CMD_EIE) ? "enabled " : "disabled"); + (temp & CMD_HSEIE) ? "enabled " : "disabled"); xhci_dbg(xhci, " HC has %sfinished light reset\n", (temp & CMD_LRESET) ? "not " : ""); } diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h index c7f33123d4c0..377f4242dabb 100644 --- a/drivers/usb/host/xhci-ext-caps.h +++ b/drivers/usb/host/xhci-ext-caps.h @@ -62,8 +62,9 @@ /* USB Legacy Support Control and Status Register - section 7.1.2 */ /* Add this offset, plus the value of xECP in HCCPARAMS to the base address */ #define XHCI_LEGACY_CONTROL_OFFSET (0x04) -/* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */ -#define XHCI_LEGACY_DISABLE_SMI ((0x3 << 1) + (0xff << 5) + (0x7 << 17)) +/* bits 1:3, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */ +#define XHCI_LEGACY_DISABLE_SMI ((0x7 << 1) + (0xff << 5) + (0x7 << 17)) +#define XHCI_LEGACY_SMI_EVENTS (0x7 << 29) /* USB 2.0 xHCI 0.96 L1C capability - section 7.2.2.1.3.2 */ #define XHCI_L1C (1 << 16) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index cae4c6f2845a..68eaa908ac8e 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1796,11 +1796,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) int i; /* Free the Event Ring Segment Table and the actual Event Ring */ - if (xhci->ir_set) { - xhci_writel(xhci, 0, &xhci->ir_set->erst_size); - xhci_write_64(xhci, 0, &xhci->ir_set->erst_base); - xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue); - } size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); if (xhci->erst.entries) dma_free_coherent(&pdev->dev, size, @@ -1812,7 +1807,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->event_ring = NULL; xhci_dbg(xhci, "Freed event ring\n"); - xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring); if (xhci->cmd_ring) xhci_ring_free(xhci, xhci->cmd_ring); xhci->cmd_ring = NULL; @@ -1841,7 +1835,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->medium_streams_pool = NULL; xhci_dbg(xhci, "Freed medium stream array pool\n"); - xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr); if (xhci->dcbaa) dma_free_coherent(&pdev->dev, sizeof(*xhci->dcbaa), xhci->dcbaa, xhci->dcbaa->dma); @@ -2459,6 +2452,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) fail: xhci_warn(xhci, "Couldn't initialize memory\n"); + xhci_halt(xhci); + xhci_reset(xhci); xhci_mem_cleanup(xhci); return -ENOMEM; } diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index ef98b38626fb..7a856a767e77 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -95,6 +95,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_RESET_ON_RESUME; xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); } + if (pdev->vendor == PCI_VENDOR_ID_VIA) + xhci->quirks |= XHCI_RESET_ON_RESUME; } /* called during probe() after chip reset completes */ @@ -326,7 +328,7 @@ int __init xhci_register_pci(void) return pci_register_driver(&xhci_pci_driver); } -void __exit xhci_unregister_pci(void) +void xhci_unregister_pci(void) { pci_unregister_driver(&xhci_pci_driver); } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 6bd9d53062eb..3d9422f16a20 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2417,7 +2417,7 @@ hw_died: u32 irq_pending; /* Acknowledge the PCI interrupt */ irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); - irq_pending |= 0x3; + irq_pending |= IMAN_IP; xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending); } @@ -2734,7 +2734,7 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, urb->dev->speed == USB_SPEED_FULL) urb->interval /= 8; } - return xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); + return xhci_queue_bulk_tx(xhci, mem_flags, urb, slot_id, ep_index); } /* @@ -3514,7 +3514,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, } ep_ring->num_trbs_free_temp = ep_ring->num_trbs_free; - return xhci_queue_isoc_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); + return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index); } /**** Command Ring Operations ****/ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index e1963d4a430f..36641a7f2371 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -106,6 +106,9 @@ int xhci_halt(struct xhci_hcd *xhci) STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); if (!ret) xhci->xhc_state |= XHCI_STATE_HALTED; + else + xhci_warn(xhci, "Host not halted after %u microseconds.\n", + XHCI_MAX_HALT_USEC); return ret; } @@ -664,11 +667,11 @@ static void xhci_save_registers(struct xhci_hcd *xhci) xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification); xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg); - xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); - xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control); xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size); xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base); xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); + xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); + xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control); } static void xhci_restore_registers(struct xhci_hcd *xhci) @@ -677,10 +680,11 @@ static void xhci_restore_registers(struct xhci_hcd *xhci) xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification); xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr); xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg); - xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending); - xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control); xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size); xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base); + xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue); + xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending); + xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control); } static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 91074fdab3eb..3d69c4b2b542 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -205,6 +205,10 @@ struct xhci_op_regs { #define CMD_PM_INDEX (1 << 11) /* bits 12:31 are reserved (and should be preserved on writes). */ +/* IMAN - Interrupt Management Register */ +#define IMAN_IP (1 << 1) +#define IMAN_IE (1 << 0) + /* USBSTS - USB status - status bitmasks */ /* HC not running - set to 1 when run/stop bit is cleared. */ #define STS_HALT XHCI_STS_HALT diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 7f547dc3a590..ed8adb052ca7 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -60,8 +60,6 @@ static int usb_serial_device_probe(struct device *dev) retval = -ENODEV; goto exit; } - if (port->dev_state != PORT_REGISTERING) - goto exit; driver = port->serial->type; if (driver->port_probe) { @@ -98,9 +96,6 @@ static int usb_serial_device_remove(struct device *dev) if (!port) return -ENODEV; - if (port->dev_state != PORT_UNREGISTERING) - return retval; - device_remove_file(&port->dev, &dev_attr_port_number); driver = port->serial->type; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ff8605b4b4be..02e7f2d32d52 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -75,7 +75,8 @@ struct ftdi_private { unsigned long last_dtr_rts; /* saved modem control outputs */ struct async_icount icount; wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ - char prev_status, diff_status; /* Used for TIOCMIWAIT */ + char prev_status; /* Used for TIOCMIWAIT */ + bool dev_gone; /* Used to abort TIOCMIWAIT */ char transmit_empty; /* If transmitter is empty or not */ struct usb_serial_port *port; __u16 interface; /* FT2232C, FT2232H or FT4232H port interface @@ -1681,6 +1682,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) init_waitqueue_head(&priv->delta_msr_wait); priv->flags = ASYNC_LOW_LATENCY; + priv->dev_gone = false; if (quirk && quirk->port_probe) quirk->port_probe(priv); @@ -1839,6 +1841,9 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) dbg("%s", __func__); + priv->dev_gone = true; + wake_up_interruptible_all(&priv->delta_msr_wait); + remove_sysfs_attrs(port); kref_put(&priv->kref, ftdi_sio_priv_release); @@ -1982,17 +1987,19 @@ static int ftdi_process_packet(struct tty_struct *tty, N.B. packet may be processed more than once, but differences are only processed once. */ status = packet[0] & FTDI_STATUS_B0_MASK; - if (status & FTDI_RS0_CTS) - priv->icount.cts++; - if (status & FTDI_RS0_DSR) - priv->icount.dsr++; - if (status & FTDI_RS0_RI) - priv->icount.rng++; - if (status & FTDI_RS0_RLSD) - priv->icount.dcd++; if (status != priv->prev_status) { - priv->diff_status |= status ^ priv->prev_status; - wake_up_interruptible(&priv->delta_msr_wait); + char diff_status = status ^ priv->prev_status; + + if (diff_status & FTDI_RS0_CTS) + priv->icount.cts++; + if (diff_status & FTDI_RS0_DSR) + priv->icount.dsr++; + if (diff_status & FTDI_RS0_RI) + priv->icount.rng++; + if (diff_status & FTDI_RS0_RLSD) + priv->icount.dcd++; + + wake_up_interruptible_all(&priv->delta_msr_wait); priv->prev_status = status; } @@ -2395,15 +2402,12 @@ static int ftdi_ioctl(struct tty_struct *tty, */ case TIOCMIWAIT: cprev = priv->icount; - while (1) { + while (!priv->dev_gone) { interruptible_sleep_on(&priv->delta_msr_wait); /* see if a signal did it */ if (signal_pending(current)) return -ERESTARTSYS; cnow = priv->icount; - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || @@ -2412,7 +2416,7 @@ static int ftdi_ioctl(struct tty_struct *tty, } cprev = cnow; } - /* not reached */ + return -EIO; break; case TIOCSERGETLSR: return get_lsr_info(port, (struct serial_struct __user *)arg); diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 6e1622f2a297..08d16e8c002d 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -27,8 +27,8 @@ /* Product information. */ #define FOCUS_VENDOR_ID 0x0C2E -#define FOCUS_PRODUCT_ID 0x0720 -#define FOCUS_PRODUCT_ID_UNI 0x0710 +#define FOCUS_PRODUCT_ID_BI 0x0720 +#define FOCUS_PRODUCT_ID_UNI 0x0700 #define METROUSB_SET_REQUEST_TYPE 0x40 #define METROUSB_SET_MODEM_CTRL_REQUEST 10 @@ -47,7 +47,7 @@ struct metrousb_private { /* Device table list. */ static struct usb_device_id id_table[] = { - { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID) }, + { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_BI) }, { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) }, { }, /* Terminating entry. */ }; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 836cfa9a515f..f4465ccddc35 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -708,6 +708,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5) }, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index ff4a174fa5de..a1a9062954c4 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -420,7 +420,7 @@ static void pl2303_set_termios(struct tty_struct *tty, control = priv->line_control; if ((cflag & CBAUD) == B0) priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); - else + else if ((old_termios->c_cflag & CBAUD) == B0) priv->line_control |= (CONTROL_DTR | CONTROL_RTS); if (control != priv->line_control) { control = priv->line_control; diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index f14465a83dd1..fdd5aa2c8d82 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -289,6 +289,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881 U */ { USB_DEVICE(0x1199, 0x6859) }, /* Sierra Wireless AirCard 885 E */ { USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */ + { USB_DEVICE(0x1199, 0x68A2) }, /* Sierra Wireless MC7710 */ /* Sierra Wireless C885 */ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)}, /* Sierra Wireless C888, Air Card 501, USB 303, USB 304 */ diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 69230f01056a..97355a15bbea 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1059,6 +1059,12 @@ int usb_serial_probe(struct usb_interface *interface, serial->attached = 1; } + /* Avoid race with tty_open and serial_install by setting the + * disconnected flag and not clearing it until all ports have been + * registered. + */ + serial->disconnected = 1; + if (get_free_serial(serial, num_ports, &minor) == NULL) { dev_err(&interface->dev, "No more free serial devices\n"); goto probe_error; @@ -1070,19 +1076,16 @@ int usb_serial_probe(struct usb_interface *interface, port = serial->port[i]; dev_set_name(&port->dev, "ttyUSB%d", port->number); dbg ("%s - registering %s", __func__, dev_name(&port->dev)); - port->dev_state = PORT_REGISTERING; device_enable_async_suspend(&port->dev); retval = device_add(&port->dev); - if (retval) { + if (retval) dev_err(&port->dev, "Error registering port device, " "continuing\n"); - port->dev_state = PORT_UNREGISTERED; - } else { - port->dev_state = PORT_REGISTERED; - } } + serial->disconnected = 0; + usb_serial_console_init(debug, minor); exit: @@ -1124,22 +1127,8 @@ void usb_serial_disconnect(struct usb_interface *interface) } kill_traffic(port); cancel_work_sync(&port->work); - if (port->dev_state == PORT_REGISTERED) { - - /* Make sure the port is bound so that the - * driver's port_remove method is called. - */ - if (!port->dev.driver) { - int rc; - - port->dev.driver = - &serial->type->driver; - rc = device_bind_driver(&port->dev); - } - port->dev_state = PORT_UNREGISTERING; + if (device_is_registered(&port->dev)) device_del(&port->dev); - port->dev_state = PORT_UNREGISTERED; - } } } serial->type->disconnect(serial); diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index c18538e4a6db..2653e73db623 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -132,6 +132,35 @@ static struct us_unusual_dev for_dynamic_ids = #undef COMPLIANT_DEV #undef USUAL_DEV +#ifdef CONFIG_LOCKDEP + +static struct lock_class_key us_interface_key[USB_MAXINTERFACES]; + +static void us_set_lock_class(struct mutex *mutex, + struct usb_interface *intf) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct usb_host_config *config = udev->actconfig; + int i; + + for (i = 0; i < config->desc.bNumInterfaces; i++) { + if (config->interface[i] == intf) + break; + } + + BUG_ON(i == config->desc.bNumInterfaces); + + lockdep_set_class(mutex, &us_interface_key[i]); +} + +#else + +static void us_set_lock_class(struct mutex *mutex, + struct usb_interface *intf) +{ +} + +#endif #ifdef CONFIG_PM /* Minimal support for suspend and resume */ @@ -895,6 +924,7 @@ int usb_stor_probe1(struct us_data **pus, *pus = us = host_to_us(host); memset(us, 0, sizeof(struct us_data)); mutex_init(&(us->dev_mutex)); + us_set_lock_class(&us->dev_mutex, intf); init_completion(&us->cmnd_ready); init_completion(&(us->notify)); init_waitqueue_head(&us->delay_wait); diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c index fc9a1d75281f..3de00d9fae2e 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -155,7 +155,7 @@ static int vhost_test_release(struct inode *inode, struct file *f) vhost_test_stop(n, &private); vhost_test_flush(n); - vhost_dev_cleanup(&n->dev); + vhost_dev_cleanup(&n->dev, false); /* We do an extra flush before freeing memory, * since jobs can re-queue themselves. */ vhost_test_flush(n); diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index befcbd8ef019..ffbce4525468 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -499,7 +499,8 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev) au1100fb_fix.mmio_start = regs_res->start; au1100fb_fix.mmio_len = resource_size(regs_res); - if (!devm_request_mem_region(au1100fb_fix.mmio_start, + if (!devm_request_mem_region(&dev->dev, + au1100fb_fix.mmio_start, au1100fb_fix.mmio_len, DRIVER_NAME)) { print_err("fail to lock memory region at 0x%08lx", @@ -516,7 +517,7 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev) fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; - fbdev->fb_mem = dmam_alloc_coherent(&dev->dev, &dev->dev, + fbdev->fb_mem = dmam_alloc_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), &fbdev->fb_phys, GFP_KERNEL); if (!fbdev->fb_mem) { diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 3e9a773db09f..7ca79f02056e 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -1724,7 +1724,7 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev) /* Allocate the framebuffer to the maximum screen size */ fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; - fbdev->fb_mem = dmam_alloc_noncoherent(&dev->dev, &dev->dev, + fbdev->fb_mem = dmam_alloc_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), &fbdev->fb_phys, GFP_KERNEL); if (!fbdev->fb_mem) { diff --git a/drivers/video/kyro/STG4000Reg.h b/drivers/video/kyro/STG4000Reg.h index 5d6269882589..50f4670e9252 100644 --- a/drivers/video/kyro/STG4000Reg.h +++ b/drivers/video/kyro/STG4000Reg.h @@ -73,210 +73,210 @@ typedef enum _OVRL_PIX_FORMAT { /* Register Table */ typedef struct { /* 0h */ - volatile unsigned long Thread0Enable; /* 0x0000 */ - volatile unsigned long Thread1Enable; /* 0x0004 */ - volatile unsigned long Thread0Recover; /* 0x0008 */ - volatile unsigned long Thread1Recover; /* 0x000C */ - volatile unsigned long Thread0Step; /* 0x0010 */ - volatile unsigned long Thread1Step; /* 0x0014 */ - volatile unsigned long VideoInStatus; /* 0x0018 */ - volatile unsigned long Core2InSignStart; /* 0x001C */ - volatile unsigned long Core1ResetVector; /* 0x0020 */ - volatile unsigned long Core1ROMOffset; /* 0x0024 */ - volatile unsigned long Core1ArbiterPriority; /* 0x0028 */ - volatile unsigned long VideoInControl; /* 0x002C */ - volatile unsigned long VideoInReg0CtrlA; /* 0x0030 */ - volatile unsigned long VideoInReg0CtrlB; /* 0x0034 */ - volatile unsigned long VideoInReg1CtrlA; /* 0x0038 */ - volatile unsigned long VideoInReg1CtrlB; /* 0x003C */ - volatile unsigned long Thread0Kicker; /* 0x0040 */ - volatile unsigned long Core2InputSign; /* 0x0044 */ - volatile unsigned long Thread0ProgCtr; /* 0x0048 */ - volatile unsigned long Thread1ProgCtr; /* 0x004C */ - volatile unsigned long Thread1Kicker; /* 0x0050 */ - volatile unsigned long GPRegister1; /* 0x0054 */ - volatile unsigned long GPRegister2; /* 0x0058 */ - volatile unsigned long GPRegister3; /* 0x005C */ - volatile unsigned long GPRegister4; /* 0x0060 */ - volatile unsigned long SerialIntA; /* 0x0064 */ - - volatile unsigned long Fill0[6]; /* GAP 0x0068 - 0x007C */ - - volatile unsigned long SoftwareReset; /* 0x0080 */ - volatile unsigned long SerialIntB; /* 0x0084 */ - - volatile unsigned long Fill1[37]; /* GAP 0x0088 - 0x011C */ - - volatile unsigned long ROMELQV; /* 0x011C */ - volatile unsigned long WLWH; /* 0x0120 */ - volatile unsigned long ROMELWL; /* 0x0124 */ - - volatile unsigned long dwFill_1; /* GAP 0x0128 */ - - volatile unsigned long IntStatus; /* 0x012C */ - volatile unsigned long IntMask; /* 0x0130 */ - volatile unsigned long IntClear; /* 0x0134 */ - - volatile unsigned long Fill2[6]; /* GAP 0x0138 - 0x014C */ - - volatile unsigned long ROMGPIOA; /* 0x0150 */ - volatile unsigned long ROMGPIOB; /* 0x0154 */ - volatile unsigned long ROMGPIOC; /* 0x0158 */ - volatile unsigned long ROMGPIOD; /* 0x015C */ - - volatile unsigned long Fill3[2]; /* GAP 0x0160 - 0x0168 */ - - volatile unsigned long AGPIntID; /* 0x0168 */ - volatile unsigned long AGPIntClassCode; /* 0x016C */ - volatile unsigned long AGPIntBIST; /* 0x0170 */ - volatile unsigned long AGPIntSSID; /* 0x0174 */ - volatile unsigned long AGPIntPMCSR; /* 0x0178 */ - volatile unsigned long VGAFrameBufBase; /* 0x017C */ - volatile unsigned long VGANotify; /* 0x0180 */ - volatile unsigned long DACPLLMode; /* 0x0184 */ - volatile unsigned long Core1VideoClockDiv; /* 0x0188 */ - volatile unsigned long AGPIntStat; /* 0x018C */ + volatile u32 Thread0Enable; /* 0x0000 */ + volatile u32 Thread1Enable; /* 0x0004 */ + volatile u32 Thread0Recover; /* 0x0008 */ + volatile u32 Thread1Recover; /* 0x000C */ + volatile u32 Thread0Step; /* 0x0010 */ + volatile u32 Thread1Step; /* 0x0014 */ + volatile u32 VideoInStatus; /* 0x0018 */ + volatile u32 Core2InSignStart; /* 0x001C */ + volatile u32 Core1ResetVector; /* 0x0020 */ + volatile u32 Core1ROMOffset; /* 0x0024 */ + volatile u32 Core1ArbiterPriority; /* 0x0028 */ + volatile u32 VideoInControl; /* 0x002C */ + volatile u32 VideoInReg0CtrlA; /* 0x0030 */ + volatile u32 VideoInReg0CtrlB; /* 0x0034 */ + volatile u32 VideoInReg1CtrlA; /* 0x0038 */ + volatile u32 VideoInReg1CtrlB; /* 0x003C */ + volatile u32 Thread0Kicker; /* 0x0040 */ + volatile u32 Core2InputSign; /* 0x0044 */ + volatile u32 Thread0ProgCtr; /* 0x0048 */ + volatile u32 Thread1ProgCtr; /* 0x004C */ + volatile u32 Thread1Kicker; /* 0x0050 */ + volatile u32 GPRegister1; /* 0x0054 */ + volatile u32 GPRegister2; /* 0x0058 */ + volatile u32 GPRegister3; /* 0x005C */ + volatile u32 GPRegister4; /* 0x0060 */ + volatile u32 SerialIntA; /* 0x0064 */ + + volatile u32 Fill0[6]; /* GAP 0x0068 - 0x007C */ + + volatile u32 SoftwareReset; /* 0x0080 */ + volatile u32 SerialIntB; /* 0x0084 */ + + volatile u32 Fill1[37]; /* GAP 0x0088 - 0x011C */ + + volatile u32 ROMELQV; /* 0x011C */ + volatile u32 WLWH; /* 0x0120 */ + volatile u32 ROMELWL; /* 0x0124 */ + + volatile u32 dwFill_1; /* GAP 0x0128 */ + + volatile u32 IntStatus; /* 0x012C */ + volatile u32 IntMask; /* 0x0130 */ + volatile u32 IntClear; /* 0x0134 */ + + volatile u32 Fill2[6]; /* GAP 0x0138 - 0x014C */ + + volatile u32 ROMGPIOA; /* 0x0150 */ + volatile u32 ROMGPIOB; /* 0x0154 */ + volatile u32 ROMGPIOC; /* 0x0158 */ + volatile u32 ROMGPIOD; /* 0x015C */ + + volatile u32 Fill3[2]; /* GAP 0x0160 - 0x0168 */ + + volatile u32 AGPIntID; /* 0x0168 */ + volatile u32 AGPIntClassCode; /* 0x016C */ + volatile u32 AGPIntBIST; /* 0x0170 */ + volatile u32 AGPIntSSID; /* 0x0174 */ + volatile u32 AGPIntPMCSR; /* 0x0178 */ + volatile u32 VGAFrameBufBase; /* 0x017C */ + volatile u32 VGANotify; /* 0x0180 */ + volatile u32 DACPLLMode; /* 0x0184 */ + volatile u32 Core1VideoClockDiv; /* 0x0188 */ + volatile u32 AGPIntStat; /* 0x018C */ /* - volatile unsigned long Fill4[0x0400/4 - 0x0190/4]; //GAP 0x0190 - 0x0400 - volatile unsigned long Fill5[0x05FC/4 - 0x0400/4]; //GAP 0x0400 - 0x05FC Fog Table - volatile unsigned long Fill6[0x0604/4 - 0x0600/4]; //GAP 0x0600 - 0x0604 - volatile unsigned long Fill7[0x0680/4 - 0x0608/4]; //GAP 0x0608 - 0x0680 - volatile unsigned long Fill8[0x07FC/4 - 0x0684/4]; //GAP 0x0684 - 0x07FC + volatile u32 Fill4[0x0400/4 - 0x0190/4]; //GAP 0x0190 - 0x0400 + volatile u32 Fill5[0x05FC/4 - 0x0400/4]; //GAP 0x0400 - 0x05FC Fog Table + volatile u32 Fill6[0x0604/4 - 0x0600/4]; //GAP 0x0600 - 0x0604 + volatile u32 Fill7[0x0680/4 - 0x0608/4]; //GAP 0x0608 - 0x0680 + volatile u32 Fill8[0x07FC/4 - 0x0684/4]; //GAP 0x0684 - 0x07FC */ - volatile unsigned long Fill4[412]; /* 0x0190 - 0x07FC */ - - volatile unsigned long TACtrlStreamBase; /* 0x0800 */ - volatile unsigned long TAObjDataBase; /* 0x0804 */ - volatile unsigned long TAPtrDataBase; /* 0x0808 */ - volatile unsigned long TARegionDataBase; /* 0x080C */ - volatile unsigned long TATailPtrBase; /* 0x0810 */ - volatile unsigned long TAPtrRegionSize; /* 0x0814 */ - volatile unsigned long TAConfiguration; /* 0x0818 */ - volatile unsigned long TAObjDataStartAddr; /* 0x081C */ - volatile unsigned long TAObjDataEndAddr; /* 0x0820 */ - volatile unsigned long TAXScreenClip; /* 0x0824 */ - volatile unsigned long TAYScreenClip; /* 0x0828 */ - volatile unsigned long TARHWClamp; /* 0x082C */ - volatile unsigned long TARHWCompare; /* 0x0830 */ - volatile unsigned long TAStart; /* 0x0834 */ - volatile unsigned long TAObjReStart; /* 0x0838 */ - volatile unsigned long TAPtrReStart; /* 0x083C */ - volatile unsigned long TAStatus1; /* 0x0840 */ - volatile unsigned long TAStatus2; /* 0x0844 */ - volatile unsigned long TAIntStatus; /* 0x0848 */ - volatile unsigned long TAIntMask; /* 0x084C */ - - volatile unsigned long Fill5[235]; /* GAP 0x0850 - 0x0BF8 */ - - volatile unsigned long TextureAddrThresh; /* 0x0BFC */ - volatile unsigned long Core1Translation; /* 0x0C00 */ - volatile unsigned long TextureAddrReMap; /* 0x0C04 */ - volatile unsigned long RenderOutAGPRemap; /* 0x0C08 */ - volatile unsigned long _3DRegionReadTrans; /* 0x0C0C */ - volatile unsigned long _3DPtrReadTrans; /* 0x0C10 */ - volatile unsigned long _3DParamReadTrans; /* 0x0C14 */ - volatile unsigned long _3DRegionReadThresh; /* 0x0C18 */ - volatile unsigned long _3DPtrReadThresh; /* 0x0C1C */ - volatile unsigned long _3DParamReadThresh; /* 0x0C20 */ - volatile unsigned long _3DRegionReadAGPRemap; /* 0x0C24 */ - volatile unsigned long _3DPtrReadAGPRemap; /* 0x0C28 */ - volatile unsigned long _3DParamReadAGPRemap; /* 0x0C2C */ - volatile unsigned long ZBufferAGPRemap; /* 0x0C30 */ - volatile unsigned long TAIndexAGPRemap; /* 0x0C34 */ - volatile unsigned long TAVertexAGPRemap; /* 0x0C38 */ - volatile unsigned long TAUVAddrTrans; /* 0x0C3C */ - volatile unsigned long TATailPtrCacheTrans; /* 0x0C40 */ - volatile unsigned long TAParamWriteTrans; /* 0x0C44 */ - volatile unsigned long TAPtrWriteTrans; /* 0x0C48 */ - volatile unsigned long TAParamWriteThresh; /* 0x0C4C */ - volatile unsigned long TAPtrWriteThresh; /* 0x0C50 */ - volatile unsigned long TATailPtrCacheAGPRe; /* 0x0C54 */ - volatile unsigned long TAParamWriteAGPRe; /* 0x0C58 */ - volatile unsigned long TAPtrWriteAGPRe; /* 0x0C5C */ - volatile unsigned long SDRAMArbiterConf; /* 0x0C60 */ - volatile unsigned long SDRAMConf0; /* 0x0C64 */ - volatile unsigned long SDRAMConf1; /* 0x0C68 */ - volatile unsigned long SDRAMConf2; /* 0x0C6C */ - volatile unsigned long SDRAMRefresh; /* 0x0C70 */ - volatile unsigned long SDRAMPowerStat; /* 0x0C74 */ - - volatile unsigned long Fill6[2]; /* GAP 0x0C78 - 0x0C7C */ - - volatile unsigned long RAMBistData; /* 0x0C80 */ - volatile unsigned long RAMBistCtrl; /* 0x0C84 */ - volatile unsigned long FIFOBistKey; /* 0x0C88 */ - volatile unsigned long RAMBistResult; /* 0x0C8C */ - volatile unsigned long FIFOBistResult; /* 0x0C90 */ + volatile u32 Fill4[412]; /* 0x0190 - 0x07FC */ + + volatile u32 TACtrlStreamBase; /* 0x0800 */ + volatile u32 TAObjDataBase; /* 0x0804 */ + volatile u32 TAPtrDataBase; /* 0x0808 */ + volatile u32 TARegionDataBase; /* 0x080C */ + volatile u32 TATailPtrBase; /* 0x0810 */ + volatile u32 TAPtrRegionSize; /* 0x0814 */ + volatile u32 TAConfiguration; /* 0x0818 */ + volatile u32 TAObjDataStartAddr; /* 0x081C */ + volatile u32 TAObjDataEndAddr; /* 0x0820 */ + volatile u32 TAXScreenClip; /* 0x0824 */ + volatile u32 TAYScreenClip; /* 0x0828 */ + volatile u32 TARHWClamp; /* 0x082C */ + volatile u32 TARHWCompare; /* 0x0830 */ + volatile u32 TAStart; /* 0x0834 */ + volatile u32 TAObjReStart; /* 0x0838 */ + volatile u32 TAPtrReStart; /* 0x083C */ + volatile u32 TAStatus1; /* 0x0840 */ + volatile u32 TAStatus2; /* 0x0844 */ + volatile u32 TAIntStatus; /* 0x0848 */ + volatile u32 TAIntMask; /* 0x084C */ + + volatile u32 Fill5[235]; /* GAP 0x0850 - 0x0BF8 */ + + volatile u32 TextureAddrThresh; /* 0x0BFC */ + volatile u32 Core1Translation; /* 0x0C00 */ + volatile u32 TextureAddrReMap; /* 0x0C04 */ + volatile u32 RenderOutAGPRemap; /* 0x0C08 */ + volatile u32 _3DRegionReadTrans; /* 0x0C0C */ + volatile u32 _3DPtrReadTrans; /* 0x0C10 */ + volatile u32 _3DParamReadTrans; /* 0x0C14 */ + volatile u32 _3DRegionReadThresh; /* 0x0C18 */ + volatile u32 _3DPtrReadThresh; /* 0x0C1C */ + volatile u32 _3DParamReadThresh; /* 0x0C20 */ + volatile u32 _3DRegionReadAGPRemap; /* 0x0C24 */ + volatile u32 _3DPtrReadAGPRemap; /* 0x0C28 */ + volatile u32 _3DParamReadAGPRemap; /* 0x0C2C */ + volatile u32 ZBufferAGPRemap; /* 0x0C30 */ + volatile u32 TAIndexAGPRemap; /* 0x0C34 */ + volatile u32 TAVertexAGPRemap; /* 0x0C38 */ + volatile u32 TAUVAddrTrans; /* 0x0C3C */ + volatile u32 TATailPtrCacheTrans; /* 0x0C40 */ + volatile u32 TAParamWriteTrans; /* 0x0C44 */ + volatile u32 TAPtrWriteTrans; /* 0x0C48 */ + volatile u32 TAParamWriteThresh; /* 0x0C4C */ + volatile u32 TAPtrWriteThresh; /* 0x0C50 */ + volatile u32 TATailPtrCacheAGPRe; /* 0x0C54 */ + volatile u32 TAParamWriteAGPRe; /* 0x0C58 */ + volatile u32 TAPtrWriteAGPRe; /* 0x0C5C */ + volatile u32 SDRAMArbiterConf; /* 0x0C60 */ + volatile u32 SDRAMConf0; /* 0x0C64 */ + volatile u32 SDRAMConf1; /* 0x0C68 */ + volatile u32 SDRAMConf2; /* 0x0C6C */ + volatile u32 SDRAMRefresh; /* 0x0C70 */ + volatile u32 SDRAMPowerStat; /* 0x0C74 */ + + volatile u32 Fill6[2]; /* GAP 0x0C78 - 0x0C7C */ + + volatile u32 RAMBistData; /* 0x0C80 */ + volatile u32 RAMBistCtrl; /* 0x0C84 */ + volatile u32 FIFOBistKey; /* 0x0C88 */ + volatile u32 RAMBistResult; /* 0x0C8C */ + volatile u32 FIFOBistResult; /* 0x0C90 */ /* - volatile unsigned long Fill11[0x0CBC/4 - 0x0C94/4]; //GAP 0x0C94 - 0x0CBC - volatile unsigned long Fill12[0x0CD0/4 - 0x0CC0/4]; //GAP 0x0CC0 - 0x0CD0 3DRegisters + volatile u32 Fill11[0x0CBC/4 - 0x0C94/4]; //GAP 0x0C94 - 0x0CBC + volatile u32 Fill12[0x0CD0/4 - 0x0CC0/4]; //GAP 0x0CC0 - 0x0CD0 3DRegisters */ - volatile unsigned long Fill7[16]; /* 0x0c94 - 0x0cd0 */ + volatile u32 Fill7[16]; /* 0x0c94 - 0x0cd0 */ - volatile unsigned long SDRAMAddrSign; /* 0x0CD4 */ - volatile unsigned long SDRAMDataSign; /* 0x0CD8 */ - volatile unsigned long SDRAMSignConf; /* 0x0CDC */ + volatile u32 SDRAMAddrSign; /* 0x0CD4 */ + volatile u32 SDRAMDataSign; /* 0x0CD8 */ + volatile u32 SDRAMSignConf; /* 0x0CDC */ /* DWFILL; //GAP 0x0CE0 */ - volatile unsigned long dwFill_2; - - volatile unsigned long ISPSignature; /* 0x0CE4 */ - - volatile unsigned long Fill8[454]; /*GAP 0x0CE8 - 0x13FC */ - - volatile unsigned long DACPrimAddress; /* 0x1400 */ - volatile unsigned long DACPrimSize; /* 0x1404 */ - volatile unsigned long DACCursorAddr; /* 0x1408 */ - volatile unsigned long DACCursorCtrl; /* 0x140C */ - volatile unsigned long DACOverlayAddr; /* 0x1410 */ - volatile unsigned long DACOverlayUAddr; /* 0x1414 */ - volatile unsigned long DACOverlayVAddr; /* 0x1418 */ - volatile unsigned long DACOverlaySize; /* 0x141C */ - volatile unsigned long DACOverlayVtDec; /* 0x1420 */ - - volatile unsigned long Fill9[9]; /* GAP 0x1424 - 0x1444 */ - - volatile unsigned long DACVerticalScal; /* 0x1448 */ - volatile unsigned long DACPixelFormat; /* 0x144C */ - volatile unsigned long DACHorizontalScal; /* 0x1450 */ - volatile unsigned long DACVidWinStart; /* 0x1454 */ - volatile unsigned long DACVidWinEnd; /* 0x1458 */ - volatile unsigned long DACBlendCtrl; /* 0x145C */ - volatile unsigned long DACHorTim1; /* 0x1460 */ - volatile unsigned long DACHorTim2; /* 0x1464 */ - volatile unsigned long DACHorTim3; /* 0x1468 */ - volatile unsigned long DACVerTim1; /* 0x146C */ - volatile unsigned long DACVerTim2; /* 0x1470 */ - volatile unsigned long DACVerTim3; /* 0x1474 */ - volatile unsigned long DACBorderColor; /* 0x1478 */ - volatile unsigned long DACSyncCtrl; /* 0x147C */ - volatile unsigned long DACStreamCtrl; /* 0x1480 */ - volatile unsigned long DACLUTAddress; /* 0x1484 */ - volatile unsigned long DACLUTData; /* 0x1488 */ - volatile unsigned long DACBurstCtrl; /* 0x148C */ - volatile unsigned long DACCrcTrigger; /* 0x1490 */ - volatile unsigned long DACCrcDone; /* 0x1494 */ - volatile unsigned long DACCrcResult1; /* 0x1498 */ - volatile unsigned long DACCrcResult2; /* 0x149C */ - volatile unsigned long DACLinecount; /* 0x14A0 */ - - volatile unsigned long Fill10[151]; /*GAP 0x14A4 - 0x16FC */ - - volatile unsigned long DigVidPortCtrl; /* 0x1700 */ - volatile unsigned long DigVidPortStat; /* 0x1704 */ + volatile u32 dwFill_2; + + volatile u32 ISPSignature; /* 0x0CE4 */ + + volatile u32 Fill8[454]; /*GAP 0x0CE8 - 0x13FC */ + + volatile u32 DACPrimAddress; /* 0x1400 */ + volatile u32 DACPrimSize; /* 0x1404 */ + volatile u32 DACCursorAddr; /* 0x1408 */ + volatile u32 DACCursorCtrl; /* 0x140C */ + volatile u32 DACOverlayAddr; /* 0x1410 */ + volatile u32 DACOverlayUAddr; /* 0x1414 */ + volatile u32 DACOverlayVAddr; /* 0x1418 */ + volatile u32 DACOverlaySize; /* 0x141C */ + volatile u32 DACOverlayVtDec; /* 0x1420 */ + + volatile u32 Fill9[9]; /* GAP 0x1424 - 0x1444 */ + + volatile u32 DACVerticalScal; /* 0x1448 */ + volatile u32 DACPixelFormat; /* 0x144C */ + volatile u32 DACHorizontalScal; /* 0x1450 */ + volatile u32 DACVidWinStart; /* 0x1454 */ + volatile u32 DACVidWinEnd; /* 0x1458 */ + volatile u32 DACBlendCtrl; /* 0x145C */ + volatile u32 DACHorTim1; /* 0x1460 */ + volatile u32 DACHorTim2; /* 0x1464 */ + volatile u32 DACHorTim3; /* 0x1468 */ + volatile u32 DACVerTim1; /* 0x146C */ + volatile u32 DACVerTim2; /* 0x1470 */ + volatile u32 DACVerTim3; /* 0x1474 */ + volatile u32 DACBorderColor; /* 0x1478 */ + volatile u32 DACSyncCtrl; /* 0x147C */ + volatile u32 DACStreamCtrl; /* 0x1480 */ + volatile u32 DACLUTAddress; /* 0x1484 */ + volatile u32 DACLUTData; /* 0x1488 */ + volatile u32 DACBurstCtrl; /* 0x148C */ + volatile u32 DACCrcTrigger; /* 0x1490 */ + volatile u32 DACCrcDone; /* 0x1494 */ + volatile u32 DACCrcResult1; /* 0x1498 */ + volatile u32 DACCrcResult2; /* 0x149C */ + volatile u32 DACLinecount; /* 0x14A0 */ + + volatile u32 Fill10[151]; /*GAP 0x14A4 - 0x16FC */ + + volatile u32 DigVidPortCtrl; /* 0x1700 */ + volatile u32 DigVidPortStat; /* 0x1704 */ /* - volatile unsigned long Fill11[0x1FFC/4 - 0x1708/4]; //GAP 0x1708 - 0x1FFC - volatile unsigned long Fill17[0x3000/4 - 0x2FFC/4]; //GAP 0x2000 - 0x2FFC ALUT + volatile u32 Fill11[0x1FFC/4 - 0x1708/4]; //GAP 0x1708 - 0x1FFC + volatile u32 Fill17[0x3000/4 - 0x2FFC/4]; //GAP 0x2000 - 0x2FFC ALUT */ - volatile unsigned long Fill11[1598]; + volatile u32 Fill11[1598]; /* DWFILL; //GAP 0x3000 ALUT 256MB offset */ - volatile unsigned long Fill_3; + volatile u32 Fill_3; } STG4000REG; diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c index 4527cbf0a4ec..b061d709bc44 100644 --- a/drivers/video/msm/mddi.c +++ b/drivers/video/msm/mddi.c @@ -420,7 +420,7 @@ static void mddi_resume(struct msm_mddi_client_data *cdata) mddi_set_auto_hibernate(&mddi->client_data, 1); } -static int __init mddi_get_client_caps(struct mddi_info *mddi) +static int __devinit mddi_get_client_caps(struct mddi_info *mddi) { int i, j; @@ -622,9 +622,9 @@ uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg) static struct mddi_info mddi_info[2]; -static int __init mddi_clk_setup(struct platform_device *pdev, - struct mddi_info *mddi, - unsigned long clk_rate) +static int __devinit mddi_clk_setup(struct platform_device *pdev, + struct mddi_info *mddi, + unsigned long clk_rate) { int ret; diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 260cca7ddb41..26e83d7fdd6f 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c @@ -815,8 +815,15 @@ static int __devinit uvesafb_vbe_init(struct fb_info *info) par->pmi_setpal = pmi_setpal; par->ypan = ypan; - if (par->pmi_setpal || par->ypan) - uvesafb_vbe_getpmi(task, par); + if (par->pmi_setpal || par->ypan) { + if (__supported_pte_mask & _PAGE_NX) { + par->pmi_setpal = par->ypan = 0; + printk(KERN_WARNING "uvesafb: NX protection is actively." + "We have better not to use the PMI.\n"); + } else { + uvesafb_vbe_getpmi(task, par); + } + } #else /* The protected mode interface is not available on non-x86. */ par->pmi_setpal = par->ypan = 0; diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 05f0a80818a2..c2d05a8279fd 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -28,6 +28,13 @@ #include <linux/slab.h> #include <linux/module.h> +/* + * Balloon device works in 4K page units. So each page is pointed to by + * multiple balloon pages. All memory counters in this driver are in balloon + * page units. + */ +#define VIRTIO_BALLOON_PAGES_PER_PAGE (PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT) + struct virtio_balloon { struct virtio_device *vdev; @@ -42,8 +49,13 @@ struct virtio_balloon /* Waiting for host to ack the pages we released. */ struct completion acked; - /* The pages we've told the Host we're not using. */ + /* Number of balloon pages we've told the Host we're not using. */ unsigned int num_pages; + /* + * The pages we've told the Host we're not using. + * Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE + * to num_pages above. + */ struct list_head pages; /* The array of pfns we tell the Host about. */ @@ -66,7 +78,13 @@ static u32 page_to_balloon_pfn(struct page *page) BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT); /* Convert pfn from Linux page size to balloon page size. */ - return pfn >> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT); + return pfn * VIRTIO_BALLOON_PAGES_PER_PAGE; +} + +static struct page *balloon_pfn_to_page(u32 pfn) +{ + BUG_ON(pfn % VIRTIO_BALLOON_PAGES_PER_PAGE); + return pfn_to_page(pfn / VIRTIO_BALLOON_PAGES_PER_PAGE); } static void balloon_ack(struct virtqueue *vq) @@ -96,12 +114,23 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq) wait_for_completion(&vb->acked); } +static void set_page_pfns(u32 pfns[], struct page *page) +{ + unsigned int i; + + /* Set balloon pfns pointing at this page. + * Note that the first pfn points at start of the page. */ + for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++) + pfns[i] = page_to_balloon_pfn(page) + i; +} + static void fill_balloon(struct virtio_balloon *vb, size_t num) { /* We can only do one array worth at a time. */ num = min(num, ARRAY_SIZE(vb->pfns)); - for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { + for (vb->num_pfns = 0; vb->num_pfns < num; + vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) { struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); if (!page) { @@ -113,9 +142,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num) msleep(200); break; } - vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page); + set_page_pfns(vb->pfns + vb->num_pfns, page); + vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE; totalram_pages--; - vb->num_pages++; list_add(&page->lru, &vb->pages); } @@ -130,8 +159,9 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num) { unsigned int i; - for (i = 0; i < num; i++) { - __free_page(pfn_to_page(pfns[i])); + /* Find pfns pointing at start of each page, get pages and free them. */ + for (i = 0; i < num; i += VIRTIO_BALLOON_PAGES_PER_PAGE) { + __free_page(balloon_pfn_to_page(pfns[i])); totalram_pages++; } } @@ -143,11 +173,12 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num) /* We can only do one array worth at a time. */ num = min(num, ARRAY_SIZE(vb->pfns)); - for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { + for (vb->num_pfns = 0; vb->num_pfns < num; + vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) { page = list_first_entry(&vb->pages, struct page, lru); list_del(&page->lru); - vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page); - vb->num_pages--; + set_page_pfns(vb->pfns + vb->num_pfns, page); + vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE; } /* @@ -234,11 +265,14 @@ static void virtballoon_changed(struct virtio_device *vdev) static inline s64 towards_target(struct virtio_balloon *vb) { - u32 v; + __le32 v; + s64 target; + vb->vdev->config->get(vb->vdev, offsetof(struct virtio_balloon_config, num_pages), &v, sizeof(v)); - return (s64)v - vb->num_pages; + target = le32_to_cpu(v); + return target - vb->num_pages; } static void update_balloon_size(struct virtio_balloon *vb) diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index d286b40a5671..86eff48dab78 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -405,6 +405,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, bio_put(bio); bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS); + BUG_ON(!bio); bio->bi_private = cb; bio->bi_end_io = end_compressed_bio_write; bio_add_page(bio, page, PAGE_CACHE_SIZE, 0); @@ -687,6 +688,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, comp_bio = compressed_bio_alloc(bdev, cur_disk_byte, GFP_NOFS); + BUG_ON(!comp_bio); comp_bio->bi_private = cb; comp_bio->bi_end_io = end_compressed_bio_read; diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 5b8ef8eb3521..3f65a812e282 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2166,7 +2166,7 @@ BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item, static inline bool btrfs_root_readonly(struct btrfs_root *root) { - return root->root_item.flags & BTRFS_ROOT_SUBVOL_RDONLY; + return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_RDONLY)) != 0; } /* struct btrfs_root_backup */ diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a84420491c11..2b35f8d14bb9 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -529,9 +529,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, * allocate blocks for the tree root we can't do the fast caching since * we likely hold important locks. */ - if (trans && (!trans->transaction->in_commit) && - (root && root != root->fs_info->tree_root) && - btrfs_test_opt(root, SPACE_CACHE)) { + if (fs_info->mount_opt & BTRFS_MOUNT_SPACE_CACHE) { ret = load_free_space_cache(fs_info, cache); spin_lock(&cache->lock); @@ -3152,15 +3150,14 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) /* * returns target flags in extended format or 0 if restripe for this * chunk_type is not in progress + * + * should be called with either volume_mutex or balance_lock held */ static u64 get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags) { struct btrfs_balance_control *bctl = fs_info->balance_ctl; u64 target = 0; - BUG_ON(!mutex_is_locked(&fs_info->volume_mutex) && - !spin_is_locked(&fs_info->balance_lock)); - if (!bctl) return 0; @@ -4205,7 +4202,7 @@ static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info) num_bytes += div64_u64(data_used + meta_used, 50); if (num_bytes * 3 > meta_used) - num_bytes = div64_u64(meta_used, 3) * 2; + num_bytes = div64_u64(meta_used, 3); return ALIGN(num_bytes, fs_info->extent_root->leafsize << 10); } diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 8d904dd7ea9f..cd4b5e400221 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1937,7 +1937,7 @@ int repair_eb_io_failure(struct btrfs_root *root, struct extent_buffer *eb, struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree; u64 start = eb->start; unsigned long i, num_pages = num_extent_pages(eb->start, eb->len); - int ret; + int ret = 0; for (i = 0; i < num_pages; i++) { struct page *p = extent_buffer_page(eb, i); @@ -2180,6 +2180,10 @@ static int bio_readpage_error(struct bio *failed_bio, struct page *page, } bio = bio_alloc(GFP_NOFS, 1); + if (!bio) { + free_io_failure(inode, failrec, 0); + return -EIO; + } bio->bi_private = state; bio->bi_end_io = failed_bio->bi_end_io; bio->bi_sector = failrec->logical >> 9; diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index e88330d3df52..202008ec367d 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -748,13 +748,6 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, u64 used = btrfs_block_group_used(&block_group->item); /* - * If we're unmounting then just return, since this does a search on the - * normal root and not the commit root and we could deadlock. - */ - if (btrfs_fs_closing(fs_info)) - return 0; - - /* * If this block group has been marked to be cleared for one reason or * another then we can't trust the on disk cache, so just return. */ @@ -768,6 +761,8 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, path = btrfs_alloc_path(); if (!path) return 0; + path->search_commit_root = 1; + path->skip_locking = 1; inode = lookup_free_space_inode(root, block_group, path); if (IS_ERR(inode)) { diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 90acc82046c3..bc015f77f3ea 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -1044,6 +1044,8 @@ static int scrub_recheck_block(struct btrfs_fs_info *fs_info, BUG_ON(!page->page); bio = bio_alloc(GFP_NOFS, 1); + if (!bio) + return -EIO; bio->bi_bdev = page->bdev; bio->bi_sector = page->physical >> 9; bio->bi_end_io = scrub_complete_bio_end_io; @@ -1171,6 +1173,8 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad, DECLARE_COMPLETION_ONSTACK(complete); bio = bio_alloc(GFP_NOFS, 1); + if (!bio) + return -EIO; bio->bi_bdev = page_bad->bdev; bio->bi_sector = page_bad->physical >> 9; bio->bi_end_io = scrub_complete_bio_end_io; diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 8da29e8e4de1..11b77a59db62 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -480,6 +480,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, struct btrfs_transaction *cur_trans = trans->transaction; struct btrfs_fs_info *info = root->fs_info; int count = 0; + int err = 0; if (--trans->use_count) { trans->block_rsv = trans->orig_rsv; @@ -532,18 +533,18 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, if (current->journal_info == trans) current->journal_info = NULL; - memset(trans, 0, sizeof(*trans)); - kmem_cache_free(btrfs_trans_handle_cachep, trans); if (throttle) btrfs_run_delayed_iputs(root); if (trans->aborted || root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { - return -EIO; + err = -EIO; } - return 0; + memset(trans, 0, sizeof(*trans)); + kmem_cache_free(btrfs_trans_handle_cachep, trans); + return err; } int btrfs_end_transaction(struct btrfs_trans_handle *trans, diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index a872b48be0ae..759d02486d7c 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -3833,6 +3833,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, int sub_stripes = 0; u64 stripes_per_dev = 0; u32 remaining_stripes = 0; + u32 last_stripe = 0; if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) { @@ -3846,6 +3847,8 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, stripe_nr_orig, factor, &remaining_stripes); + div_u64_rem(stripe_nr_end - 1, factor, &last_stripe); + last_stripe *= sub_stripes; } for (i = 0; i < num_stripes; i++) { @@ -3858,16 +3861,29 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, BTRFS_BLOCK_GROUP_RAID10)) { bbio->stripes[i].length = stripes_per_dev * map->stripe_len; + if (i / sub_stripes < remaining_stripes) bbio->stripes[i].length += map->stripe_len; + + /* + * Special for the first stripe and + * the last stripe: + * + * |-------|...|-------| + * |----------| + * off end_off + */ if (i < sub_stripes) bbio->stripes[i].length -= stripe_offset; - if ((i / sub_stripes + 1) % - sub_stripes == remaining_stripes) + + if (stripe_index >= last_stripe && + stripe_index <= (last_stripe + + sub_stripes - 1)) bbio->stripes[i].length -= stripe_end_offset; + if (i == sub_stripes - 1) stripe_offset = 0; } else diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d81e933a796b..f31dc9ac37b7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -109,6 +109,8 @@ enum { /* Options which could be blank */ Opt_blank_pass, + Opt_blank_user, + Opt_blank_ip, Opt_err }; @@ -183,11 +185,15 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_wsize, "wsize=%s" }, { Opt_actimeo, "actimeo=%s" }, + { Opt_blank_user, "user=" }, + { Opt_blank_user, "username=" }, { Opt_user, "user=%s" }, { Opt_user, "username=%s" }, { Opt_blank_pass, "pass=" }, { Opt_pass, "pass=%s" }, { Opt_pass, "password=%s" }, + { Opt_blank_ip, "ip=" }, + { Opt_blank_ip, "addr=" }, { Opt_ip, "ip=%s" }, { Opt_ip, "addr=%s" }, { Opt_unc, "unc=%s" }, @@ -1117,7 +1123,7 @@ static int get_option_ul(substring_t args[], unsigned long *option) string = match_strdup(args); if (string == NULL) return -ENOMEM; - rc = kstrtoul(string, 10, option); + rc = kstrtoul(string, 0, option); kfree(string); return rc; @@ -1534,15 +1540,17 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, /* String Arguments */ + case Opt_blank_user: + /* null user, ie. anonymous authentication */ + vol->nullauth = 1; + vol->username = NULL; + break; case Opt_user: string = match_strdup(args); if (string == NULL) goto out_nomem; - if (!*string) { - /* null user, ie. anonymous authentication */ - vol->nullauth = 1; - } else if (strnlen(string, MAX_USERNAME_SIZE) > + if (strnlen(string, MAX_USERNAME_SIZE) > MAX_USERNAME_SIZE) { printk(KERN_WARNING "CIFS: username too long\n"); goto cifs_parse_mount_err; @@ -1611,14 +1619,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } vol->password[j] = '\0'; break; + case Opt_blank_ip: + vol->UNCip = NULL; + break; case Opt_ip: string = match_strdup(args); if (string == NULL) goto out_nomem; - if (!*string) { - vol->UNCip = NULL; - } else if (strnlen(string, INET6_ADDRSTRLEN) > + if (strnlen(string, INET6_ADDRSTRLEN) > INET6_ADDRSTRLEN) { printk(KERN_WARNING "CIFS: ip address " "too long\n"); @@ -1636,12 +1645,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: invalid path to " - "network resource\n"); - goto cifs_parse_mount_err; - } - temp_len = strnlen(string, 300); if (temp_len == 300) { printk(KERN_WARNING "CIFS: UNC name too long\n"); @@ -1670,11 +1673,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: invalid domain" - " name\n"); - goto cifs_parse_mount_err; - } else if (strnlen(string, 256) == 256) { + if (strnlen(string, 256) == 256) { printk(KERN_WARNING "CIFS: domain name too" " long\n"); goto cifs_parse_mount_err; @@ -1693,11 +1692,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: srcaddr value not" - " specified\n"); - goto cifs_parse_mount_err; - } else if (!cifs_convert_address( + if (!cifs_convert_address( (struct sockaddr *)&vol->srcaddr, string, strlen(string))) { printk(KERN_WARNING "CIFS: Could not parse" @@ -1710,11 +1705,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: Invalid path" - " prefix\n"); - goto cifs_parse_mount_err; - } temp_len = strnlen(string, 1024); if (string[0] != '/') temp_len++; /* missing leading slash */ @@ -1742,11 +1732,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: Invalid iocharset" - " specified\n"); - goto cifs_parse_mount_err; - } else if (strnlen(string, 1024) >= 65) { + if (strnlen(string, 1024) >= 65) { printk(KERN_WARNING "CIFS: iocharset name " "too long.\n"); goto cifs_parse_mount_err; @@ -1771,11 +1757,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: No socket option" - " specified\n"); - goto cifs_parse_mount_err; - } if (strnicmp(string, "TCP_NODELAY", 11) == 0) vol->sockopt_tcp_nodelay = 1; break; @@ -1784,12 +1765,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: Invalid (empty)" - " netbiosname\n"); - break; - } - memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN); /* @@ -1817,11 +1792,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: Empty server" - " netbiosname specified\n"); - break; - } /* last byte, type, is 0x20 for servr type */ memset(vol->target_rfc1001_name, 0x20, RFC1001_NAME_LEN_WITH_NULL); @@ -1848,12 +1818,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - cERROR(1, "no protocol version specified" - " after vers= mount option"); - goto cifs_parse_mount_err; - } - if (strnicmp(string, "cifs", 4) == 0 || strnicmp(string, "1", 1) == 0) { /* This is the default */ @@ -1868,12 +1832,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (!*string) { - printk(KERN_WARNING "CIFS: no security flavor" - " specified\n"); - break; - } - if (cifs_parse_security_flavors(string, vol) != 0) goto cifs_parse_mount_err; break; diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index ab2594a30f86..0e01e90add8b 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1203,9 +1203,6 @@ struct ext4_sb_info { unsigned long s_ext_blocks; unsigned long s_ext_extents; #endif - /* ext4 extent cache stats */ - unsigned long extent_cache_hits; - unsigned long extent_cache_misses; /* for buddy allocator */ struct ext4_group_info ***s_group_info; diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 1421938e6792..abcdeab67f52 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2066,10 +2066,6 @@ static int ext4_ext_check_cache(struct inode *inode, ext4_lblk_t block, ret = 1; } errout: - if (!ret) - sbi->extent_cache_misses++; - else - sbi->extent_cache_hits++; trace_ext4_ext_in_cache(inode, block, ret); spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); return ret; @@ -2882,7 +2878,7 @@ static int ext4_split_extent_at(handle_t *handle, if (err) goto fix_extent_len; /* update the extent length and mark as initialized */ - ex->ee_len = cpu_to_le32(ee_len); + ex->ee_len = cpu_to_le16(ee_len); ext4_ext_try_to_merge(inode, path, ex); err = ext4_ext_dirty(handle, inode, path + depth); goto out; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index ceebaf853beb..6da193564e43 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1305,20 +1305,20 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args) ext4_msg(sb, KERN_ERR, "Cannot change journaled " "quota options when quota turned on"); - return 0; + return -1; } qname = match_strdup(args); if (!qname) { ext4_msg(sb, KERN_ERR, "Not enough memory for storing quotafile name"); - return 0; + return -1; } if (sbi->s_qf_names[qtype] && strcmp(sbi->s_qf_names[qtype], qname)) { ext4_msg(sb, KERN_ERR, "%s quota file already specified", QTYPE2NAME(qtype)); kfree(qname); - return 0; + return -1; } sbi->s_qf_names[qtype] = qname; if (strchr(sbi->s_qf_names[qtype], '/')) { @@ -1326,7 +1326,7 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args) "quotafile must be on filesystem root"); kfree(sbi->s_qf_names[qtype]); sbi->s_qf_names[qtype] = NULL; - return 0; + return -1; } set_opt(sb, QUOTA); return 1; @@ -1341,7 +1341,7 @@ static int clear_qf_name(struct super_block *sb, int qtype) sbi->s_qf_names[qtype]) { ext4_msg(sb, KERN_ERR, "Cannot change journaled quota options" " when quota turned on"); - return 0; + return -1; } /* * The space will be released later when all options are confirmed @@ -1450,6 +1450,16 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, const struct mount_opts *m; int arg = 0; +#ifdef CONFIG_QUOTA + if (token == Opt_usrjquota) + return set_qf_name(sb, USRQUOTA, &args[0]); + else if (token == Opt_grpjquota) + return set_qf_name(sb, GRPQUOTA, &args[0]); + else if (token == Opt_offusrjquota) + return clear_qf_name(sb, USRQUOTA); + else if (token == Opt_offgrpjquota) + return clear_qf_name(sb, GRPQUOTA); +#endif if (args->from && match_int(args, &arg)) return -1; switch (token) { @@ -1549,18 +1559,6 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, sbi->s_mount_opt |= m->mount_opt; } #ifdef CONFIG_QUOTA - } else if (token == Opt_usrjquota) { - if (!set_qf_name(sb, USRQUOTA, &args[0])) - return -1; - } else if (token == Opt_grpjquota) { - if (!set_qf_name(sb, GRPQUOTA, &args[0])) - return -1; - } else if (token == Opt_offusrjquota) { - if (!clear_qf_name(sb, USRQUOTA)) - return -1; - } else if (token == Opt_offgrpjquota) { - if (!clear_qf_name(sb, GRPQUOTA)) - return -1; } else if (m->flags & MOPT_QFMT) { if (sb_any_quota_loaded(sb) && sbi->s_jquota_fmt != m->mount_opt) { @@ -2366,18 +2364,6 @@ static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a, EXT4_SB(sb)->s_sectors_written_start) >> 1))); } -static ssize_t extent_cache_hits_show(struct ext4_attr *a, - struct ext4_sb_info *sbi, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_hits); -} - -static ssize_t extent_cache_misses_show(struct ext4_attr *a, - struct ext4_sb_info *sbi, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_misses); -} - static ssize_t inode_readahead_blks_store(struct ext4_attr *a, struct ext4_sb_info *sbi, const char *buf, size_t count) @@ -2435,8 +2421,6 @@ static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store) EXT4_RO_ATTR(delayed_allocation_blocks); EXT4_RO_ATTR(session_write_kbytes); EXT4_RO_ATTR(lifetime_write_kbytes); -EXT4_RO_ATTR(extent_cache_hits); -EXT4_RO_ATTR(extent_cache_misses); EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show, inode_readahead_blks_store, s_inode_readahead_blks); EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); @@ -2452,8 +2436,6 @@ static struct attribute *ext4_attrs[] = { ATTR_LIST(delayed_allocation_blocks), ATTR_LIST(session_write_kbytes), ATTR_LIST(lifetime_write_kbytes), - ATTR_LIST(extent_cache_hits), - ATTR_LIST(extent_cache_misses), ATTR_LIST(inode_readahead_blks), ATTR_LIST(inode_goal), ATTR_LIST(mb_stats), diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 206632887bb4..df5ac048dc74 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -387,9 +387,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, if (fc->no_create) return -ENOSYS; - if (flags & O_DIRECT) - return -EINVAL; - forget = fuse_alloc_forget(); if (!forget) return -ENOMEM; @@ -644,13 +641,12 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) fuse_put_request(fc, req); if (!err) { struct inode *inode = entry->d_inode; + struct fuse_inode *fi = get_fuse_inode(inode); - /* - * Set nlink to zero so the inode can be cleared, if the inode - * does have more links this will be discovered at the next - * lookup/getattr. - */ - clear_nlink(inode); + spin_lock(&fc->lock); + fi->attr_version = ++fc->attr_version; + drop_nlink(inode); + spin_unlock(&fc->lock); fuse_invalidate_attr(inode); fuse_invalidate_attr(dir); fuse_invalidate_entry_cache(entry); @@ -762,8 +758,17 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, will reflect changes in the backing inode (link count, etc.) */ - if (!err || err == -EINTR) + if (!err) { + struct fuse_inode *fi = get_fuse_inode(inode); + + spin_lock(&fc->lock); + fi->attr_version = ++fc->attr_version; + inc_nlink(inode); + spin_unlock(&fc->lock); + fuse_invalidate_attr(inode); + } else if (err == -EINTR) { fuse_invalidate_attr(inode); + } return err; } diff --git a/fs/fuse/file.c b/fs/fuse/file.c index a841868bf9ce..504e61b7fd75 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -194,10 +194,6 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir) struct fuse_conn *fc = get_fuse_conn(inode); int err; - /* VFS checks this, but only _after_ ->open() */ - if (file->f_flags & O_DIRECT) - return -EINVAL; - err = generic_file_open(inode, file); if (err) return err; @@ -932,17 +928,23 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov, struct file *file = iocb->ki_filp; struct address_space *mapping = file->f_mapping; size_t count = 0; + size_t ocount = 0; ssize_t written = 0; + ssize_t written_buffered = 0; struct inode *inode = mapping->host; ssize_t err; struct iov_iter i; + loff_t endbyte = 0; WARN_ON(iocb->ki_pos != pos); - err = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ); + ocount = 0; + err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ); if (err) return err; + count = ocount; + mutex_lock(&inode->i_mutex); vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); @@ -962,11 +964,41 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov, file_update_time(file); - iov_iter_init(&i, iov, nr_segs, count, 0); - written = fuse_perform_write(file, mapping, &i, pos); - if (written >= 0) - iocb->ki_pos = pos + written; + if (file->f_flags & O_DIRECT) { + written = generic_file_direct_write(iocb, iov, &nr_segs, + pos, &iocb->ki_pos, + count, ocount); + if (written < 0 || written == count) + goto out; + + pos += written; + count -= written; + iov_iter_init(&i, iov, nr_segs, count, written); + written_buffered = fuse_perform_write(file, mapping, &i, pos); + if (written_buffered < 0) { + err = written_buffered; + goto out; + } + endbyte = pos + written_buffered - 1; + + err = filemap_write_and_wait_range(file->f_mapping, pos, + endbyte); + if (err) + goto out; + + invalidate_mapping_pages(file->f_mapping, + pos >> PAGE_CACHE_SHIFT, + endbyte >> PAGE_CACHE_SHIFT); + + written += written_buffered; + iocb->ki_pos = pos + written_buffered; + } else { + iov_iter_init(&i, iov, nr_segs, count, 0); + written = fuse_perform_write(file, mapping, &i, pos); + if (written >= 0) + iocb->ki_pos = pos + written; + } out: current->backing_dev_info = NULL; mutex_unlock(&inode->i_mutex); @@ -1101,30 +1133,41 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf, return res; } -static ssize_t fuse_direct_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) +static ssize_t __fuse_direct_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) { struct inode *inode = file->f_path.dentry->d_inode; ssize_t res; - if (is_bad_inode(inode)) - return -EIO; - - /* Don't allow parallel writes to the same file */ - mutex_lock(&inode->i_mutex); res = generic_write_checks(file, ppos, &count, 0); if (!res) { res = fuse_direct_io(file, buf, count, ppos, 1); if (res > 0) fuse_write_update_size(inode, *ppos); } - mutex_unlock(&inode->i_mutex); fuse_invalidate_attr(inode); return res; } +static ssize_t fuse_direct_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct inode *inode = file->f_path.dentry->d_inode; + ssize_t res; + + if (is_bad_inode(inode)) + return -EIO; + + /* Don't allow parallel writes to the same file */ + mutex_lock(&inode->i_mutex); + res = __fuse_direct_write(file, buf, count, ppos); + mutex_unlock(&inode->i_mutex); + + return res; +} + static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req) { __free_page(req->pages[0]); @@ -2077,6 +2120,57 @@ int fuse_notify_poll_wakeup(struct fuse_conn *fc, return 0; } +static ssize_t fuse_loop_dio(struct file *filp, const struct iovec *iov, + unsigned long nr_segs, loff_t *ppos, int rw) +{ + const struct iovec *vector = iov; + ssize_t ret = 0; + + while (nr_segs > 0) { + void __user *base; + size_t len; + ssize_t nr; + + base = vector->iov_base; + len = vector->iov_len; + vector++; + nr_segs--; + + if (rw == WRITE) + nr = __fuse_direct_write(filp, base, len, ppos); + else + nr = fuse_direct_read(filp, base, len, ppos); + + if (nr < 0) { + if (!ret) + ret = nr; + break; + } + ret += nr; + if (nr != len) + break; + } + + return ret; +} + + +static ssize_t +fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, + loff_t offset, unsigned long nr_segs) +{ + ssize_t ret = 0; + struct file *file = NULL; + loff_t pos = 0; + + file = iocb->ki_filp; + pos = offset; + + ret = fuse_loop_dio(file, iov, nr_segs, &pos, rw); + + return ret; +} + static const struct file_operations fuse_file_operations = { .llseek = fuse_file_llseek, .read = do_sync_read, @@ -2120,6 +2214,7 @@ static const struct address_space_operations fuse_file_aops = { .readpages = fuse_readpages, .set_page_dirty = __set_page_dirty_nobuffers, .bmap = fuse_bmap, + .direct_IO = fuse_direct_IO, }; void fuse_init_file_inode(struct inode *inode) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 4aec5995867e..26783eb2b1fc 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -947,6 +947,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) sb->s_magic = FUSE_SUPER_MAGIC; sb->s_op = &fuse_super_operations; sb->s_maxbytes = MAX_LFS_FILESIZE; + sb->s_time_gran = 1; sb->s_export_op = &fuse_export_operations; file = fget(d.fd); diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig index c465ae066c62..eb08c9e43c2a 100644 --- a/fs/gfs2/Kconfig +++ b/fs/gfs2/Kconfig @@ -1,10 +1,6 @@ config GFS2_FS tristate "GFS2 file system support" depends on (64BIT || LBDAF) - select DLM if GFS2_FS_LOCKING_DLM - select CONFIGFS_FS if GFS2_FS_LOCKING_DLM - select SYSFS if GFS2_FS_LOCKING_DLM - select IP_SCTP if DLM_SCTP select FS_POSIX_ACL select CRC32 select QUOTACTL @@ -29,7 +25,8 @@ config GFS2_FS config GFS2_FS_LOCKING_DLM bool "GFS2 DLM locking" - depends on (GFS2_FS!=n) && NET && INET && (IPV6 || IPV6=n) && HOTPLUG + depends on (GFS2_FS!=n) && NET && INET && (IPV6 || IPV6=n) && \ + HOTPLUG && DLM && CONFIGFS_FS && SYSFS help Multiple node locking module for GFS2 diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 38b7a74a0f91..9b2ff0e851b1 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -807,7 +807,7 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, if (inode == sdp->sd_rindex) { adjust_fs_space(inode); - ip->i_gh.gh_flags |= GL_NOCACHE; + sdp->sd_rindex_uptodate = 0; } brelse(dibh); @@ -873,7 +873,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, if (inode == sdp->sd_rindex) { adjust_fs_space(inode); - ip->i_gh.gh_flags |= GL_NOCACHE; + sdp->sd_rindex_uptodate = 0; } brelse(dibh); diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 197c5c47e577..03c04febe26f 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -724,7 +724,11 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, int metadata; unsigned int revokes = 0; int x; - int error = 0; + int error; + + error = gfs2_rindex_update(sdp); + if (error) + return error; if (!*top) sm->sm_first = 0; diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index c35573abd371..a836056343f0 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -1844,6 +1844,10 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, unsigned int x, size = len * sizeof(u64); int error; + error = gfs2_rindex_update(sdp); + if (error) + return error; + memset(&rlist, 0, sizeof(struct gfs2_rgrp_list)); ht = kzalloc(size, GFP_NOFS); diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index c98a60ee6dfd..a9ba2444e077 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1031,7 +1031,13 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) struct buffer_head *bh; struct gfs2_holder ghs[3]; struct gfs2_rgrpd *rgd; - int error = -EROFS; + int error; + + error = gfs2_rindex_update(sdp); + if (error) + return error; + + error = -EROFS; gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); @@ -1224,6 +1230,10 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, return 0; } + error = gfs2_rindex_update(sdp); + if (error) + return error; + if (odip != ndip) { error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, 0, &r_gh); @@ -1345,7 +1355,6 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, error = alloc_required; if (error < 0) goto out_gunlock; - error = 0; if (alloc_required) { struct gfs2_qadata *qa = gfs2_qadata_get(ndip); diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 19bde40b4864..3df65c9ab73b 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -332,9 +332,6 @@ struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk, bool exact) struct rb_node *n, *next; struct gfs2_rgrpd *cur; - if (gfs2_rindex_update(sdp)) - return NULL; - spin_lock(&sdp->sd_rindex_spin); n = sdp->sd_rindex_tree.rb_node; while (n) { @@ -640,6 +637,7 @@ static int read_rindex_entry(struct gfs2_inode *ip, return 0; error = 0; /* someone else read in the rgrp; free it and ignore it */ + gfs2_glock_put(rgd->rd_gl); fail: kfree(rgd->rd_bits); @@ -927,6 +925,10 @@ int gfs2_fitrim(struct file *filp, void __user *argp) } else if (copy_from_user(&r, argp, sizeof(r))) return -EFAULT; + ret = gfs2_rindex_update(sdp); + if (ret) + return ret; + rgd = gfs2_blk2rgrpd(sdp, r.start, 0); rgd_end = gfs2_blk2rgrpd(sdp, r.start + r.len, 0); diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index 2e5ba425cae7..927f4df874ae 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c @@ -238,6 +238,10 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, unsigned int x; int error; + error = gfs2_rindex_update(sdp); + if (error) + return error; + if (GFS2_EA_IS_STUFFED(ea)) return 0; @@ -1330,6 +1334,10 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) unsigned int x; int error; + error = gfs2_rindex_update(sdp); + if (error) + return error; + memset(&rlist, 0, sizeof(struct gfs2_rgrp_list)); error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, &indbh); @@ -1439,6 +1447,10 @@ static int ea_dealloc_block(struct gfs2_inode *ip) struct gfs2_holder gh; int error; + error = gfs2_rindex_update(sdp); + if (error) + return error; + rgd = gfs2_blk2rgrpd(sdp, ip->i_eattr, 1); if (!rgd) { gfs2_consist_inode(ip); diff --git a/fs/libfs.c b/fs/libfs.c index 358094f0433d..18d08f5db53a 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -529,6 +529,7 @@ int simple_fill_super(struct super_block *s, unsigned long magic, return 0; out: d_genocide(root); + shrink_dcache_parent(root); dput(root); return -ENOMEM; } diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c index 3ddcbb1c0a43..13ad1539fbf2 100644 --- a/fs/lockd/clnt4xdr.c +++ b/fs/lockd/clnt4xdr.c @@ -241,7 +241,7 @@ static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat) p = xdr_inline_decode(xdr, 4); if (unlikely(p == NULL)) goto out_overflow; - if (unlikely(*p > nlm4_failed)) + if (unlikely(ntohl(*p) > ntohl(nlm4_failed))) goto out_bad_xdr; *stat = *p; return 0; diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c index 3d35e3e80c1c..d269ada7670e 100644 --- a/fs/lockd/clntxdr.c +++ b/fs/lockd/clntxdr.c @@ -236,7 +236,7 @@ static int decode_nlm_stat(struct xdr_stream *xdr, p = xdr_inline_decode(xdr, 4); if (unlikely(p == NULL)) goto out_overflow; - if (unlikely(*p > nlm_lck_denied_grace_period)) + if (unlikely(ntohl(*p) > ntohl(nlm_lck_denied_grace_period))) goto out_enum; *stat = *p; return 0; diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 08c6e36ab2eb..43f46cd9edea 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -803,13 +803,13 @@ encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, return p; } -static int +static __be32 compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, const char *name, int namlen) { struct svc_export *exp; struct dentry *dparent, *dchild; - int rv = 0; + __be32 rv = nfserr_noent; dparent = cd->fh.fh_dentry; exp = cd->fh.fh_export; @@ -817,26 +817,20 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, if (isdotent(name, namlen)) { if (namlen == 2) { dchild = dget_parent(dparent); - if (dchild == dparent) { - /* filesystem root - cannot return filehandle for ".." */ - dput(dchild); - return -ENOENT; - } + /* filesystem root - cannot return filehandle for ".." */ + if (dchild == dparent) + goto out; } else dchild = dget(dparent); } else dchild = lookup_one_len(name, dparent, namlen); if (IS_ERR(dchild)) - return -ENOENT; - rv = -ENOENT; + return rv; if (d_mountpoint(dchild)) goto out; - rv = fh_compose(fhp, exp, dchild, &cd->fh); - if (rv) - goto out; if (!dchild->d_inode) goto out; - rv = 0; + rv = fh_compose(fhp, exp, dchild, &cd->fh); out: dput(dchild); return rv; @@ -845,7 +839,7 @@ out: static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) { struct svc_fh fh; - int err; + __be32 err; fh_init(&fh, NFS3_FHSIZE); err = compose_entry_fh(cd, &fh, name, namlen); diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 2ed14dfd00a2..694d526c8f19 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -841,6 +841,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_setattr *setattr) { __be32 status = nfs_ok; + int err; if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { nfs4_lock_state(); @@ -852,9 +853,9 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, return status; } } - status = fh_want_write(&cstate->current_fh); - if (status) - return status; + err = fh_want_write(&cstate->current_fh); + if (err) + return nfserrno(err); status = nfs_ok; status = check_attr_support(rqstp, cstate, setattr->sa_bmval, diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 1841f8bf845e..7f71c69cdcdf 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4211,16 +4211,14 @@ out: * vfs_test_lock. (Arguably perhaps test_lock should be done with an * inode operation.) */ -static int nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock) +static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock) { struct file *file; - int err; - - err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); - if (err) - return err; - err = vfs_test_lock(file, lock); - nfsd_close(file); + __be32 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); + if (!err) { + err = nfserrno(vfs_test_lock(file, lock)); + nfsd_close(file); + } return err; } @@ -4234,7 +4232,6 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct inode *inode; struct file_lock file_lock; struct nfs4_lockowner *lo; - int error; __be32 status; if (locks_in_grace()) @@ -4280,12 +4277,10 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, nfs4_transform_lock_offset(&file_lock); - status = nfs_ok; - error = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock); - if (error) { - status = nfserrno(error); + status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock); + if (status) goto out; - } + if (file_lock.fl_type != F_UNLCK) { status = nfserr_denied; nfs4_set_lock_denied(&file_lock, &lockt->lt_denied); diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index bcd8904ab1e3..74c00bc92b9a 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1392,7 +1392,7 @@ nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_sta for (i = 0; i < test_stateid->ts_num_ids; i++) { stateid = kmalloc(sizeof(struct nfsd4_test_stateid_id), GFP_KERNEL); if (!stateid) { - status = PTR_ERR(stateid); + status = nfserrno(-ENOMEM); goto out; } @@ -3410,7 +3410,7 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr, *p++ = htonl(test_stateid->ts_num_ids); list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) { - *p++ = htonl(stateid->ts_id_status); + *p++ = stateid->ts_id_status; } ADJUST_ARGS(); diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 3165aebb43c8..31b9463fba1f 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -1134,7 +1134,7 @@ static int ocfs2_adjust_rightmost_branch(handle_t *handle, } el = path_leaf_el(path); - rec = &el->l_recs[le32_to_cpu(el->l_next_free_rec) - 1]; + rec = &el->l_recs[le16_to_cpu(el->l_next_free_rec) - 1]; ocfs2_adjust_rightmost_records(handle, et, path, rec); diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index cf7823382664..9f32d7cbb7a3 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -1036,14 +1036,14 @@ static int ocfs2_get_refcount_cpos_end(struct ocfs2_caching_info *ci, tmp_el = left_path->p_node[subtree_root].el; blkno = left_path->p_node[subtree_root+1].bh->b_blocknr; - for (i = 0; i < le32_to_cpu(tmp_el->l_next_free_rec); i++) { + for (i = 0; i < le16_to_cpu(tmp_el->l_next_free_rec); i++) { if (le64_to_cpu(tmp_el->l_recs[i].e_blkno) == blkno) { *cpos_end = le32_to_cpu(tmp_el->l_recs[i+1].e_cpos); break; } } - BUG_ON(i == le32_to_cpu(tmp_el->l_next_free_rec)); + BUG_ON(i == le16_to_cpu(tmp_el->l_next_free_rec)); out: ocfs2_free_path(left_path); @@ -1468,7 +1468,7 @@ static int ocfs2_divide_leaf_refcount_block(struct buffer_head *ref_leaf_bh, trace_ocfs2_divide_leaf_refcount_block( (unsigned long long)ref_leaf_bh->b_blocknr, - le32_to_cpu(rl->rl_count), le32_to_cpu(rl->rl_used)); + le16_to_cpu(rl->rl_count), le16_to_cpu(rl->rl_used)); /* * XXX: Improvement later. @@ -2411,7 +2411,7 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, rb = (struct ocfs2_refcount_block *) prev_bh->b_data; - if (le64_to_cpu(rb->rf_records.rl_used) + + if (le16_to_cpu(rb->rf_records.rl_used) + recs_add > le16_to_cpu(rb->rf_records.rl_count)) ref_blocks++; @@ -2476,7 +2476,7 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, if (prev_bh) { rb = (struct ocfs2_refcount_block *)prev_bh->b_data; - if (le64_to_cpu(rb->rf_records.rl_used) + recs_add > + if (le16_to_cpu(rb->rf_records.rl_used) + recs_add > le16_to_cpu(rb->rf_records.rl_count)) ref_blocks++; @@ -3629,7 +3629,7 @@ int ocfs2_refcounted_xattr_delete_need(struct inode *inode, * one will split a refcount rec, so totally we need * clusters * 2 new refcount rec. */ - if (le64_to_cpu(rb->rf_records.rl_used) + clusters * 2 > + if (le16_to_cpu(rb->rf_records.rl_used) + clusters * 2 > le16_to_cpu(rb->rf_records.rl_count)) ref_blocks++; diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index ba5d97e4a73e..f169da4624fd 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -600,7 +600,7 @@ static void ocfs2_bg_alloc_cleanup(handle_t *handle, ret = ocfs2_free_clusters(handle, cluster_ac->ac_inode, cluster_ac->ac_bh, le64_to_cpu(rec->e_blkno), - le32_to_cpu(rec->e_leaf_clusters)); + le16_to_cpu(rec->e_leaf_clusters)); if (ret) mlog_errno(ret); /* Try all the clusters to free */ @@ -1628,7 +1628,7 @@ static int ocfs2_bg_discontig_fix_by_rec(struct ocfs2_suballoc_result *res, { unsigned int bpc = le16_to_cpu(cl->cl_bpc); unsigned int bitoff = le32_to_cpu(rec->e_cpos) * bpc; - unsigned int bitcount = le32_to_cpu(rec->e_leaf_clusters) * bpc; + unsigned int bitcount = le16_to_cpu(rec->e_leaf_clusters) * bpc; if (res->sr_bit_offset < bitoff) return 0; diff --git a/fs/proc/stat.c b/fs/proc/stat.c index 6a0c62d6e442..64c3b3172367 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c @@ -18,19 +18,39 @@ #ifndef arch_irq_stat #define arch_irq_stat() 0 #endif -#ifndef arch_idle_time -#define arch_idle_time(cpu) 0 -#endif + +#ifdef arch_idle_time + +static cputime64_t get_idle_time(int cpu) +{ + cputime64_t idle; + + idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE]; + if (cpu_online(cpu) && !nr_iowait_cpu(cpu)) + idle += arch_idle_time(cpu); + return idle; +} + +static cputime64_t get_iowait_time(int cpu) +{ + cputime64_t iowait; + + iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT]; + if (cpu_online(cpu) && nr_iowait_cpu(cpu)) + iowait += arch_idle_time(cpu); + return iowait; +} + +#else static u64 get_idle_time(int cpu) { u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL); - if (idle_time == -1ULL) { + if (idle_time == -1ULL) /* !NO_HZ so we can rely on cpustat.idle */ idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE]; - idle += arch_idle_time(cpu); - } else + else idle = usecs_to_cputime64(idle_time); return idle; @@ -49,6 +69,8 @@ static u64 get_iowait_time(int cpu) return iowait; } +#endif + static int show_stat(struct seq_file *p, void *v) { int i, j; diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 2a7a3f5d1ca6..35a36d39fa2c 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -729,6 +729,9 @@ int sysfs_create_dir(struct kobject * kobj) else parent_sd = &sysfs_root; + if (!parent_sd) + return -ENOENT; + if (sysfs_ns_type(parent_sd)) ns = kobj->ktype->namespace(kobj); type = sysfs_read_ns_type(kobj); @@ -878,7 +881,6 @@ int sysfs_rename(struct sysfs_dirent *sd, dup_name = sd->s_name; sd->s_name = new_name; - sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name); } /* Move to the appropriate place in the appropriate directories rbtree. */ @@ -886,6 +888,7 @@ int sysfs_rename(struct sysfs_dirent *sd, sysfs_get(new_parent_sd); sysfs_put(sd->s_parent); sd->s_ns = new_ns; + sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name); sd->s_parent = new_parent_sd; sysfs_link_sibling(sd); diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index dd1701caecc9..2df555c66d57 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -67,7 +67,11 @@ static int internal_create_group(struct kobject *kobj, int update, /* Updates may happen before the object has been instantiated */ if (unlikely(update && !kobj->sd)) return -EINVAL; - + if (!grp->attrs) { + WARN(1, "sysfs: attrs not set by subsystem for group: %s/%s\n", + kobj->name, grp->name ? "" : grp->name); + return -EINVAL; + } if (grp->name) { error = sysfs_create_subdir(kobj, grp->name, &sd); if (error) diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h index 3963116083ae..e478de4e5d56 100644 --- a/include/drm/exynos_drm.h +++ b/include/drm/exynos_drm.h @@ -85,7 +85,7 @@ struct drm_exynos_gem_mmap { struct drm_exynos_vidi_connection { unsigned int connection; unsigned int extensions; - uint64_t *edid; + uint64_t edid; }; struct drm_exynos_plane_set_zpos { @@ -96,7 +96,8 @@ struct drm_exynos_plane_set_zpos { /* memory type definitions. */ enum e_drm_exynos_gem_mem_type { /* Physically Non-Continuous memory. */ - EXYNOS_BO_NONCONTIG = 1 << 0 + EXYNOS_BO_NONCONTIG = 1 << 0, + EXYNOS_BO_MASK = EXYNOS_BO_NONCONTIG }; #define DRM_EXYNOS_GEM_CREATE 0x00 diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h index 7847e197730a..8d54f79457ba 100644 --- a/include/linux/amba/bus.h +++ b/include/linux/amba/bus.h @@ -30,7 +30,6 @@ struct amba_device { struct device dev; struct resource res; struct clk *pclk; - struct regulator *vcore; u64 dma_mask; unsigned int periphid; unsigned int irq[AMBA_NR_IRQS]; @@ -75,12 +74,6 @@ void amba_release_regions(struct amba_device *); #define amba_pclk_disable(d) \ do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0) -#define amba_vcore_enable(d) \ - (IS_ERR((d)->vcore) ? 0 : regulator_enable((d)->vcore)) - -#define amba_vcore_disable(d) \ - do { if (!IS_ERR((d)->vcore)) regulator_disable((d)->vcore); } while (0) - /* Some drivers don't use the struct amba_device */ #define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff) #define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f) diff --git a/include/linux/amba/pl022.h b/include/linux/amba/pl022.h index b8c51124ed19..76dd1b199a1b 100644 --- a/include/linux/amba/pl022.h +++ b/include/linux/amba/pl022.h @@ -25,6 +25,8 @@ #ifndef _SSP_PL022_H #define _SSP_PL022_H +#include <linux/types.h> + /** * whether SSP is in loopback mode or not */ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 606cf339bb56..2aa24664a5b5 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -426,14 +426,10 @@ struct request_queue { (1 << QUEUE_FLAG_SAME_COMP) | \ (1 << QUEUE_FLAG_ADD_RANDOM)) -static inline int queue_is_locked(struct request_queue *q) +static inline void queue_lockdep_assert_held(struct request_queue *q) { -#ifdef CONFIG_SMP - spinlock_t *lock = q->queue_lock; - return lock && spin_is_locked(lock); -#else - return 1; -#endif + if (q->queue_lock) + lockdep_assert_held(q->queue_lock); } static inline void queue_flag_set_unlocked(unsigned int flag, @@ -445,7 +441,7 @@ static inline void queue_flag_set_unlocked(unsigned int flag, static inline int queue_flag_test_and_clear(unsigned int flag, struct request_queue *q) { - WARN_ON_ONCE(!queue_is_locked(q)); + queue_lockdep_assert_held(q); if (test_bit(flag, &q->queue_flags)) { __clear_bit(flag, &q->queue_flags); @@ -458,7 +454,7 @@ static inline int queue_flag_test_and_clear(unsigned int flag, static inline int queue_flag_test_and_set(unsigned int flag, struct request_queue *q) { - WARN_ON_ONCE(!queue_is_locked(q)); + queue_lockdep_assert_held(q); if (!test_bit(flag, &q->queue_flags)) { __set_bit(flag, &q->queue_flags); @@ -470,7 +466,7 @@ static inline int queue_flag_test_and_set(unsigned int flag, static inline void queue_flag_set(unsigned int flag, struct request_queue *q) { - WARN_ON_ONCE(!queue_is_locked(q)); + queue_lockdep_assert_held(q); __set_bit(flag, &q->queue_flags); } @@ -487,7 +483,7 @@ static inline int queue_in_flight(struct request_queue *q) static inline void queue_flag_clear(unsigned int flag, struct request_queue *q) { - WARN_ON_ONCE(!queue_is_locked(q)); + queue_lockdep_assert_held(q); __clear_bit(flag, &q->queue_flags); } diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 676f967390ae..f9a2e5e67a54 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -974,6 +974,7 @@ int dma_async_device_register(struct dma_device *device); void dma_async_device_unregister(struct dma_device *device); void dma_run_dependencies(struct dma_async_tx_descriptor *tx); struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type); +struct dma_chan *net_dma_find_channel(void); #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y) /* --- Helper iov-locking functions --- */ diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 8ba2c9460b28..8f2ab8fef929 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -593,7 +593,7 @@ struct fuse_dirent { __u64 off; __u32 namelen; __u32 type; - char name[0]; + char name[]; }; #define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name) diff --git a/include/linux/irq.h b/include/linux/irq.h index bff29c58da23..7810406f3d80 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -263,6 +263,11 @@ static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d) d->state_use_accessors &= ~IRQD_IRQ_INPROGRESS; } +static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d) +{ + return d->hwirq; +} + /** * struct irq_chip - hardware interrupt chip descriptor * diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index ead4a4215797..c65740d76e66 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -42,12 +42,6 @@ struct of_device_id; /* Number of irqs reserved for a legacy isa controller */ #define NUM_ISA_INTERRUPTS 16 -/* This type is the placeholder for a hardware interrupt number. It has to - * be big enough to enclose whatever representation is used by a given - * platform. - */ -typedef unsigned long irq_hw_number_t; - /** * struct irq_domain_ops - Methods for irq_domain objects * @match: Match an interrupt controller device node to a host, returns @@ -104,6 +98,9 @@ struct irq_domain { unsigned int size; unsigned int *revmap; } linear; + struct { + unsigned int max_irq; + } nomap; struct radix_tree_root tree; } revmap_data; const struct irq_domain_ops *ops; @@ -126,6 +123,7 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node, const struct irq_domain_ops *ops, void *host_data); struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, + unsigned int max_irq, const struct irq_domain_ops *ops, void *host_data); struct irq_domain *irq_domain_add_tree(struct device_node *of_node, @@ -134,7 +132,6 @@ struct irq_domain *irq_domain_add_tree(struct device_node *of_node, extern struct irq_domain *irq_find_host(struct device_node *node); extern void irq_set_default_host(struct irq_domain *host); -extern void irq_set_virq_count(unsigned int count); static inline struct irq_domain *irq_domain_add_legacy_isa( struct device_node *of_node, @@ -146,7 +143,6 @@ static inline struct irq_domain *irq_domain_add_legacy_isa( } extern struct irq_domain *irq_find_host(struct device_node *node); extern void irq_set_default_host(struct irq_domain *host); -extern void irq_set_virq_count(unsigned int count); extern unsigned int irq_create_mapping(struct irq_domain *host, diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h index 067eda0e4b32..be342b94c640 100644 --- a/include/linux/kconfig.h +++ b/include/linux/kconfig.h @@ -4,29 +4,43 @@ #include <generated/autoconf.h> /* - * Helper macros to use CONFIG_ options in C expressions. Note that + * Helper macros to use CONFIG_ options in C/CPP expressions. Note that * these only work with boolean and tristate options. */ /* + * Getting something that works in C and CPP for an arg that may or may + * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1" + * we match on the placeholder define, insert the "0," for arg1 and generate + * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one). + * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when + * the last step cherry picks the 2nd arg, we get a zero. + */ +#define __ARG_PLACEHOLDER_1 0, +#define config_enabled(cfg) _config_enabled(cfg) +#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value) +#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0) +#define ___config_enabled(__ignored, val, ...) val + +/* * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm', * 0 otherwise. * */ #define IS_ENABLED(option) \ - (__enabled_ ## option || __enabled_ ## option ## _MODULE) + (config_enabled(option) || config_enabled(option##_MODULE)) /* * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0 * otherwise. For boolean options, this is equivalent to * IS_ENABLED(CONFIG_FOO). */ -#define IS_BUILTIN(option) __enabled_ ## option +#define IS_BUILTIN(option) config_enabled(option) /* * IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0 * otherwise. */ -#define IS_MODULE(option) __enabled_ ## option ## _MODULE +#define IS_MODULE(option) config_enabled(option##_MODULE) #endif /* __LINUX_KCONFIG_H */ diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index f549adccc94c..1bc898b14a80 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -287,7 +287,17 @@ extern unsigned int ip6t_do_table(struct sk_buff *skb, struct xt_table *table); /* Check for an extension */ -extern int ip6t_ext_hdr(u8 nexthdr); +static inline int +ip6t_ext_hdr(u8 nexthdr) +{ return (nexthdr == IPPROTO_HOPOPTS) || + (nexthdr == IPPROTO_ROUTING) || + (nexthdr == IPPROTO_FRAGMENT) || + (nexthdr == IPPROTO_ESP) || + (nexthdr == IPPROTO_AH) || + (nexthdr == IPPROTO_NONE) || + (nexthdr == IPPROTO_DSTOPTS); +} + /* find specified header and get offset to it */ extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target, unsigned short *fragoff); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index f51bf2e70c69..2db407a40051 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -357,7 +357,7 @@ struct uart_port { #define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) #define UPF_EXAR_EFR ((__force upf_t) (1 << 25)) -#define UPF_IIR_ONCE ((__force upf_t) (1 << 26)) +#define UPF_BUG_THRE ((__force upf_t) (1 << 26)) /* The exact UART type is known and should not be probed. */ #define UPF_FIXED_TYPE ((__force upf_t) (1 << 27)) #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28)) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 33370271b8b2..70a3f8d49118 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -481,6 +481,7 @@ struct sk_buff { union { __u32 mark; __u32 dropcount; + __u32 avail_size; }; sk_buff_data_t transport_header; @@ -1366,6 +1367,18 @@ static inline int skb_tailroom(const struct sk_buff *skb) } /** + * skb_availroom - bytes at buffer end + * @skb: buffer to check + * + * Return the number of bytes of free space at the tail of an sk_buff + * allocated by sk_stream_alloc() + */ +static inline int skb_availroom(const struct sk_buff *skb) +{ + return skb_is_nonlinear(skb) ? 0 : skb->avail_size - skb->len; +} + +/** * skb_reserve - adjust headroom * @skb: buffer to alter * @len: bytes to move diff --git a/include/linux/stddef.h b/include/linux/stddef.h index 6a40c76bdcf1..1747b6787b9e 100644 --- a/include/linux/stddef.h +++ b/include/linux/stddef.h @@ -3,14 +3,10 @@ #include <linux/compiler.h> +#ifdef __KERNEL__ + #undef NULL -#if defined(__cplusplus) -#define NULL 0 -#else #define NULL ((void *)0) -#endif - -#ifdef __KERNEL__ enum { false = 0, diff --git a/include/linux/types.h b/include/linux/types.h index e5fa50345516..7f480db60231 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -210,6 +210,12 @@ typedef u32 phys_addr_t; typedef phys_addr_t resource_size_t; +/* + * This type is the placeholder for a hardware interrupt number. It has to be + * big enough to enclose whatever representation is used by a given platform. + */ +typedef unsigned long irq_hw_number_t; + typedef struct { int counter; } atomic_t; diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index fbb666b1b670..474283888233 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -28,13 +28,6 @@ /* parity check flag */ #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) -enum port_dev_state { - PORT_UNREGISTERED, - PORT_REGISTERING, - PORT_REGISTERED, - PORT_UNREGISTERING, -}; - /* USB serial flags */ #define USB_SERIAL_WRITE_BUSY 0 @@ -124,7 +117,6 @@ struct usb_serial_port { char throttle_req; unsigned long sysrq; /* sysrq timeout */ struct device dev; - enum port_dev_state dev_state; }; #define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev) diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h index 9c3120dca294..b572f80bdfd5 100644 --- a/include/linux/vgaarb.h +++ b/include/linux/vgaarb.h @@ -47,6 +47,8 @@ */ #define VGA_DEFAULT_DEVICE (NULL) +struct pci_dev; + /* For use by clients */ /** diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 344b0f972828..d47e523c9d83 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -92,6 +92,7 @@ enum { HCI_SERVICE_CACHE, HCI_LINK_KEYS, HCI_DEBUG_KEYS, + HCI_UNREGISTER, HCI_LE_SCAN, HCI_SSP_ENABLED, @@ -1327,8 +1328,8 @@ struct sockaddr_hci { #define HCI_DEV_NONE 0xffff #define HCI_CHANNEL_RAW 0 -#define HCI_CHANNEL_CONTROL 1 #define HCI_CHANNEL_MONITOR 2 +#define HCI_CHANNEL_CONTROL 3 struct hci_filter { unsigned long type_mask; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index daefaac51131..6822d2595aff 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -427,7 +427,7 @@ enum { static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; - return (test_bit(HCI_SSP_ENABLED, &hdev->flags) && + return (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && test_bit(HCI_CONN_SSP_ENABLED, &conn->flags)); } @@ -907,11 +907,13 @@ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type) { - u8 field_len; - size_t parsed; + size_t parsed = 0; - for (parsed = 0; parsed < data_len - 1; parsed += field_len) { - field_len = data[0]; + if (data_len < 2) + return false; + + while (parsed < data_len - 1) { + u8 field_len = data[0]; if (field_len == 0) break; diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index ffc1377e092e..ebfd91fc20f8 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -117,7 +117,7 @@ struct mgmt_mode { #define MGMT_OP_SET_DISCOVERABLE 0x0006 struct mgmt_cp_set_discoverable { __u8 val; - __u16 timeout; + __le16 timeout; } __packed; #define MGMT_SET_DISCOVERABLE_SIZE 3 diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 87d203ff7a8a..9210bdc7bd8d 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1327,7 +1327,7 @@ static inline struct ieee80211_rate * ieee80211_get_tx_rate(const struct ieee80211_hw *hw, const struct ieee80211_tx_info *c) { - if (WARN_ON(c->control.rates[0].idx < 0)) + if (WARN_ON_ONCE(c->control.rates[0].idx < 0)) return NULL; return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx]; } diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 377df4a28512..1e1198546c72 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -134,6 +134,9 @@ struct scsi_cmnd { static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd) { + if (!cmd->request->rq_disk) + return NULL; + return *(struct scsi_driver **)cmd->request->rq_disk->private_data; } diff --git a/include/sound/core.h b/include/sound/core.h index b6e0f57d451d..bc056687f647 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -325,6 +325,13 @@ void release_and_free_resource(struct resource *res); /* --- */ +/* sound printk debug levels */ +enum { + SND_PR_ALWAYS, + SND_PR_DEBUG, + SND_PR_VERBOSE, +}; + #if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK) __printf(4, 5) void __snd_printk(unsigned int level, const char *file, int line, @@ -354,6 +361,8 @@ void __snd_printk(unsigned int level, const char *file, int line, */ #define snd_printd(fmt, args...) \ __snd_printk(1, __FILE__, __LINE__, fmt, ##args) +#define _snd_printd(level, fmt, args...) \ + __snd_printk(level, __FILE__, __LINE__, fmt, ##args) /** * snd_BUG - give a BUG warning message and stack trace @@ -383,6 +392,7 @@ void __snd_printk(unsigned int level, const char *file, int line, #else /* !CONFIG_SND_DEBUG */ #define snd_printd(fmt, args...) do { } while (0) +#define _snd_printd(level, fmt, args...) do { } while (0) #define snd_BUG() do { } while (0) static inline int __snd_bug_on(int cond) { diff --git a/kernel/cred.c b/kernel/cred.c index 97b36eeca4c9..e70683d9ec32 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -386,6 +386,8 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) struct cred *new; int ret; + p->replacement_session_keyring = NULL; + if ( #ifdef CONFIG_KEYS !p->cred->thread_keyring && diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index cf1a4a68ce44..d1a758bc972a 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig @@ -62,7 +62,7 @@ config IRQ_DOMAIN_DEBUG help This option will show the mapping relationship between hardware irq numbers and Linux irq numbers. The mapping is exposed via debugfs - in the file "virq_mapping". + in the file "irq_domain_mapping". If you don't know what this means you don't need it. diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 3601f3fbf67c..0e0ba5f840b2 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -23,7 +23,6 @@ static LIST_HEAD(irq_domain_list); static DEFINE_MUTEX(irq_domain_mutex); static DEFINE_MUTEX(revmap_trees_mutex); -static unsigned int irq_virq_count = NR_IRQS; static struct irq_domain *irq_default_domain; /** @@ -184,13 +183,16 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node, } struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, + unsigned int max_irq, const struct irq_domain_ops *ops, void *host_data) { struct irq_domain *domain = irq_domain_alloc(of_node, IRQ_DOMAIN_MAP_NOMAP, ops, host_data); - if (domain) + if (domain) { + domain->revmap_data.nomap.max_irq = max_irq ? max_irq : ~0; irq_domain_add(domain); + } return domain; } @@ -262,22 +264,6 @@ void irq_set_default_host(struct irq_domain *domain) irq_default_domain = domain; } -/** - * irq_set_virq_count() - Set the maximum number of linux irqs - * @count: number of linux irqs, capped with NR_IRQS - * - * This is mainly for use by platforms like iSeries who want to program - * the virtual irq number in the controller to avoid the reverse mapping - */ -void irq_set_virq_count(unsigned int count) -{ - pr_debug("irq: Trying to set virq count to %d\n", count); - - BUG_ON(count < NUM_ISA_INTERRUPTS); - if (count < NR_IRQS) - irq_virq_count = count; -} - static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, irq_hw_number_t hwirq) { @@ -320,13 +306,12 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) pr_debug("irq: create_direct virq allocation failed\n"); return 0; } - if (virq >= irq_virq_count) { + if (virq >= domain->revmap_data.nomap.max_irq) { pr_err("ERROR: no free irqs available below %i maximum\n", - irq_virq_count); + domain->revmap_data.nomap.max_irq); irq_free_desc(virq); return 0; } - pr_debug("irq: create_direct obtained virq %d\n", virq); if (irq_setup_virq(domain, virq, virq)) { @@ -350,7 +335,8 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) unsigned int irq_create_mapping(struct irq_domain *domain, irq_hw_number_t hwirq) { - unsigned int virq, hint; + unsigned int hint; + int virq; pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq); @@ -377,13 +363,13 @@ unsigned int irq_create_mapping(struct irq_domain *domain, return irq_domain_legacy_revmap(domain, hwirq); /* Allocate a virtual interrupt number */ - hint = hwirq % irq_virq_count; + hint = hwirq % nr_irqs; if (hint == 0) hint++; virq = irq_alloc_desc_from(hint, 0); - if (!virq) + if (virq <= 0) virq = irq_alloc_desc_from(1, 0); - if (!virq) { + if (virq <= 0) { pr_debug("irq: -> virq allocation failed\n"); return 0; } @@ -515,7 +501,7 @@ unsigned int irq_find_mapping(struct irq_domain *domain, irq_hw_number_t hwirq) { unsigned int i; - unsigned int hint = hwirq % irq_virq_count; + unsigned int hint = hwirq % nr_irqs; /* Look for default domain if nececssary */ if (domain == NULL) @@ -536,7 +522,7 @@ unsigned int irq_find_mapping(struct irq_domain *domain, if (data && (data->domain == domain) && (data->hwirq == hwirq)) return i; i++; - if (i >= irq_virq_count) + if (i >= nr_irqs) i = 1; } while(i != hint); return 0; @@ -642,8 +628,9 @@ static int virq_debug_show(struct seq_file *m, void *private) void *data; int i; - seq_printf(m, "%-5s %-7s %-15s %-18s %s\n", "virq", "hwirq", - "chip name", "chip data", "domain name"); + seq_printf(m, "%-5s %-7s %-15s %-*s %s\n", "irq", "hwirq", + "chip name", (int)(2 * sizeof(void *) + 2), "chip data", + "domain name"); for (i = 1; i < nr_irqs; i++) { desc = irq_to_desc(i); @@ -666,7 +653,7 @@ static int virq_debug_show(struct seq_file *m, void *private) seq_printf(m, "%-15s ", p); data = irq_desc_get_chip_data(desc); - seq_printf(m, "0x%16p ", data); + seq_printf(m, data ? "0x%p " : " %p ", data); if (desc->irq_data.domain && desc->irq_data.domain->of_node) p = desc->irq_data.domain->of_node->full_name; diff --git a/kernel/irq_work.c b/kernel/irq_work.c index 0c56d44b9fd5..1588e3b2871b 100644 --- a/kernel/irq_work.c +++ b/kernel/irq_work.c @@ -11,6 +11,7 @@ #include <linux/irq_work.h> #include <linux/percpu.h> #include <linux/hardirq.h> +#include <linux/irqflags.h> #include <asm/processor.h> /* diff --git a/kernel/itimer.c b/kernel/itimer.c index 22000c3db0dd..8d262b467573 100644 --- a/kernel/itimer.c +++ b/kernel/itimer.c @@ -284,8 +284,12 @@ SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value, if (value) { if(copy_from_user(&set_buffer, value, sizeof(set_buffer))) return -EFAULT; - } else - memset((char *) &set_buffer, 0, sizeof(set_buffer)); + } else { + memset(&set_buffer, 0, sizeof(set_buffer)); + printk_once(KERN_WARNING "%s calls setitimer() with new_value NULL pointer." + " Misfeature support will be removed\n", + current->comm); + } error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : NULL); if (error || !ovalue) diff --git a/kernel/panic.c b/kernel/panic.c index 80aed44e345a..8ed89a175d79 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -97,7 +97,7 @@ void panic(const char *fmt, ...) /* * Avoid nested stack-dumping if a panic occurs during oops processing */ - if (!oops_in_progress) + if (!test_taint(TAINT_DIE) && oops_in_progress <= 1) dump_stack(); #endif diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig index 2cf9cc7aa103..a20dc8a3c949 100644 --- a/kernel/time/Kconfig +++ b/kernel/time/Kconfig @@ -1,6 +1,10 @@ # # Timer subsystem related configuration options # + +# Core internal switch. Selected by NO_HZ / HIGH_RES_TIMERS. This is +# only related to the tick functionality. Oneshot clockevent devices +# are supported independ of this. config TICK_ONESHOT bool diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index e883f57a3cd3..bf57abdc7bd0 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -575,10 +575,12 @@ void tick_broadcast_switch_to_oneshot(void) unsigned long flags; raw_spin_lock_irqsave(&tick_broadcast_lock, flags); + + tick_broadcast_device.mode = TICKDEV_MODE_ONESHOT; + if (cpumask_empty(tick_get_broadcast_mask())) goto end; - tick_broadcast_device.mode = TICKDEV_MODE_ONESHOT; bc = tick_broadcast_device.evtdev; if (bc) tick_broadcast_setup_oneshot(bc); diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 3526038f2836..6a3a5b9ff561 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -534,9 +534,9 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now) hrtimer_get_expires(&ts->sched_timer), 0)) break; } - /* Update jiffies and reread time */ - tick_do_update_jiffies64(now); + /* Reread time and update jiffies */ now = ktime_get(); + tick_do_update_jiffies64(now); } } diff --git a/lib/kobject.c b/lib/kobject.c index 21dee7c19afd..aeefa8bc8b1c 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -192,14 +192,14 @@ static int kobject_add_internal(struct kobject *kobj) /* be noisy on error issues */ if (error == -EEXIST) - printk(KERN_ERR "%s failed for %s with " - "-EEXIST, don't try to register things with " - "the same name in the same directory.\n", - __func__, kobject_name(kobj)); + WARN(1, "%s failed for %s with " + "-EEXIST, don't try to register things with " + "the same name in the same directory.\n", + __func__, kobject_name(kobj)); else - printk(KERN_ERR "%s failed for %s (%d)\n", - __func__, kobject_name(kobj), error); - dump_stack(); + WARN(1, "%s failed for %s (error: %d parent: %s)\n", + __func__, kobject_name(kobj), error, + parent ? kobject_name(parent) : "'none'"); } else kobj->state_in_sysfs = 1; diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c index 2f526627e4f5..0c505361da19 100644 --- a/lib/mpi/mpi-bit.c +++ b/lib/mpi/mpi-bit.c @@ -177,8 +177,8 @@ int mpi_rshift(MPI x, MPI a, unsigned n) */ int mpi_lshift_limbs(MPI a, unsigned int count) { - mpi_ptr_t ap = a->d; - int n = a->nlimbs; + const int n = a->nlimbs; + mpi_ptr_t ap; int i; if (!count || !n) @@ -187,6 +187,7 @@ int mpi_lshift_limbs(MPI a, unsigned int count) if (RESIZE_IF_NEEDED(a, n + count) < 0) return -ENOMEM; + ap = a->d; for (i = n - 1; i >= 0; i--) ap[i + count] = ap[i]; for (i = 0; i < count; i++) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index b8ce6f450956..cd65cb19c941 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2791,6 +2791,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, * so no worry about deadlock. */ page = pte_page(entry); + get_page(page); if (page != pagecache_page) lock_page(page); @@ -2822,6 +2823,7 @@ out_page_table_lock: } if (page != pagecache_page) unlock_page(page); + put_page(page); out_mutex: mutex_unlock(&hugetlb_instantiation_mutex); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 7d698df4a067..a7165a60d0a7 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2165,7 +2165,7 @@ static int __cpuinit memcg_cpu_hotplug_callback(struct notifier_block *nb, if (action == CPU_ONLINE) return NOTIFY_OK; - if ((action != CPU_DEAD) || action != CPU_DEAD_FROZEN) + if (action != CPU_DEAD && action != CPU_DEAD_FROZEN) return NOTIFY_OK; for_each_mem_cgroup(iter) @@ -3763,7 +3763,7 @@ move_account: goto try_to_free; cond_resched(); /* "ret" should also be checked to ensure all lists are empty. */ - } while (memcg->res.usage > 0 || ret); + } while (res_counter_read_u64(&memcg->res, RES_USAGE) > 0 || ret); out: css_put(&memcg->css); return ret; @@ -3778,7 +3778,7 @@ try_to_free: lru_add_drain_all(); /* try to free all pages in this cgroup */ shrink = 1; - while (nr_retries && memcg->res.usage > 0) { + while (nr_retries && res_counter_read_u64(&memcg->res, RES_USAGE) > 0) { int progress; if (signal_pending(current)) { diff --git a/mm/vmscan.c b/mm/vmscan.c index 33c332bbab73..1a518684a32f 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2107,12 +2107,7 @@ restart: * with multiple processes reclaiming pages, the total * freeing target can get unreasonably large. */ - if (nr_reclaimed >= nr_to_reclaim) - nr_to_reclaim = 0; - else - nr_to_reclaim -= nr_reclaimed; - - if (!nr_to_reclaim && priority < DEF_PRIORITY) + if (nr_reclaimed >= nr_to_reclaim && priority < DEF_PRIORITY) break; } blk_finish_plug(&plug); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index e33af63a884a..92a857e3786d 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -665,6 +665,11 @@ int hci_dev_open(__u16 dev) hci_req_lock(hdev); + if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) { + ret = -ENODEV; + goto done; + } + if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) { ret = -ERFKILL; goto done; @@ -1849,6 +1854,8 @@ void hci_unregister_dev(struct hci_dev *hdev) BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); + set_bit(HCI_UNREGISTER, &hdev->dev_flags); + write_lock(&hci_dev_list_lock); list_del(&hdev->list); write_unlock(&hci_dev_list_lock); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b8e17e4dac8b..94552b33d528 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1308,6 +1308,7 @@ static void l2cap_monitor_timeout(struct work_struct *work) if (chan->retry_count >= chan->remote_max_tx) { l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); l2cap_chan_unlock(chan); + l2cap_chan_put(chan); return; } @@ -1316,6 +1317,7 @@ static void l2cap_monitor_timeout(struct work_struct *work) l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); l2cap_chan_unlock(chan); + l2cap_chan_put(chan); } static void l2cap_retrans_timeout(struct work_struct *work) @@ -1335,6 +1337,7 @@ static void l2cap_retrans_timeout(struct work_struct *work) l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); l2cap_chan_unlock(chan); + l2cap_chan_put(chan); } static void l2cap_drop_acked_frames(struct l2cap_chan *chan) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index c4fe583b0af6..29122ed28ea9 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -82,7 +82,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) } if (la.l2_cid) - err = l2cap_add_scid(chan, la.l2_cid); + err = l2cap_add_scid(chan, __le16_to_cpu(la.l2_cid)); else err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm); @@ -123,7 +123,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al if (la.l2_cid && la.l2_psm) return -EINVAL; - err = l2cap_chan_connect(chan, la.l2_psm, la.l2_cid, &la.l2_bdaddr); + err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), + &la.l2_bdaddr); if (err) return err; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7fcff8887131..4ef275c69675 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2523,13 +2523,18 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, if (cp->val) { type = PAGE_SCAN_TYPE_INTERLACED; - acp.interval = 0x0024; /* 22.5 msec page scan interval */ + + /* 22.5 msec page scan interval */ + acp.interval = __constant_cpu_to_le16(0x0024); } else { type = PAGE_SCAN_TYPE_STANDARD; /* default */ - acp.interval = 0x0800; /* default 1.28 sec page scan */ + + /* default 1.28 sec page scan */ + acp.interval = __constant_cpu_to_le16(0x0800); } - acp.window = 0x0012; /* default 11.25 msec page scan window */ + /* default 11.25 msec page scan window */ + acp.window = __constant_cpu_to_le16(0x0012); err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), &acp); @@ -2936,7 +2941,7 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, name, name_len); if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0) - eir_len = eir_append_data(&ev->eir[eir_len], eir_len, + eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV, dev_class, 3); put_unaligned_le16(eir_len, &ev->eir_len); diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 702a1ae9220b..27ca25ed7021 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -241,7 +241,6 @@ static void br_multicast_group_expired(unsigned long data) hlist_del_rcu(&mp->hlist[mdb->ver]); mdb->size--; - del_timer(&mp->query_timer); call_rcu_bh(&mp->rcu, br_multicast_free_group); out: @@ -271,7 +270,6 @@ static void br_multicast_del_pg(struct net_bridge *br, rcu_assign_pointer(*pp, p->next); hlist_del_init(&p->mglist); del_timer(&p->timer); - del_timer(&p->query_timer); call_rcu_bh(&p->rcu, br_multicast_free_pg); if (!mp->ports && !mp->mglist && @@ -507,74 +505,6 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, return NULL; } -static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp) -{ - struct net_bridge *br = mp->br; - struct sk_buff *skb; - - skb = br_multicast_alloc_query(br, &mp->addr); - if (!skb) - goto timer; - - netif_rx(skb); - -timer: - if (++mp->queries_sent < br->multicast_last_member_count) - mod_timer(&mp->query_timer, - jiffies + br->multicast_last_member_interval); -} - -static void br_multicast_group_query_expired(unsigned long data) -{ - struct net_bridge_mdb_entry *mp = (void *)data; - struct net_bridge *br = mp->br; - - spin_lock(&br->multicast_lock); - if (!netif_running(br->dev) || !mp->mglist || - mp->queries_sent >= br->multicast_last_member_count) - goto out; - - br_multicast_send_group_query(mp); - -out: - spin_unlock(&br->multicast_lock); -} - -static void br_multicast_send_port_group_query(struct net_bridge_port_group *pg) -{ - struct net_bridge_port *port = pg->port; - struct net_bridge *br = port->br; - struct sk_buff *skb; - - skb = br_multicast_alloc_query(br, &pg->addr); - if (!skb) - goto timer; - - br_deliver(port, skb); - -timer: - if (++pg->queries_sent < br->multicast_last_member_count) - mod_timer(&pg->query_timer, - jiffies + br->multicast_last_member_interval); -} - -static void br_multicast_port_group_query_expired(unsigned long data) -{ - struct net_bridge_port_group *pg = (void *)data; - struct net_bridge_port *port = pg->port; - struct net_bridge *br = port->br; - - spin_lock(&br->multicast_lock); - if (!netif_running(br->dev) || hlist_unhashed(&pg->mglist) || - pg->queries_sent >= br->multicast_last_member_count) - goto out; - - br_multicast_send_port_group_query(pg); - -out: - spin_unlock(&br->multicast_lock); -} - static struct net_bridge_mdb_entry *br_multicast_get_group( struct net_bridge *br, struct net_bridge_port *port, struct br_ip *group, int hash) @@ -690,8 +620,6 @@ rehash: mp->addr = *group; setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); - setup_timer(&mp->query_timer, br_multicast_group_query_expired, - (unsigned long)mp); hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); mdb->size++; @@ -746,8 +674,6 @@ static int br_multicast_add_group(struct net_bridge *br, hlist_add_head(&p->mglist, &port->mglist); setup_timer(&p->timer, br_multicast_port_group_expired, (unsigned long)p); - setup_timer(&p->query_timer, br_multicast_port_group_query_expired, - (unsigned long)p); rcu_assign_pointer(*pp, p); @@ -1291,9 +1217,6 @@ static void br_multicast_leave_group(struct net_bridge *br, time_after(mp->timer.expires, time) : try_to_del_timer_sync(&mp->timer) >= 0)) { mod_timer(&mp->timer, time); - - mp->queries_sent = 0; - mod_timer(&mp->query_timer, now); } goto out; @@ -1310,9 +1233,6 @@ static void br_multicast_leave_group(struct net_bridge *br, time_after(p->timer.expires, time) : try_to_del_timer_sync(&p->timer) >= 0)) { mod_timer(&p->timer, time); - - p->queries_sent = 0; - mod_timer(&p->query_timer, now); } break; @@ -1681,7 +1601,6 @@ void br_multicast_stop(struct net_bridge *br) hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i], hlist[ver]) { del_timer(&mp->timer); - del_timer(&mp->query_timer); call_rcu_bh(&mp->rcu, br_multicast_free_group); } } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 0b67a63ad7a8..e1d882257877 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -82,9 +82,7 @@ struct net_bridge_port_group { struct hlist_node mglist; struct rcu_head rcu; struct timer_list timer; - struct timer_list query_timer; struct br_ip addr; - u32 queries_sent; }; struct net_bridge_mdb_entry @@ -94,10 +92,8 @@ struct net_bridge_mdb_entry struct net_bridge_port_group __rcu *ports; struct rcu_head rcu; struct timer_list timer; - struct timer_list query_timer; struct br_ip addr; bool mglist; - u32 queries_sent; }; struct net_bridge_mdb_htable diff --git a/net/core/skbuff.c b/net/core/skbuff.c index baf8d281152c..e59840010d45 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -952,9 +952,11 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, goto adjust_others; } - data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask); + data = kmalloc(size + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)), + gfp_mask); if (!data) goto nodata; + size = SKB_WITH_OVERHEAD(ksize(data)); /* Copy only real data... and, alas, header. This should be * optimized for the cases when header is void. diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index de9da21113a1..cf73cc70ed2d 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -74,16 +74,24 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); if (iph == NULL) - return -NF_DROP; + return -NF_ACCEPT; /* Conntrack defragments packets, we might still see fragments * inside ICMP packets though. */ if (iph->frag_off & htons(IP_OFFSET)) - return -NF_DROP; + return -NF_ACCEPT; *dataoff = nhoff + (iph->ihl << 2); *protonum = iph->protocol; + /* Check bogus IP headers */ + if (*dataoff > skb->len) { + pr_debug("nf_conntrack_ipv4: bogus IPv4 packet: " + "nhoff %u, ihl %u, skblen %u\n", + nhoff, iph->ihl << 2, skb->len); + return -NF_ACCEPT; + } + return NF_ACCEPT; } diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 5d54ed30e821..8bb6adeb62c0 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -701,11 +701,12 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp) skb = alloc_skb_fclone(size + sk->sk_prot->max_header, gfp); if (skb) { if (sk_wmem_schedule(sk, skb->truesize)) { + skb_reserve(skb, sk->sk_prot->max_header); /* * Make sure that we have exactly size bytes * available to the caller, no more, no less. */ - skb_reserve(skb, skb_tailroom(skb) - size); + skb->avail_size = size; return skb; } __kfree_skb(skb); @@ -995,10 +996,9 @@ new_segment: copy = seglen; /* Where to copy to? */ - if (skb_tailroom(skb) > 0) { + if (skb_availroom(skb) > 0) { /* We have some space in skb head. Superb! */ - if (copy > skb_tailroom(skb)) - copy = skb_tailroom(skb); + copy = min_t(int, copy, skb_availroom(skb)); err = skb_add_data_nocache(sk, skb, from, copy); if (err) goto do_fault; @@ -1452,7 +1452,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if ((available < target) && (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) && !sysctl_tcp_low_latency && - dma_find_channel(DMA_MEMCPY)) { + net_dma_find_channel()) { preempt_enable_no_resched(); tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len); @@ -1667,7 +1667,7 @@ do_prequeue: if (!(flags & MSG_TRUNC)) { #ifdef CONFIG_NET_DMA if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) - tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); + tp->ucopy.dma_chan = net_dma_find_channel(); if (tp->ucopy.dma_chan) { tp->ucopy.dma_cookie = dma_skb_copy_datagram_iovec( @@ -3302,8 +3302,7 @@ void __init tcp_init(void) tcp_init_mem(&init_net); /* Set per-socket limits to no more than 1/128 the pressure threshold */ - limit = nr_free_buffer_pages() << (PAGE_SHIFT - 10); - limit = max(limit, 128UL); + limit = nr_free_buffer_pages() << (PAGE_SHIFT - 7); max_share = min(4UL*1024*1024, limit); sysctl_tcp_wmem[0] = SK_MEM_QUANTUM; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e886e2f7fa8d..9944c1d9a218 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -474,8 +474,11 @@ static void tcp_rcv_rtt_update(struct tcp_sock *tp, u32 sample, int win_dep) if (!win_dep) { m -= (new_sample >> 3); new_sample += m; - } else if (m < new_sample) - new_sample = m << 3; + } else { + m <<= 3; + if (m < new_sample) + new_sample = m; + } } else { /* No previous measure. */ new_sample = m << 3; @@ -5225,7 +5228,7 @@ static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, return 0; if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) - tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); + tp->ucopy.dma_chan = net_dma_find_channel(); if (tp->ucopy.dma_chan && skb_csum_unnecessary(skb)) { diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3a25cf743f8b..0cb86ceb652f 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1730,7 +1730,7 @@ process: #ifdef CONFIG_NET_DMA struct tcp_sock *tp = tcp_sk(sk); if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) - tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); + tp->ucopy.dma_chan = net_dma_find_channel(); if (tp->ucopy.dma_chan) ret = tcp_v4_do_rcv(sk, skb); else diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 364784a91939..376b2cfbb685 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2060,7 +2060,7 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to, /* Punt if not enough space exists in the first SKB for * the data in the second */ - if (skb->len > skb_tailroom(to)) + if (skb->len > skb_availroom(to)) break; if (after(TCP_SKB_CB(skb)->end_seq, tcp_wnd_end(tp))) diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 94874b0bdcdc..9d4e15559319 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -78,19 +78,6 @@ EXPORT_SYMBOL_GPL(ip6t_alloc_initial_table); Hence the start of any table is given by get_table() below. */ -/* Check for an extension */ -int -ip6t_ext_hdr(u8 nexthdr) -{ - return (nexthdr == IPPROTO_HOPOPTS) || - (nexthdr == IPPROTO_ROUTING) || - (nexthdr == IPPROTO_FRAGMENT) || - (nexthdr == IPPROTO_ESP) || - (nexthdr == IPPROTO_AH) || - (nexthdr == IPPROTO_NONE) || - (nexthdr == IPPROTO_DSTOPTS); -} - /* Returns whether matches rule or not. */ /* Performance critical - called for every packet */ static inline bool @@ -2366,7 +2353,6 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, EXPORT_SYMBOL(ip6t_register_table); EXPORT_SYMBOL(ip6t_unregister_table); EXPORT_SYMBOL(ip6t_do_table); -EXPORT_SYMBOL(ip6t_ext_hdr); EXPORT_SYMBOL(ipv6_find_hdr); module_init(ip6_tables_init); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 12c6ece67f39..86cfe6005f40 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1645,7 +1645,7 @@ process: #ifdef CONFIG_NET_DMA struct tcp_sock *tp = tcp_sk(sk); if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) - tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); + tp->ucopy.dma_chan = net_dma_find_channel(); if (tp->ucopy.dma_chan) ret = tcp_v6_do_rcv(sk, skb); else diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 576fb25456dd..f76da5b3f5c5 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3387,8 +3387,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, */ printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", sdata->name, ifmgd->bssid); - assoc_data->timeout = jiffies + - TU_TO_EXP_TIME(req->bss->beacon_interval); + assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); } else { assoc_data->have_beacon = true; assoc_data->sent_assoc = false; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 3cc4487ac349..729f157a0efa 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1592,7 +1592,7 @@ static int nf_conntrack_init_net(struct net *net) return 0; err_timeout: - nf_conntrack_timeout_fini(net); + nf_conntrack_ecache_fini(net); err_ecache: nf_conntrack_tstamp_fini(net); err_tstamp: diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 361eade62a09..0d07a1dcf605 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -584,8 +584,8 @@ static bool tcp_in_window(const struct nf_conn *ct, * Let's try to use the data from the packet. */ sender->td_end = end; - win <<= sender->td_scale; - sender->td_maxwin = (win == 0 ? 1 : win); + swin = win << sender->td_scale; + sender->td_maxwin = (swin == 0 ? 1 : swin); sender->td_maxend = end + sender->td_maxwin; /* * We haven't seen traffic in the other direction yet diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index 7b76eb7192f3..ef10ffcb4b6f 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c @@ -474,7 +474,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, while (remaining_len > 0) { - frag_len = min_t(u16, local->remote_miu, remaining_len); + frag_len = min_t(size_t, local->remote_miu, remaining_len); pr_debug("Fragment %zd bytes remaining %zd", frag_len, remaining_len); @@ -497,7 +497,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, release_sock(sk); remaining_len -= frag_len; - msg_ptr += len; + msg_ptr += frag_len; } kfree(msg_data); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e49da2797022..f432c57af05d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1294,6 +1294,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) goto bad_res; } + if (!netif_running(netdev)) { + result = -ENETDOWN; + goto bad_res; + } + nla_for_each_nested(nl_txq_params, info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], rem_txq_params) { @@ -6384,7 +6389,7 @@ static struct genl_ops nl80211_ops[] = { .doit = nl80211_get_key, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { @@ -6416,7 +6421,7 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, .doit = nl80211_set_beacon, - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { @@ -6424,7 +6429,7 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, .doit = nl80211_start_ap, - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { @@ -6432,7 +6437,7 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, .doit = nl80211_stop_ap, - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { @@ -6448,7 +6453,7 @@ static struct genl_ops nl80211_ops[] = { .doit = nl80211_set_station, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { @@ -6464,7 +6469,7 @@ static struct genl_ops nl80211_ops[] = { .doit = nl80211_del_station, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { @@ -6497,7 +6502,7 @@ static struct genl_ops nl80211_ops[] = { .doit = nl80211_del_mpath, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { @@ -6505,7 +6510,7 @@ static struct genl_ops nl80211_ops[] = { .doit = nl80211_set_bss, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { @@ -6531,7 +6536,7 @@ static struct genl_ops nl80211_ops[] = { .doit = nl80211_get_mesh_config, .policy = nl80211_policy, /* can be retrieved by unprivileged users */ - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { @@ -6664,7 +6669,7 @@ static struct genl_ops nl80211_ops[] = { .doit = nl80211_setdel_pmksa, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { @@ -6672,7 +6677,7 @@ static struct genl_ops nl80211_ops[] = { .doit = nl80211_setdel_pmksa, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { @@ -6680,7 +6685,7 @@ static struct genl_ops nl80211_ops[] = { .doit = nl80211_flush_pmksa, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { @@ -6840,7 +6845,7 @@ static struct genl_ops nl80211_ops[] = { .doit = nl80211_probe_client, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV | + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, { diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 0af7f54e4f61..af648e08e61b 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -780,8 +780,10 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, if (cmd == SIOCSIWENCODEEXT) { struct iw_encode_ext *ee = (void *) extra; - if (iwp->length < sizeof(*ee) + ee->key_len) - return -EFAULT; + if (iwp->length < sizeof(*ee) + ee->key_len) { + err = -EFAULT; + goto out; + } } } diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index de639eeeed50..faea0ec612bf 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1869,12 +1869,6 @@ sub process { "No space is necessary after a cast\n" . $hereprev); } - if ($rawline =~ /^\+[ \t]*\/\*[ \t]*$/ && - $prevrawline =~ /^\+[ \t]*$/) { - CHK("BLOCK_COMMENT_STYLE", - "Don't begin block comments with only a /* line, use /* comment...\n" . $hereprev); - } - # check for spaces at the beginning of a line. # Exceptions: # 1) within comments diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 0586085136d1..52577f052bc1 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -540,35 +540,6 @@ static struct conf_printer header_printer_cb = }; /* - * Generate the __enabled_CONFIG_* and __enabled_CONFIG_*_MODULE macros for - * use by the IS_{ENABLED,BUILTIN,MODULE} macros. The _MODULE variant is - * generated even for booleans so that the IS_ENABLED() macro works. - */ -static void -header_print__enabled_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) -{ - - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: { - fprintf(fp, "#define __enabled_" CONFIG_ "%s %d\n", - sym->name, (*value == 'y')); - fprintf(fp, "#define __enabled_" CONFIG_ "%s_MODULE %d\n", - sym->name, (*value == 'm')); - break; - } - default: - break; - } -} - -static struct conf_printer header__enabled_printer_cb = -{ - .print_symbol = header_print__enabled_symbol, - .print_comment = header_print_comment, -}; - -/* * Tristate printer * * This printer is used when generating the `include/config/tristate.conf' file. @@ -949,16 +920,11 @@ int conf_write_autoconf(void) conf_write_heading(out_h, &header_printer_cb, NULL); for_all_symbols(i, sym) { - if (!sym->name) - continue; - sym_calc_value(sym); - - conf_write_symbol(out_h, sym, &header__enabled_printer_cb, NULL); - - if (!(sym->flags & SYMBOL_WRITE)) + if (!(sym->flags & SYMBOL_WRITE) || !sym->name) continue; + /* write symbol to auto.conf, tristate and header files */ conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); diff --git a/scripts/xz_wrap.sh b/scripts/xz_wrap.sh index 17a5798c29da..7a2d372f4885 100644 --- a/scripts/xz_wrap.sh +++ b/scripts/xz_wrap.sh @@ -12,8 +12,8 @@ BCJ= LZMA2OPTS= -case $ARCH in - x86|x86_64) BCJ=--x86 ;; +case $SRCARCH in + x86) BCJ=--x86 ;; powerpc) BCJ=--powerpc ;; ia64) BCJ=--ia64; LZMA2OPTS=pb=4 ;; arm) BCJ=--arm ;; diff --git a/security/commoncap.c b/security/commoncap.c index 0cf4b53480a7..71a166a05975 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -29,6 +29,7 @@ #include <linux/securebits.h> #include <linux/user_namespace.h> #include <linux/binfmts.h> +#include <linux/personality.h> /* * If a non-root user executes a setuid-root binary in @@ -505,6 +506,11 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) } skip: + /* if we have fs caps, clear dangerous personality flags */ + if (!cap_issubset(new->cap_permitted, old->cap_permitted)) + bprm->per_clear |= PER_CLEAR_ON_SETID; + + /* Don't let someone trace a set[ug]id/setpcap binary with the revised * credentials unless they have the appropriate permit */ diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 81c03a597112..45c32f074166 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1939,18 +1939,19 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) char *hostsp; struct socket_smack *ssp = sk->sk_security; struct smk_audit_info ad; - struct lsm_network_audit net; rcu_read_lock(); hostsp = smack_host_label(sap); if (hostsp != NULL) { - sk_lbl = SMACK_UNLABELED_SOCKET; #ifdef CONFIG_AUDIT + struct lsm_network_audit net; + smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); ad.a.u.net->family = sap->sin_family; ad.a.u.net->dport = sap->sin_port; ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr; #endif + sk_lbl = SMACK_UNLABELED_SOCKET; rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad); } else { sk_lbl = SMACK_CIPSO_SOCKET; @@ -2809,11 +2810,14 @@ static int smack_unix_stream_connect(struct sock *sock, struct socket_smack *osp = other->sk_security; struct socket_smack *nsp = newsk->sk_security; struct smk_audit_info ad; - struct lsm_network_audit net; int rc = 0; +#ifdef CONFIG_AUDIT + struct lsm_network_audit net; + smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); smk_ad_setfield_u_net_sk(&ad, other); +#endif if (!capable(CAP_MAC_OVERRIDE)) rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); @@ -2842,11 +2846,14 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) struct socket_smack *ssp = sock->sk->sk_security; struct socket_smack *osp = other->sk->sk_security; struct smk_audit_info ad; - struct lsm_network_audit net; int rc = 0; +#ifdef CONFIG_AUDIT + struct lsm_network_audit net; + smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); smk_ad_setfield_u_net_sk(&ad, other->sk); +#endif if (!capable(CAP_MAC_OVERRIDE)) rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); @@ -2993,7 +3000,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) char *csp; int rc; struct smk_audit_info ad; +#ifdef CONFIG_AUDIT struct lsm_network_audit net; +#endif if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) return 0; @@ -3156,7 +3165,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, char *sp; int rc; struct smk_audit_info ad; +#ifdef CONFIG_AUDIT struct lsm_network_audit net; +#endif /* handle mapped IPv4 packets arriving via IPv6 sockets */ if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) @@ -3629,8 +3640,38 @@ struct security_operations smack_ops = { }; -static __init void init_smack_know_list(void) +static __init void init_smack_known_list(void) { + /* + * Initialize CIPSO locks + */ + spin_lock_init(&smack_known_huh.smk_cipsolock); + spin_lock_init(&smack_known_hat.smk_cipsolock); + spin_lock_init(&smack_known_star.smk_cipsolock); + spin_lock_init(&smack_known_floor.smk_cipsolock); + spin_lock_init(&smack_known_invalid.smk_cipsolock); + spin_lock_init(&smack_known_web.smk_cipsolock); + /* + * Initialize rule list locks + */ + mutex_init(&smack_known_huh.smk_rules_lock); + mutex_init(&smack_known_hat.smk_rules_lock); + mutex_init(&smack_known_floor.smk_rules_lock); + mutex_init(&smack_known_star.smk_rules_lock); + mutex_init(&smack_known_invalid.smk_rules_lock); + mutex_init(&smack_known_web.smk_rules_lock); + /* + * Initialize rule lists + */ + INIT_LIST_HEAD(&smack_known_huh.smk_rules); + INIT_LIST_HEAD(&smack_known_hat.smk_rules); + INIT_LIST_HEAD(&smack_known_star.smk_rules); + INIT_LIST_HEAD(&smack_known_floor.smk_rules); + INIT_LIST_HEAD(&smack_known_invalid.smk_rules); + INIT_LIST_HEAD(&smack_known_web.smk_rules); + /* + * Create the known labels list + */ list_add(&smack_known_huh.list, &smack_known_list); list_add(&smack_known_hat.list, &smack_known_list); list_add(&smack_known_star.list, &smack_known_list); @@ -3665,16 +3706,8 @@ static __init int smack_init(void) cred = (struct cred *) current->cred; cred->security = tsp; - /* initialize the smack_know_list */ - init_smack_know_list(); - /* - * Initialize locks - */ - spin_lock_init(&smack_known_huh.smk_cipsolock); - spin_lock_init(&smack_known_hat.smk_cipsolock); - spin_lock_init(&smack_known_star.smk_cipsolock); - spin_lock_init(&smack_known_floor.smk_cipsolock); - spin_lock_init(&smack_known_invalid.smk_cipsolock); + /* initialize the smack_known_list */ + init_smack_known_list(); /* * Register with LSM diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 5c32f36ff706..038811cb7e62 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -1614,20 +1614,6 @@ static int __init init_smk_fs(void) smk_cipso_doi(); smk_unlbl_ambient(NULL); - mutex_init(&smack_known_floor.smk_rules_lock); - mutex_init(&smack_known_hat.smk_rules_lock); - mutex_init(&smack_known_huh.smk_rules_lock); - mutex_init(&smack_known_invalid.smk_rules_lock); - mutex_init(&smack_known_star.smk_rules_lock); - mutex_init(&smack_known_web.smk_rules_lock); - - INIT_LIST_HEAD(&smack_known_floor.smk_rules); - INIT_LIST_HEAD(&smack_known_hat.smk_rules); - INIT_LIST_HEAD(&smack_known_huh.smk_rules); - INIT_LIST_HEAD(&smack_known_invalid.smk_rules); - INIT_LIST_HEAD(&smack_known_star.smk_rules); - INIT_LIST_HEAD(&smack_known_web.smk_rules); - return err; } diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index b4a6aa960f4b..8490f59709bb 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -1019,13 +1019,15 @@ static int __devinit create_sscape(int dev, struct snd_card *card) irq_cfg = get_irq_config(sscape->type, irq[dev]); if (irq_cfg == INVALID_IRQ) { snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]); - return -ENXIO; + err = -ENXIO; + goto _release_dma; } mpu_irq_cfg = get_irq_config(sscape->type, mpu_irq[dev]); if (mpu_irq_cfg == INVALID_IRQ) { snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]); - return -ENXIO; + err = -ENXIO; + goto _release_dma; } /* diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c index 2c79d60a725f..536c4c0514d3 100644 --- a/sound/oss/msnd_pinnacle.c +++ b/sound/oss/msnd_pinnacle.c @@ -1294,6 +1294,8 @@ static int __init calibrate_adc(WORD srate) static int upload_dsp_code(void) { + int ret = 0; + msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS); #ifndef HAVE_DSPCODEH INITCODESIZE = mod_firmware_load(INITCODEFILE, &INITCODE); @@ -1312,7 +1314,8 @@ static int upload_dsp_code(void) memcpy_toio(dev.base, PERMCODE, PERMCODESIZE); if (msnd_upload_host(&dev, INITCODE, INITCODESIZE) < 0) { printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n"); - return -ENODEV; + ret = -ENODEV; + goto out; } #ifdef HAVE_DSPCODEH printk(KERN_INFO LOGNAME ": DSP firmware uploaded (resident)\n"); @@ -1320,12 +1323,13 @@ static int upload_dsp_code(void) printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n"); #endif +out: #ifndef HAVE_DSPCODEH vfree(INITCODE); vfree(PERMCODE); #endif - return 0; + return ret; } #ifdef MSND_CLASSIC diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 88168044375f..5ca0939e4223 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -2,8 +2,8 @@ config SND_TEA575X tristate - depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 - default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 + depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO + default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO menuconfig SND_PCI bool "PCI sound devices" diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h index 8c63200cf339..bc86cb726d79 100644 --- a/sound/pci/asihpi/hpi_internal.h +++ b/sound/pci/asihpi/hpi_internal.h @@ -1,7 +1,7 @@ /****************************************************************************** AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> + Copyright (C) 1997-2012 AudioScience Inc. <support@audioscience.com> This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as @@ -42,7 +42,7 @@ On error *pLockedMemHandle marked invalid, non-zero returned. If this function succeeds, then HpiOs_LockedMem_GetVirtAddr() and HpiOs_LockedMem_GetPyhsAddr() will always succed on the returned handle. */ -int hpios_locked_mem_alloc(struct consistent_dma_area *p_locked_mem_handle, +u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_locked_mem_handle, /**< memory handle */ u32 size, /**< Size in bytes to allocate */ struct pci_dev *p_os_reference diff --git a/sound/pci/asihpi/hpios.c b/sound/pci/asihpi/hpios.c index 87f4385fe8c7..5ef4fe964366 100644 --- a/sound/pci/asihpi/hpios.c +++ b/sound/pci/asihpi/hpios.c @@ -1,7 +1,7 @@ /****************************************************************************** AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> + Copyright (C) 1997-2012 AudioScience Inc. <support@audioscience.com> This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as @@ -39,11 +39,11 @@ void hpios_delay_micro_seconds(u32 num_micro_sec) } -/** Allocated an area of locked memory for bus master DMA operations. +/** Allocate an area of locked memory for bus master DMA operations. -On error, return -ENOMEM, and *pMemArea.size = 0 +If allocation fails, return 1, and *pMemArea.size = 0 */ -int hpios_locked_mem_alloc(struct consistent_dma_area *p_mem_area, u32 size, +u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_mem_area, u32 size, struct pci_dev *pdev) { /*?? any benefit in using managed dmam_alloc_coherent? */ @@ -62,7 +62,7 @@ int hpios_locked_mem_alloc(struct consistent_dma_area *p_mem_area, u32 size, HPI_DEBUG_LOG(WARNING, "failed to allocate %d bytes locked memory\n", size); p_mem_area->size = 0; - return -ENOMEM; + return 1; } } diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 9a9f372e1be4..56b4f74c0b13 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -851,6 +851,9 @@ struct hda_codec { unsigned int pin_amp_workaround:1; /* pin out-amp takes index * (e.g. Conexant codecs) */ + unsigned int single_adc_amp:1; /* adc in-amp takes no index + * (e.g. CX20549 codec) + */ unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */ unsigned int pins_shutup:1; /* pins are shut up */ unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index b58b4b1687fa..4c054f4486b9 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -418,7 +418,7 @@ static void hdmi_show_short_audio_desc(struct cea_sad *a) else buf2[0] = '\0'; - printk(KERN_INFO "HDMI: supports coding type %s:" + _snd_printd(SND_PR_VERBOSE, "HDMI: supports coding type %s:" " channels = %d, rates =%s%s\n", cea_audio_coding_type_names[a->format], a->channels, @@ -442,14 +442,14 @@ void snd_hdmi_show_eld(struct hdmi_eld *e) { int i; - printk(KERN_INFO "HDMI: detected monitor %s at connection type %s\n", + _snd_printd(SND_PR_VERBOSE, "HDMI: detected monitor %s at connection type %s\n", e->monitor_name, eld_connection_type_names[e->conn_type]); if (e->spk_alloc) { char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf)); - printk(KERN_INFO "HDMI: available speakers:%s\n", buf); + _snd_printd(SND_PR_VERBOSE, "HDMI: available speakers:%s\n", buf); } for (i = 0; i < e->sad_count; i++) diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 254ab5204603..e59e2f059b6e 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -651,9 +651,16 @@ static void print_codec_info(struct snd_info_entry *entry, snd_iprintf(buffer, " Amp-In caps: "); print_amp_caps(buffer, codec, nid, HDA_INPUT); snd_iprintf(buffer, " Amp-In vals: "); - print_amp_vals(buffer, codec, nid, HDA_INPUT, - wid_caps & AC_WCAP_STEREO, - wid_type == AC_WID_PIN ? 1 : conn_len); + if (wid_type == AC_WID_PIN || + (codec->single_adc_amp && + wid_type == AC_WID_AUD_IN)) + print_amp_vals(buffer, codec, nid, HDA_INPUT, + wid_caps & AC_WCAP_STEREO, + 1); + else + print_amp_vals(buffer, codec, nid, HDA_INPUT, + wid_caps & AC_WCAP_STEREO, + conn_len); } if (wid_caps & AC_WCAP_OUT_AMP) { snd_iprintf(buffer, " Amp-Out caps: "); diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 8c6523bbc797..a36488d94aaa 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -141,7 +141,6 @@ struct conexant_spec { unsigned int hp_laptop:1; unsigned int asus:1; unsigned int pin_eapd_ctrls:1; - unsigned int single_adc_amp:1; unsigned int adc_switching:1; @@ -687,27 +686,26 @@ static const struct hda_channel_mode cxt5045_modes[1] = { static const struct hda_input_mux cxt5045_capture_source = { .num_items = 2, .items = { - { "IntMic", 0x1 }, - { "ExtMic", 0x2 }, + { "Internal Mic", 0x1 }, + { "Mic", 0x2 }, } }; static const struct hda_input_mux cxt5045_capture_source_benq = { - .num_items = 5, + .num_items = 4, .items = { - { "IntMic", 0x1 }, - { "ExtMic", 0x2 }, - { "LineIn", 0x3 }, - { "CD", 0x4 }, - { "Mixer", 0x0 }, + { "Internal Mic", 0x1 }, + { "Mic", 0x2 }, + { "Line", 0x3 }, + { "Mixer", 0x0 }, } }; static const struct hda_input_mux cxt5045_capture_source_hp530 = { .num_items = 2, .items = { - { "ExtMic", 0x1 }, - { "IntMic", 0x2 }, + { "Mic", 0x1 }, + { "Internal Mic", 0x2 }, } }; @@ -798,10 +796,8 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec, } static const struct snd_kcontrol_new cxt5045_mixers[] = { - HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Internal Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x00, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x1, HDA_INPUT), @@ -822,27 +818,15 @@ static const struct snd_kcontrol_new cxt5045_mixers[] = { }; static const struct snd_kcontrol_new cxt5045_benq_mixers[] = { - HDA_CODEC_VOLUME("CD Capture Volume", 0x1a, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Capture Switch", 0x1a, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x4, HDA_INPUT), - - HDA_CODEC_VOLUME("Line In Capture Volume", 0x1a, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("Line In Capture Switch", 0x1a, 0x03, HDA_INPUT), - HDA_CODEC_VOLUME("Line In Playback Volume", 0x17, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("Line In Playback Switch", 0x17, 0x3, HDA_INPUT), - - HDA_CODEC_VOLUME("Mixer Capture Volume", 0x1a, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mixer Capture Switch", 0x1a, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x3, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x3, HDA_INPUT), {} }; static const struct snd_kcontrol_new cxt5045_mixers_hp530[] = { - HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Internal Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x00, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x2, HDA_INPUT), @@ -946,10 +930,10 @@ static const struct snd_kcontrol_new cxt5045_test_mixer[] = { /* Output controls */ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Node 11 Playback Volume", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Node 11 Playback Switch", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Node 12 Playback Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Node 12 Playback Switch", 0x12, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("HP-OUT Playback Volume", 0x11, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("HP-OUT Playback Switch", 0x11, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x12, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("LINE1 Playback Switch", 0x12, 0x0, HDA_OUTPUT), /* Modes for retasking pin widgets */ CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), @@ -960,16 +944,16 @@ static const struct snd_kcontrol_new cxt5045_test_mixer[] = { /* Loopback mixer controls */ - HDA_CODEC_VOLUME("Mixer-1 Volume", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mixer-1 Switch", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Mixer-2 Volume", 0x17, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Mixer-2 Switch", 0x17, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Mixer-3 Volume", 0x17, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("Mixer-3 Switch", 0x17, 0x2, HDA_INPUT), - HDA_CODEC_VOLUME("Mixer-4 Volume", 0x17, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("Mixer-4 Switch", 0x17, 0x3, HDA_INPUT), - HDA_CODEC_VOLUME("Mixer-5 Volume", 0x17, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("Mixer-5 Switch", 0x17, 0x4, HDA_INPUT), + HDA_CODEC_VOLUME("PCM Volume", 0x17, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("PCM Switch", 0x17, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("MIC1 pin Volume", 0x17, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("MIC1 pin Switch", 0x17, 0x1, HDA_INPUT), + HDA_CODEC_VOLUME("LINE1 pin Volume", 0x17, 0x2, HDA_INPUT), + HDA_CODEC_MUTE("LINE1 pin Switch", 0x17, 0x2, HDA_INPUT), + HDA_CODEC_VOLUME("HP-OUT pin Volume", 0x17, 0x3, HDA_INPUT), + HDA_CODEC_MUTE("HP-OUT pin Switch", 0x17, 0x3, HDA_INPUT), + HDA_CODEC_VOLUME("CD pin Volume", 0x17, 0x4, HDA_INPUT), + HDA_CODEC_MUTE("CD pin Switch", 0x17, 0x4, HDA_INPUT), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Input Source", @@ -978,16 +962,8 @@ static const struct snd_kcontrol_new cxt5045_test_mixer[] = { .put = conexant_mux_enum_put, }, /* Audio input controls */ - HDA_CODEC_VOLUME("Input-1 Volume", 0x1a, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Input-1 Switch", 0x1a, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Input-2 Volume", 0x1a, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Input-2 Switch", 0x1a, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Input-3 Volume", 0x1a, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("Input-3 Switch", 0x1a, 0x2, HDA_INPUT), - HDA_CODEC_VOLUME("Input-4 Volume", 0x1a, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("Input-4 Switch", 0x1a, 0x3, HDA_INPUT), - HDA_CODEC_VOLUME("Input-5 Volume", 0x1a, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("Input-5 Switch", 0x1a, 0x4, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), { } /* end */ }; @@ -1009,10 +985,6 @@ static const struct hda_verb cxt5045_test_init_verbs[] = { {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0}, - /* Start with output sum widgets muted and their output gains at min */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Unmute retasking pin widget output buffers since the default * state appears to be output. As the pin mode is changed by the * user the pin mode control will take care of enabling the pin's @@ -1027,11 +999,11 @@ static const struct hda_verb cxt5045_test_init_verbs[] = { /* Set ADC connection select to match default mixer setting (mic1 * pin) */ - {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x17, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, + {0x17, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Mute all inputs to mixer widget (even unconnected ones) */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */ + {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer */ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */ @@ -1110,7 +1082,7 @@ static int patch_cxt5045(struct hda_codec *codec) if (!spec) return -ENOMEM; codec->spec = spec; - codec->pin_amp_workaround = 1; + codec->single_adc_amp = 1; spec->multiout.max_channels = 2; spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); @@ -4220,7 +4192,7 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, int idx = get_input_connection(codec, adc_nid, nid); if (idx < 0) continue; - if (spec->single_adc_amp) + if (codec->single_adc_amp) idx = 0; return cx_auto_add_volume_idx(codec, label, pfx, cidx, adc_nid, HDA_INPUT, idx); @@ -4275,7 +4247,7 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) if (cidx < 0) continue; input_conn[i] = spec->imux_info[i].adc; - if (!spec->single_adc_amp) + if (!codec->single_adc_amp) input_conn[i] |= cidx << 8; if (i > 0 && input_conn[i] != input_conn[0]) multi_connection = 1; @@ -4466,15 +4438,17 @@ static int patch_conexant_auto(struct hda_codec *codec) if (!spec) return -ENOMEM; codec->spec = spec; - codec->pin_amp_workaround = 1; switch (codec->vendor_id) { case 0x14f15045: - spec->single_adc_amp = 1; + codec->single_adc_amp = 1; break; case 0x14f15051: add_cx5051_fake_mutes(codec); + codec->pin_amp_workaround = 1; break; + default: + codec->pin_amp_workaround = 1; } apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 540cd13f7f15..83f345f3c961 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -757,8 +757,6 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) struct hdmi_spec *spec = codec->spec; int tag = res >> AC_UNSOL_RES_TAG_SHIFT; int pin_nid; - int pd = !!(res & AC_UNSOL_RES_PD); - int eldv = !!(res & AC_UNSOL_RES_ELDV); int pin_idx; struct hda_jack_tbl *jack; @@ -768,9 +766,10 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) pin_nid = jack->nid; jack->jack_dirty = 1; - printk(KERN_INFO + _snd_printd(SND_PR_VERBOSE, "HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", - codec->addr, pin_nid, pd, eldv); + codec->addr, pin_nid, + !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV)); pin_idx = pin_nid_to_pin_index(spec, pin_nid); if (pin_idx < 0) @@ -992,7 +991,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) if (eld->monitor_present) eld_valid = !!(present & AC_PINSENSE_ELDV); - printk(KERN_INFO + _snd_printd(SND_PR_VERBOSE, "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", codec->addr, pin_nid, eld->monitor_present, eld_valid); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 9917e55d6f11..2508f8109f11 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3398,8 +3398,10 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) for (;;) { badness = fill_and_eval_dacs(codec, fill_hardwired, fill_mio_first); - if (badness < 0) + if (badness < 0) { + kfree(best_cfg); return badness; + } debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n", cfg->line_out_type, fill_hardwired, fill_mio_first, badness); @@ -3434,7 +3436,7 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; fill_hardwired = true; continue; - } + } if (cfg->hp_outs > 0 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { cfg->speaker_outs = cfg->line_outs; @@ -3448,7 +3450,7 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) cfg->line_out_type = AUTO_PIN_HP_OUT; fill_hardwired = true; continue; - } + } break; } @@ -4423,7 +4425,7 @@ static int alc_parse_auto_config(struct hda_codec *codec, static int alc880_parse_auto_config(struct hda_codec *codec) { static const hda_nid_t alc880_ignore[] = { 0x1d, 0 }; - static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 }; + static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 }; return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids); } @@ -5269,7 +5271,9 @@ static const struct alc_fixup alc882_fixups[] = { { 0x16, 0x99130111 }, /* CLFE speaker */ { 0x17, 0x99130112 }, /* surround speaker */ { } - } + }, + .chained = true, + .chain_id = ALC882_FIXUP_GPIO1, }, [ALC882_FIXUP_ACER_ASPIRE_8930G] = { .type = ALC_FIXUP_PINS, @@ -5312,7 +5316,9 @@ static const struct alc_fixup alc882_fixups[] = { { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 }, { } - } + }, + .chained = true, + .chain_id = ALC882_FIXUP_GPIO1, }, [ALC885_FIXUP_MACPRO_GPIO] = { .type = ALC_FIXUP_FUNC, @@ -5359,6 +5365,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { ALC882_FIXUP_ACER_ASPIRE_4930G), SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210), SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE), + SND_PCI_QUIRK(0x1025, 0x026b, "Acer Aspire 8940G", ALC882_FIXUP_ACER_ASPIRE_8930G), SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736), SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD), SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V), @@ -5384,6 +5391,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF), + SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO), SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF), @@ -5399,6 +5407,13 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { {} }; +static const struct alc_model_fixup alc882_fixup_models[] = { + {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"}, + {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"}, + {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"}, + {} +}; + /* * BIOS auto configuration */ @@ -5439,7 +5454,8 @@ static int patch_alc882(struct hda_codec *codec) if (err < 0) goto error; - alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups); + alc_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl, + alc882_fixups); alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); alc_auto_parse_customize_define(codec); @@ -6079,7 +6095,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { * Basically the device should work as is without the fixup table. * If BIOS doesn't give a proper info, enable the corresponding * fixup entry. - */ + */ SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", ALC269_FIXUP_AMIC), SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC), @@ -6296,7 +6312,7 @@ static void alc_fixup_no_jack_detect(struct hda_codec *codec, { if (action == ALC_FIXUP_ACT_PRE_PROBE) codec->no_jack_detect = 1; -} +} static const struct alc_fixup alc861_fixups[] = { [ALC861_FIXUP_FSC_AMILO_PI1505] = { @@ -6714,7 +6730,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { * Basically the device should work as is without the fixup table. * If BIOS doesn't give a proper info, enable the corresponding * fixup entry. - */ + */ SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3), SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1), diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index f8e10ced244a..b3e24f289421 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -140,7 +140,7 @@ * min : 0xFE : -115.0 dB * mute: 0xFF */ -static const DECLARE_TLV_DB_SCALE(out_tlv, -11500, 50, 1); +static const DECLARE_TLV_DB_SCALE(out_tlv, -11550, 50, 1); static const struct snd_kcontrol_new ak4642_snd_controls[] = { diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index d1926266fe00..8e92fb88ed09 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -143,11 +143,11 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, } /* - * using codec assist to small pop, hp_powerup or lineout_powerup - * should stay setting until vag_powerup is fully ramped down, - * vag fully ramped down require 400ms. + * As manual described, ADC/DAC only works when VAG powerup, + * So enabled VAG before ADC/DAC up. + * In power down case, we need wait 400ms when vag fully ramped down. */ -static int small_pop_event(struct snd_soc_dapm_widget *w, +static int power_vag_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { switch (event) { @@ -156,7 +156,7 @@ static int small_pop_event(struct snd_soc_dapm_widget *w, SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); break; - case SND_SOC_DAPM_PRE_PMD: + case SND_SOC_DAPM_POST_PMD: snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, SGTL5000_VAG_POWERUP, 0); msleep(400); @@ -201,12 +201,8 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = { mic_bias_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA_E("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0, - small_pop_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA_E("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0, - small_pop_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PGA("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0), + SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0), SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux), SND_SOC_DAPM_MUX("Headphone Mux", SND_SOC_NOPM, 0, 0, &dac_mux), @@ -221,8 +217,11 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = { 0, SGTL5000_CHIP_DIG_POWER, 1, 0), - SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), + SND_SOC_DAPM_SUPPLY("VAG_POWER", SGTL5000_CHIP_ANA_POWER, 7, 0, + power_vag_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0), }; @@ -231,9 +230,11 @@ static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = { {"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */ {"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */ + {"ADC", NULL, "VAG_POWER"}, {"ADC", NULL, "Capture Mux"}, /* adc_mux --> adc */ {"AIFOUT", NULL, "ADC"}, /* adc --> i2s_out */ + {"DAC", NULL, "VAG_POWER"}, {"DAC", NULL, "AIFIN"}, /* i2s-->dac,skip audio mux */ {"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */ {"LO", NULL, "DAC"}, /* dac --> line_out */ diff --git a/sound/soc/imx/imx-audmux.c b/sound/soc/imx/imx-audmux.c index 1765a197acb0..f23700359c67 100644 --- a/sound/soc/imx/imx-audmux.c +++ b/sound/soc/imx/imx-audmux.c @@ -73,6 +73,9 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, if (!buf) return -ENOMEM; + if (!audmux_base) + return -ENOSYS; + if (audmux_clk) clk_prepare_enable(audmux_clk); @@ -152,7 +155,7 @@ static void __init audmux_debugfs_init(void) return; } - for (i = 1; i < 8; i++) { + for (i = 0; i < MX31_AUDMUX_PORT6_SSI_PINS_6 + 1; i++) { snprintf(buf, sizeof(buf), "ssi%d", i); if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, (void *)i, &audmux_debugfs_fops)) diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 609abd51e55f..d08583790d23 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -17,6 +17,7 @@ #include <linux/delay.h> #include <linux/clk.h> #include <linux/platform_device.h> +#include <linux/io.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/initval.h> diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e19c24ade414..accdcb7d4d9d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1081,6 +1081,8 @@ static int soc_probe_platform(struct snd_soc_card *card, snd_soc_dapm_new_controls(&platform->dapm, driver->dapm_widgets, driver->num_dapm_widgets); + platform->dapm.idle_bias_off = 1; + if (driver->probe) { ret = driver->probe(platform); if (ret < 0) { diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c index 33509de52540..e53349912b2e 100644 --- a/sound/soc/tegra/tegra_i2s.c +++ b/sound/soc/tegra/tegra_i2s.c @@ -79,11 +79,15 @@ static int tegra_i2s_show(struct seq_file *s, void *unused) struct tegra_i2s *i2s = s->private; int i; + clk_enable(i2s->clk_i2s); + for (i = 0; i < ARRAY_SIZE(regs); i++) { u32 val = tegra_i2s_read(i2s, regs[i].offset); seq_printf(s, "%s = %08x\n", regs[i].name, val); } + clk_disable(i2s->clk_i2s); + return 0; } @@ -112,7 +116,7 @@ static void tegra_i2s_debug_remove(struct tegra_i2s *i2s) debugfs_remove(i2s->debug); } #else -static inline void tegra_i2s_debug_add(struct tegra_i2s *i2s, int id) +static inline void tegra_i2s_debug_add(struct tegra_i2s *i2s) { } diff --git a/sound/soc/tegra/tegra_spdif.c b/sound/soc/tegra/tegra_spdif.c index 475428cf270e..9ff2c601445f 100644 --- a/sound/soc/tegra/tegra_spdif.c +++ b/sound/soc/tegra/tegra_spdif.c @@ -79,11 +79,15 @@ static int tegra_spdif_show(struct seq_file *s, void *unused) struct tegra_spdif *spdif = s->private; int i; + clk_enable(spdif->clk_spdif_out); + for (i = 0; i < ARRAY_SIZE(regs); i++) { u32 val = tegra_spdif_read(spdif, regs[i].offset); seq_printf(s, "%s = %08x\n", regs[i].name, val); } + clk_disable(spdif->clk_spdif_out); + return 0; } diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore index 416684be0ad3..26b823b61aa1 100644 --- a/tools/perf/.gitignore +++ b/tools/perf/.gitignore @@ -19,3 +19,5 @@ TAGS cscope* config.mak config.mak.autogen +*-bison.* +*-flex.* diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 820371f10d1b..03059e75665a 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -237,21 +237,20 @@ export PERL_PATH FLEX = $(CROSS_COMPILE)flex BISON= $(CROSS_COMPILE)bison -event-parser: - $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c +$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c -$(OUTPUT)util/parse-events-flex.c: event-parser -$(OUTPUT)util/parse-events-bison.c: event-parser +$(OUTPUT)util/parse-events-bison.c: util/parse-events.y + $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c -pmu-parser: - $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c +$(OUTPUT)util/pmu-flex.c: util/pmu.l $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c -$(OUTPUT)util/pmu-flex.c: pmu-parser -$(OUTPUT)util/pmu-bison.c: pmu-parser +$(OUTPUT)util/pmu-bison.c: util/pmu.y + $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -$(OUTPUT)util/parse-events.o: event-parser pmu-parser +$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c +$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c LIB_FILE=$(OUTPUT)libperf.a @@ -527,7 +526,7 @@ else endif ifdef NO_GTK2 - BASIC_CFLAGS += -DNO_GTK2 + BASIC_CFLAGS += -DNO_GTK2_SUPPORT else FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0) ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y) @@ -852,8 +851,6 @@ help: @echo ' html - make html documentation' @echo ' info - make GNU info documentation (access with info <foo>)' @echo ' pdf - make pdf documentation' - @echo ' event-parser - make event parser code' - @echo ' pmu-parser - make pmu format parser code' @echo ' TAGS - use etags to make tag information for source browsing' @echo ' tags - use ctags to make tag information for source browsing' @echo ' cscope - use cscope to make interactive browsing database' diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index fb8b5f83b4a0..1cad3af4bf4c 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -17,6 +17,7 @@ #include "util/debug.h" #include <sys/prctl.h> +#include <sys/resource.h> #include <semaphore.h> #include <pthread.h> diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index e3c63aef8efc..8ef59f8262bb 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -42,6 +42,7 @@ #include "util/debug.h" #include <assert.h> +#include <elf.h> #include <fcntl.h> #include <stdio.h> @@ -59,6 +60,7 @@ #include <sys/prctl.h> #include <sys/wait.h> #include <sys/uio.h> +#include <sys/utsname.h> #include <sys/mman.h> #include <linux/unistd.h> @@ -162,12 +164,40 @@ static void __zero_source_counters(struct hist_entry *he) symbol__annotate_zero_histograms(sym); } +static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip) +{ + struct utsname uts; + int err = uname(&uts); + + ui__warning("Out of bounds address found:\n\n" + "Addr: %" PRIx64 "\n" + "DSO: %s %c\n" + "Map: %" PRIx64 "-%" PRIx64 "\n" + "Symbol: %" PRIx64 "-%" PRIx64 " %c %s\n" + "Arch: %s\n" + "Kernel: %s\n" + "Tools: %s\n\n" + "Not all samples will be on the annotation output.\n\n" + "Please report to linux-kernel@vger.kernel.org\n", + ip, map->dso->long_name, dso__symtab_origin(map->dso), + map->start, map->end, sym->start, sym->end, + sym->binding == STB_GLOBAL ? 'g' : + sym->binding == STB_LOCAL ? 'l' : 'w', sym->name, + err ? "[unknown]" : uts.machine, + err ? "[unknown]" : uts.release, perf_version_string); + if (use_browser <= 0) + sleep(5); + + map->erange_warned = true; +} + static void perf_top__record_precise_ip(struct perf_top *top, struct hist_entry *he, int counter, u64 ip) { struct annotation *notes; struct symbol *sym; + int err; if (he == NULL || he->ms.sym == NULL || ((top->sym_filter_entry == NULL || @@ -189,9 +219,12 @@ static void perf_top__record_precise_ip(struct perf_top *top, } ip = he->ms.map->map_ip(he->ms.map, ip); - symbol__inc_addr_samples(sym, he->ms.map, counter, ip); + err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip); pthread_mutex_unlock(¬es->lock); + + if (err == -ERANGE && !he->ms.map->erange_warned) + ui__warn_map_erange(he->ms.map, sym, ip); } static void perf_top__show_details(struct perf_top *top) @@ -615,6 +648,7 @@ process_hotkey: /* Tag samples to be skipped. */ static const char *skip_symbols[] = { + "intel_idle", "default_idle", "native_safe_halt", "cpu_idle", diff --git a/tools/perf/perf-archive.sh b/tools/perf/perf-archive.sh index 677e59d62a8d..95b6f8b6177a 100644 --- a/tools/perf/perf-archive.sh +++ b/tools/perf/perf-archive.sh @@ -29,13 +29,14 @@ if [ ! -s $BUILDIDS ] ; then fi MANIFEST=$(mktemp /tmp/perf-archive-manifest.XXXXXX) +PERF_BUILDID_LINKDIR=$(readlink -f $PERF_BUILDID_DIR)/ cut -d ' ' -f 1 $BUILDIDS | \ while read build_id ; do linkname=$PERF_BUILDID_DIR.build-id/${build_id:0:2}/${build_id:2} filename=$(readlink -f $linkname) echo ${linkname#$PERF_BUILDID_DIR} >> $MANIFEST - echo ${filename#$PERF_BUILDID_DIR} >> $MANIFEST + echo ${filename#$PERF_BUILDID_LINKDIR} >> $MANIFEST done tar cfj $PERF_DATA.tar.bz2 -C $PERF_BUILDID_DIR -T $MANIFEST diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 199f69ec656f..08c6d138a655 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -64,8 +64,8 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); - if (addr > sym->end) - return 0; + if (addr < sym->start || addr > sym->end) + return -ERANGE; offset = addr - sym->start; h = annotation__histogram(notes, evidx); @@ -561,16 +561,12 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx) { struct annotation *notes = symbol__annotation(sym); struct sym_hist *h = annotation__histogram(notes, evidx); - struct objdump_line *pos; - int len = sym->end - sym->start; + int len = sym->end - sym->start, offset; h->sum = 0; - - list_for_each_entry(pos, ¬es->src->source, node) { - if (pos->offset != -1 && pos->offset < len) { - h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8; - h->sum += h->addr[pos->offset]; - } + for (offset = 0; offset < len; ++offset) { + h->addr[offset] = h->addr[offset] * 7 / 8; + h->sum += h->addr[offset]; } } diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 2ec4b60aff6c..9f6d630d5316 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -256,6 +256,18 @@ static struct hist_entry *add_hist_entry(struct hists *hists, if (!cmp) { he->period += period; ++he->nr_events; + + /* If the map of an existing hist_entry has + * become out-of-date due to an exec() or + * similar, update it. Otherwise we will + * mis-adjust symbol addresses when computing + * the history counter to increment. + */ + if (he->ms.map != entry->ms.map) { + he->ms.map = entry->ms.map; + if (he->ms.map) + he->ms.map->referenced = true; + } goto out; } diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index dea6d1c1a954..35ae56864e4f 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -38,6 +38,7 @@ void map__init(struct map *self, enum map_type type, RB_CLEAR_NODE(&self->rb_node); self->groups = NULL; self->referenced = false; + self->erange_warned = false; } struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index b100c20b7f94..81371bad4ef0 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -33,6 +33,7 @@ struct map { u64 end; u8 /* enum map_type */ type; bool referenced; + bool erange_warned; u32 priv; u64 pgoff; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 9412e3b05f68..1efd3bee6336 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -826,8 +826,16 @@ static struct machine * { const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; - if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) - return perf_session__find_machine(session, event->ip.pid); + if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { + u32 pid; + + if (event->header.type == PERF_RECORD_MMAP) + pid = event->mmap.pid; + else + pid = event->ip.pid; + + return perf_session__find_machine(session, pid); + } return perf_session__find_host_machine(session); } @@ -868,11 +876,11 @@ static int perf_session_deliver_event(struct perf_session *session, dump_sample(session, event, sample); if (evsel == NULL) { ++session->hists.stats.nr_unknown_id; - return -1; + return 0; } if (machine == NULL) { ++session->hists.stats.nr_unprocessable_samples; - return -1; + return 0; } return tool->sample(tool, event, sample, evsel, machine); case PERF_RECORD_MMAP: diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index d7a1c4afe28b..2f83e5dc9967 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c @@ -125,6 +125,9 @@ static int callchain__count_rows(struct rb_root *chain) static bool map_symbol__toggle_fold(struct map_symbol *self) { + if (!self) + return false; + if (!self->has_children) return false; |