diff options
656 files changed, 5588 insertions, 9377 deletions
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index 2f7fd4360848..9c27e5125dd2 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -102,9 +102,12 @@ X!Iinclude/linux/kobject.h !Iinclude/linux/device.h </sect1> <sect1><title>Device Drivers Base</title> +!Idrivers/base/init.c !Edrivers/base/driver.c !Edrivers/base/core.c +!Edrivers/base/syscore.c !Edrivers/base/class.c +!Idrivers/base/node.c !Edrivers/base/firmware_class.c !Edrivers/base/transport_class.c <!-- Cannot be included, because @@ -113,7 +116,7 @@ X!Iinclude/linux/kobject.h exceed allowed 44 characters maximum X!Edrivers/base/attribute_container.c --> -!Edrivers/base/sys.c +!Edrivers/base/dd.c <!-- X!Edrivers/base/interface.c --> @@ -121,6 +124,11 @@ X!Edrivers/base/interface.c !Edrivers/base/platform.c !Edrivers/base/bus.c </sect1> + <sect1><title>Device Drivers DMA Management</title> +!Edrivers/base/dma-buf.c +!Edrivers/base/dma-coherent.c +!Edrivers/base/dma-mapping.c + </sect1> <sect1><title>Device Drivers Power Management</title> !Edrivers/base/power/main.c </sect1> @@ -219,7 +227,7 @@ X!Isound/sound_firmware.c <chapter id="uart16x50"> <title>16x50 UART Driver</title> !Edrivers/tty/serial/serial_core.c -!Edrivers/tty/serial/8250.c +!Edrivers/tty/serial/8250/8250.c </chapter> <chapter id="fbdev"> diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 10c64c8a13d4..41c0c5d1ba14 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -233,6 +233,10 @@ certainly invest a bit more effort into libata core layer). 6. List of managed interfaces ----------------------------- +MEM + devm_kzalloc() + devm_kfree() + IO region devm_request_region() devm_request_mem_region() diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 1bea46a54b1c..a0ffac029a0d 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -510,3 +510,17 @@ Why: The pci_scan_bus_parented() interface creates a new root bus. The convert to using pci_scan_root_bus() so they can supply a list of bus resources when the bus is created. Who: Bjorn Helgaas <bhelgaas@google.com> + +---------------------------- + +What: The CAP9 SoC family will be removed +When: 3.4 +Files: arch/arm/mach-at91/at91cap9.c + arch/arm/mach-at91/at91cap9_devices.c + arch/arm/mach-at91/include/mach/at91cap9.h + arch/arm/mach-at91/include/mach/at91cap9_matrix.h + arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h + arch/arm/mach-at91/board-cap9adk.c +Why: The code is not actively maintained and platforms are now hard to find. +Who: Nicolas Ferre <nicolas.ferre@atmel.com> + Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> diff --git a/Documentation/input/event-codes.txt b/Documentation/input/event-codes.txt index 23fcb05175be..53305bd08182 100644 --- a/Documentation/input/event-codes.txt +++ b/Documentation/input/event-codes.txt @@ -17,11 +17,11 @@ reports supported by a device are also provided by sysfs in class/input/event*/device/capabilities/, and the properties of a device are provided in class/input/event*/device/properties. -Types: -========== -Types are groupings of codes under a logical input construct. Each type has a -set of applicable codes to be used in generating events. See the Codes section -for details on valid codes for each type. +Event types: +=========== +Event types are groupings of codes under a logical input construct. Each +type has a set of applicable codes to be used in generating events. See the +Codes section for details on valid codes for each type. * EV_SYN: - Used as markers to separate events. Events may be separated in time or in @@ -63,9 +63,9 @@ for details on valid codes for each type. * EV_FF_STATUS: - Used to receive force feedback device status. -Codes: -========== -Codes define the precise type of event. +Event codes: +=========== +Event codes define the precise type of event. EV_SYN: ---------- @@ -220,6 +220,56 @@ EV_PWR: EV_PWR events are a special type of event used specifically for power mangement. Its usage is not well defined. To be addressed later. +Device properties: +================= +Normally, userspace sets up an input device based on the data it emits, +i.e., the event types. In the case of two devices emitting the same event +types, additional information can be provided in the form of device +properties. + +INPUT_PROP_DIRECT + INPUT_PROP_POINTER: +-------------------------------------- +The INPUT_PROP_DIRECT property indicates that device coordinates should be +directly mapped to screen coordinates (not taking into account trivial +transformations, such as scaling, flipping and rotating). Non-direct input +devices require non-trivial transformation, such as absolute to relative +transformation for touchpads. Typical direct input devices: touchscreens, +drawing tablets; non-direct devices: touchpads, mice. + +The INPUT_PROP_POINTER property indicates that the device is not transposed +on the screen and thus requires use of an on-screen pointer to trace user's +movements. Typical pointer devices: touchpads, tablets, mice; non-pointer +device: touchscreen. + +If neither INPUT_PROP_DIRECT or INPUT_PROP_POINTER are set, the property is +considered undefined and the device type should be deduced in the +traditional way, using emitted event types. + +INPUT_PROP_BUTTONPAD: +-------------------- +For touchpads where the button is placed beneath the surface, such that +pressing down on the pad causes a button click, this property should be +set. Common in clickpad notebooks and macbooks from 2009 and onwards. + +Originally, the buttonpad property was coded into the bcm5974 driver +version field under the name integrated button. For backwards +compatibility, both methods need to be checked in userspace. + +INPUT_PROP_SEMI_MT: +------------------ +Some touchpads, most common between 2008 and 2011, can detect the presence +of multiple contacts without resolving the individual positions; only the +number of contacts and a rectangular shape is known. For such +touchpads, the semi-mt property should be set. + +Depending on the device, the rectangle may enclose all touches, like a +bounding box, or just some of them, for instance the two most recent +touches. The diversity makes the rectangle of limited use, but some +gestures can normally be extracted from it. + +If INPUT_PROP_SEMI_MT is not set, the device is assumed to be a true MT +device. + Guidelines: ========== The guidelines below ensure proper single-touch and multi-finger functionality. @@ -240,6 +290,8 @@ used to report when a touch is active on the screen. BTN_{MOUSE,LEFT,MIDDLE,RIGHT} must not be reported as the result of touch contact. BTN_TOOL_<name> events should be reported where possible. +For new hardware, INPUT_PROP_DIRECT should be set. + Trackpads: ---------- Legacy trackpads that only provide relative position information must report @@ -250,6 +302,8 @@ location of the touch. BTN_TOUCH should be used to report when a touch is active on the trackpad. Where multi-finger support is available, BTN_TOOL_<name> should be used to report the number of touches active on the trackpad. +For new hardware, INPUT_PROP_POINTER should be set. + Tablets: ---------- BTN_TOOL_<name> events must be reported when a stylus or other tool is active on @@ -260,3 +314,5 @@ button may be used for buttons on the tablet except BTN_{MOUSE,LEFT}. BTN_{0,1,2,etc} are good generic codes for unlabeled buttons. Do not use meaningful buttons, like BTN_FORWARD, unless the button is labeled for that purpose on the device. + +For new hardware, both INPUT_PROP_DIRECT and INPUT_PROP_POINTER should be set. diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 6727b92bc2fb..150fd3833d0b 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -857,42 +857,41 @@ case), we define a mapping like this: ... { - .name "2bit" + .name = "2bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { - .name "4bit" + .name = "4bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { - .name "4bit" + .name = "4bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_2_grp", .dev_name = "foo-mmc.0", }, { - .name "8bit" + .name = "8bit" .ctrl_dev_name = "pinctrl-foo", - .function = "mmc0", .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { - .name "8bit" + .name = "8bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_2_grp", .dev_name = "foo-mmc.0", }, { - .name "8bit" + .name = "8bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_3_grp", @@ -995,7 +994,7 @@ This is enabled by simply setting the .hog_on_boot field in the map to true, like this: { - .name "POWERMAP" + .name = "POWERMAP" .ctrl_dev_name = "pinctrl-foo", .function = "power_func", .hog_on_boot = true, @@ -1025,7 +1024,7 @@ it, disables and releases it, and muxes it in on the pins defined by group B: foo_switch() { - struct pinmux pmx; + struct pinmux *pmx; /* Enable on position A */ pmx = pinmux_get(&device, "spi0-pos-A"); diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt index 21fd05c28e73..f0ab5cf28fca 100644 --- a/Documentation/stable_kernel_rules.txt +++ b/Documentation/stable_kernel_rules.txt @@ -25,7 +25,8 @@ Procedure for submitting patches to the -stable tree: - Send the patch, after verifying that it follows the above rules, to stable@vger.kernel.org. You must note the upstream commit ID in the - changelog of your submission. + changelog of your submission, as well as the kernel version you wish + it to be applied to. - To have the patch automatically included in the stable tree, add the tag Cc: stable@vger.kernel.org in the sign-off area. Once the patch is merged it will be applied to diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 8c20fbd8b42d..6d78841fd416 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -601,6 +601,8 @@ can be ORed together: instead of using the one provided by the hardware. 512 - A kernel warning has occurred. 1024 - A module from drivers/staging was loaded. +2048 - The system is working around a severe firmware bug. +4096 - An out-of-tree module has been loaded. ============================================================== diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt index b61e46f449aa..1733ab947a95 100644 --- a/Documentation/thermal/sysfs-api.txt +++ b/Documentation/thermal/sysfs-api.txt @@ -284,7 +284,7 @@ method, the sys I/F structure will be built like this: The framework includes a simple notification mechanism, in the form of a netlink event. Netlink socket initialization is done during the _init_ of the framework. Drivers which intend to use the notification mechanism -just need to call generate_netlink_event() with two arguments viz +just need to call thermal_generate_netlink_event() with two arguments viz (originator, event). Typically the originator will be an integer assigned to a thermal_zone_device when it registers itself with the framework. The event will be one of:{THERMAL_AUX0, THERMAL_AUX1, THERMAL_CRITICAL, diff --git a/Documentation/virtual/00-INDEX b/Documentation/virtual/00-INDEX index 8e601991d91c..924bd462675e 100644 --- a/Documentation/virtual/00-INDEX +++ b/Documentation/virtual/00-INDEX @@ -4,8 +4,6 @@ Virtualization support in the Linux kernel. - this file. kvm/ - Kernel Virtual Machine. See also http://linux-kvm.org -lguest/ - - Extremely simple hypervisor for experimental/educational use. uml/ - User Mode Linux, builds/runs Linux kernel as a userspace program. virtio.txt diff --git a/MAINTAINERS b/MAINTAINERS index 93c68d5f1cf4..55ca0bea142c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -159,7 +159,7 @@ S: Maintained F: drivers/net/ethernet/realtek/r8169.c 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER -M: Greg Kroah-Hartman <gregkh@suse.de> +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> L: linux-serial@vger.kernel.org W: http://serial.sourceforge.net S: Maintained @@ -789,12 +789,6 @@ F: arch/arm/mach-mx*/ F: arch/arm/mach-imx/ F: arch/arm/plat-mxc/ -ARM/FREESCALE IMX51 -M: Amit Kucheria <amit.kucheria@canonical.com> -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Maintained -F: arch/arm/mach-mx5/ - ARM/FREESCALE IMX6 M: Shawn Guo <shawn.guo@linaro.org> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -1783,9 +1777,9 @@ X: net/wireless/wext* CHAR and MISC DRIVERS M: Arnd Bergmann <arnd@arndb.de> -M: Greg Kroah-Hartman <greg@kroah.com> +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git -S: Maintained +S: Supported F: drivers/char/* F: drivers/misc/* @@ -2287,7 +2281,7 @@ F: drivers/acpi/dock.c DOCUMENTATION M: Randy Dunlap <rdunlap@xenotime.net> L: linux-doc@vger.kernel.org -T: quilt http://userweb.kernel.org/~rdunlap/kernel-doc-patches/current/ +T: quilt http://xenotime.net/kernel-doc-patches/current/ S: Maintained F: Documentation/ @@ -2320,7 +2314,7 @@ F: lib/lru_cache.c F: Documentation/blockdev/drbd/ DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS -M: Greg Kroah-Hartman <gregkh@suse.de> +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6.git S: Supported F: Documentation/kobject.txt @@ -2350,6 +2344,9 @@ F: include/drm/i915* DRM DRIVERS FOR EXYNOS M: Inki Dae <inki.dae@samsung.com> +M: Joonyoung Shim <jy0922.shim@samsung.com> +M: Seung-Woo Kim <sw0312.kim@samsung.com> +M: Kyungmin Park <kyungmin.park@samsung.com> L: dri-devel@lists.freedesktop.org S: Supported F: drivers/gpu/drm/exynos @@ -2402,7 +2399,7 @@ F: net/bridge/netfilter/ebt*.c ECRYPT FILE SYSTEM M: Tyler Hicks <tyhicks@canonical.com> -M: Dustin Kirkland <kirkland@canonical.com> +M: Dustin Kirkland <dustin.kirkland@gazzang.com> L: ecryptfs@vger.kernel.org W: https://launchpad.net/ecryptfs S: Supported @@ -3989,11 +3986,11 @@ M: Rusty Russell <rusty@rustcorp.com.au> L: lguest@lists.ozlabs.org W: http://lguest.ozlabs.org/ S: Odd Fixes -F: Documentation/virtual/lguest/ +F: arch/x86/include/asm/lguest*.h F: arch/x86/lguest/ F: drivers/lguest/ F: include/linux/lguest*.h -F: arch/x86/include/asm/lguest*.h +F: tools/lguest/ LINUX FOR IBM pSERIES (RS/6000) M: Paul Mackerras <paulus@au.ibm.com> @@ -4133,10 +4130,11 @@ L: linux-ntfs-dev@lists.sourceforge.net W: http://www.linux-ntfs.org/content/view/19/37/ S: Maintained F: Documentation/ldm.txt -F: fs/partitions/ldm.* +F: block/partitions/ldm.* LogFS M: Joern Engel <joern@logfs.org> +M: Prasad Joshi <prasadjoshi.linux@gmail.com> L: logfs@logfs.org W: logfs.org S: Maintained @@ -4278,13 +4276,6 @@ S: Orphan F: drivers/video/matrox/matroxfb_* F: include/linux/matroxfb.h -MAX1668 TEMPERATURE SENSOR DRIVER -M: "David George" <david.george@ska.ac.za> -L: lm-sensors@lm-sensors.org -S: Maintained -F: Documentation/hwmon/max1668 -F: drivers/hwmon/max1668.c - MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER M: "Hans J. Koch" <hjk@hansjkoch.de> L: lm-sensors@lm-sensors.org @@ -5636,7 +5627,7 @@ W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported F: arch/s390/ F: drivers/s390/ -F: fs/partitions/ibm.c +F: block/partitions/ibm.c F: Documentation/s390/ F: Documentation/DocBook/s390* @@ -6279,15 +6270,15 @@ S: Maintained F: arch/alpha/kernel/srm_env.c STABLE BRANCH -M: Greg Kroah-Hartman <greg@kroah.com> +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> L: stable@vger.kernel.org -S: Maintained +S: Supported STAGING SUBSYSTEM -M: Greg Kroah-Hartman <gregkh@suse.de> +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git L: devel@driverdev.osuosl.org -S: Maintained +S: Supported F: drivers/staging/ STAGING - AGERE HERMES II and II.5 WIRELESS DRIVERS @@ -6399,11 +6390,6 @@ M: Omar Ramirez Luna <omar.ramirez@ti.com> S: Odd Fixes F: drivers/staging/tidspbridge/ -STAGING - TRIDENT TVMASTER TMxxxx USB VIDEO CAPTURE DRIVERS -L: linux-media@vger.kernel.org -S: Odd Fixes -F: drivers/staging/tm6000/ - STAGING - USB ENE SM/MS CARD READER DRIVER M: Al Cho <acho@novell.com> S: Odd Fixes @@ -6672,10 +6658,10 @@ S: Maintained K: ^Subject:.*(?i)trivial TTY LAYER -M: Greg Kroah-Hartman <gregkh@suse.de> -S: Maintained +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +S: Supported T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6.git -F: drivers/tty/* +F: drivers/tty/ F: drivers/tty/serial/serial_core.c F: include/linux/serial_core.h F: include/linux/serial.h @@ -6961,7 +6947,7 @@ S: Maintained F: drivers/usb/serial/digi_acceleport.c USB SERIAL DRIVER -M: Greg Kroah-Hartman <gregkh@suse.de> +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> L: linux-usb@vger.kernel.org S: Supported F: Documentation/usb/usb-serial.txt @@ -6976,9 +6962,8 @@ S: Maintained F: drivers/usb/serial/empeg.c USB SERIAL KEYSPAN DRIVER -M: Greg Kroah-Hartman <greg@kroah.com> +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> L: linux-usb@vger.kernel.org -W: http://www.kroah.com/linux/ S: Maintained F: drivers/usb/serial/*keyspan* @@ -7006,7 +6991,7 @@ F: Documentation/video4linux/sn9c102.txt F: drivers/media/video/sn9c102/ USB SUBSYSTEM -M: Greg Kroah-Hartman <gregkh@suse.de> +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> L: linux-usb@vger.kernel.org W: http://www.linux-usb.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6.git @@ -7093,7 +7078,7 @@ F: fs/hppfs/ USERSPACE I/O (UIO) M: "Hans J. Koch" <hjk@hansjkoch.de> -M: Greg Kroah-Hartman <gregkh@suse.de> +M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> S: Maintained F: Documentation/DocBook/uio-howto.tmpl F: drivers/uio/ @@ -7368,6 +7353,7 @@ S: Supported F: Documentation/hwmon/wm83?? F: arch/arm/mach-s3c64xx/mach-crag6410* F: drivers/leds/leds-wm83*.c +F: drivers/hwmon/wm83??-hwmon.c F: drivers/input/misc/wm831x-on.c F: drivers/input/touchscreen/wm831x-ts.c F: drivers/input/touchscreen/wm97*.c @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 3 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2 NAME = Saber-toothed Squirrel # *DOCUMENTATION* diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 24626b0419ee..a48aecc17eac 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -754,7 +754,7 @@ config ARCH_SA1100 select ARCH_HAS_CPUFREQ select CPU_FREQ select GENERIC_CLOCKEVENTS - select CLKDEV_LOOKUP + select HAVE_CLK select HAVE_SCHED_CLOCK select TICK_ONESHOT select ARCH_REQUIRE_GPIOLIB @@ -825,7 +825,6 @@ config ARCH_S5PC100 select HAVE_CLK select CLKDEV_LOOKUP select CPU_V7 - select ARM_L1_CACHE_SHIFT_6 select ARCH_USES_GETTIMEOFFSET select HAVE_S3C2410_I2C if I2C select HAVE_S3C_RTC if RTC_CLASS @@ -842,7 +841,6 @@ config ARCH_S5PV210 select HAVE_CLK select CLKDEV_LOOKUP select CLKSRC_MMIO - select ARM_L1_CACHE_SHIFT_6 select ARCH_HAS_CPUFREQ select GENERIC_CLOCKEVENTS select HAVE_SCHED_CLOCK diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index b2dc2dd7f1df..c47d6199b784 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -41,6 +41,7 @@ #include <asm/irq.h> #include <asm/exception.h> +#include <asm/smp_plat.h> #include <asm/mach/irq.h> #include <asm/hardware/gic.h> @@ -352,11 +353,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic) unsigned int gic_irqs = gic->gic_irqs; struct irq_domain *domain = &gic->domain; void __iomem *base = gic_data_dist_base(gic); - u32 cpu = 0; - -#ifdef CONFIG_SMP - cpu = cpu_logical_map(smp_processor_id()); -#endif + u32 cpu = cpu_logical_map(smp_processor_id()); cpumask = 1 << cpu; cpumask |= cpumask << 8; diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index b6e65dedfd71..62f8095d46de 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -237,7 +237,7 @@ */ #ifdef CONFIG_THUMB2_KERNEL - .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T() + .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER() 9999: .if \inc == 1 \instr\cond\()b\()\t\().w \reg, [\ptr, #\off] @@ -277,7 +277,7 @@ #else /* !CONFIG_THUMB2_KERNEL */ - .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=T() + .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER() .rept \rept 9999: .if \inc == 1 diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h index af18ceaacf5d..b5dc173d336f 100644 --- a/arch/arm/include/asm/domain.h +++ b/arch/arm/include/asm/domain.h @@ -83,9 +83,9 @@ * instructions (inline assembly) */ #ifdef CONFIG_CPU_USE_DOMAINS -#define T(instr) #instr "t" +#define TUSER(instr) #instr "t" #else -#define T(instr) #instr +#define TUSER(instr) #instr #endif #else /* __ASSEMBLY__ */ @@ -95,9 +95,9 @@ * instructions */ #ifdef CONFIG_CPU_USE_DOMAINS -#define T(instr) instr ## t +#define TUSER(instr) instr ## t #else -#define T(instr) instr +#define TUSER(instr) instr #endif #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h index 253cc86318bf..7be54690aeec 100644 --- a/arch/arm/include/asm/futex.h +++ b/arch/arm/include/asm/futex.h @@ -75,9 +75,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, #define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \ __asm__ __volatile__( \ - "1: " T(ldr) " %1, [%3]\n" \ + "1: " TUSER(ldr) " %1, [%3]\n" \ " " insn "\n" \ - "2: " T(str) " %0, [%3]\n" \ + "2: " TUSER(str) " %0, [%3]\n" \ " mov %0, #0\n" \ __futex_atomic_ex_table("%5") \ : "=&r" (ret), "=&r" (oldval), "=&r" (tmp) \ @@ -95,10 +95,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, return -EFAULT; __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" - "1: " T(ldr) " %1, [%4]\n" + "1: " TUSER(ldr) " %1, [%4]\n" " teq %1, %2\n" " it eq @ explicit IT needed for the 2b label\n" - "2: " T(streq) " %3, [%4]\n" + "2: " TUSER(streq) " %3, [%4]\n" __futex_atomic_ex_table("%5") : "+r" (ret), "=&r" (val) : "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT) diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 1e5717afc4ac..ae29293270a3 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -71,12 +71,6 @@ extern void platform_secondary_init(unsigned int cpu); extern void platform_smp_prepare_cpus(unsigned int); /* - * Logical CPU mapping. - */ -extern int __cpu_logical_map[NR_CPUS]; -#define cpu_logical_map(cpu) __cpu_logical_map[cpu] - -/* * Initial data for bringing up a secondary CPU. */ struct secondary_data { diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h index f24c1b9e211d..558d6c80aca9 100644 --- a/arch/arm/include/asm/smp_plat.h +++ b/arch/arm/include/asm/smp_plat.h @@ -43,4 +43,10 @@ static inline int cache_ops_need_broadcast(void) } #endif +/* + * Logical CPU mapping. + */ +extern int __cpu_logical_map[]; +#define cpu_logical_map(cpu) __cpu_logical_map[cpu] + #endif diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index 5d3ed7e38561..314d4664eae7 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h @@ -198,7 +198,15 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, unsigned long addr) { pgtable_page_dtor(pte); - tlb_add_flush(tlb, addr); + + /* + * With the classic ARM MMU, a pte page has two corresponding pmd + * entries, each covering 1MB. + */ + addr &= PMD_MASK; + tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE); + tlb_add_flush(tlb, addr + SZ_1M); + tlb_remove_page(tlb, pte); } diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index b293616a1a1a..2958976d867b 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -227,7 +227,7 @@ do { \ #define __get_user_asm_byte(x,addr,err) \ __asm__ __volatile__( \ - "1: " T(ldrb) " %1,[%2],#0\n" \ + "1: " TUSER(ldrb) " %1,[%2],#0\n" \ "2:\n" \ " .pushsection .fixup,\"ax\"\n" \ " .align 2\n" \ @@ -263,7 +263,7 @@ do { \ #define __get_user_asm_word(x,addr,err) \ __asm__ __volatile__( \ - "1: " T(ldr) " %1,[%2],#0\n" \ + "1: " TUSER(ldr) " %1,[%2],#0\n" \ "2:\n" \ " .pushsection .fixup,\"ax\"\n" \ " .align 2\n" \ @@ -308,7 +308,7 @@ do { \ #define __put_user_asm_byte(x,__pu_addr,err) \ __asm__ __volatile__( \ - "1: " T(strb) " %1,[%2],#0\n" \ + "1: " TUSER(strb) " %1,[%2],#0\n" \ "2:\n" \ " .pushsection .fixup,\"ax\"\n" \ " .align 2\n" \ @@ -341,7 +341,7 @@ do { \ #define __put_user_asm_word(x,__pu_addr,err) \ __asm__ __volatile__( \ - "1: " T(str) " %1,[%2],#0\n" \ + "1: " TUSER(str) " %1,[%2],#0\n" \ "2:\n" \ " .pushsection .fixup,\"ax\"\n" \ " .align 2\n" \ @@ -366,10 +366,10 @@ do { \ #define __put_user_asm_dword(x,__pu_addr,err) \ __asm__ __volatile__( \ - ARM( "1: " T(str) " " __reg_oper1 ", [%1], #4\n" ) \ - ARM( "2: " T(str) " " __reg_oper0 ", [%1]\n" ) \ - THUMB( "1: " T(str) " " __reg_oper1 ", [%1]\n" ) \ - THUMB( "2: " T(str) " " __reg_oper0 ", [%1, #4]\n" ) \ + ARM( "1: " TUSER(str) " " __reg_oper1 ", [%1], #4\n" ) \ + ARM( "2: " TUSER(str) " " __reg_oper0 ", [%1]\n" ) \ + THUMB( "1: " TUSER(str) " " __reg_oper1 ", [%1]\n" ) \ + THUMB( "2: " TUSER(str) " " __reg_oper0 ", [%1, #4]\n" ) \ "3:\n" \ " .pushsection .fixup,\"ax\"\n" \ " .align 2\n" \ diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 3a456c6c7005..be16a48007b4 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -790,7 +790,7 @@ __kuser_cmpxchg64: @ 0xffff0f60 smp_dmb arm rsbs r0, r3, #0 @ set returned val and C flag ldmfd sp!, {r4, r5, r6, r7} - bx lr + usr_ret lr #elif !defined(CONFIG_SMP) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 520889cf1b5b..9fd0ba90c1d2 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -149,6 +149,11 @@ ENDPROC(ret_from_fork) #endif #endif +.macro mcount_adjust_addr rd, rn + bic \rd, \rn, #1 @ clear the Thumb bit if present + sub \rd, \rd, #MCOUNT_INSN_SIZE +.endm + .macro __mcount suffix mcount_enter ldr r0, =ftrace_trace_function @@ -173,8 +178,7 @@ ENDPROC(ret_from_fork) mcount_exit 1: mcount_get_lr r1 @ lr of instrumented func - mov r0, lr @ instrumented function - sub r0, r0, #MCOUNT_INSN_SIZE + mcount_adjust_addr r0, lr @ instrumented function adr lr, BSYM(2f) mov pc, r2 2: mcount_exit @@ -184,8 +188,7 @@ ENDPROC(ret_from_fork) mcount_enter mcount_get_lr r1 @ lr of instrumented func - mov r0, lr @ instrumented function - sub r0, r0, #MCOUNT_INSN_SIZE + mcount_adjust_addr r0, lr @ instrumented function .globl ftrace_call\suffix ftrace_call\suffix: @@ -205,11 +208,11 @@ ftrace_graph_call\suffix: #ifdef CONFIG_DYNAMIC_FTRACE @ called from __ftrace_caller, saved in mcount_enter ldr r1, [sp, #16] @ instrumented routine (func) + mcount_adjust_addr r1, r1 #else @ called from __mcount, untouched in lr - mov r1, lr @ instrumented routine (func) + mcount_adjust_addr r1, lr @ instrumented routine (func) #endif - sub r1, r1, #MCOUNT_INSN_SIZE mov r2, fp @ frame pointer bl prepare_ftrace_return mcount_exit diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 460bbbb6b885..6933244c68f9 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -469,6 +469,20 @@ static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, }, }, + [C(NODE)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + }, }; /* @@ -579,6 +593,20 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, }, }, + [C(NODE)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + }, }; /* diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index e1d5e1929fbd..e33870ff0ac0 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -699,10 +699,13 @@ static int vfp_set(struct task_struct *target, { int ret; struct thread_info *thread = task_thread_info(target); - struct vfp_hard_struct new_vfp = thread->vfpstate.hard; + struct vfp_hard_struct new_vfp; const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs); const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); + vfp_sync_hwstate(thread); + new_vfp = thread->vfpstate.hard; + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &new_vfp.fpregs, user_fpregs_offset, @@ -723,9 +726,8 @@ static int vfp_set(struct task_struct *target, if (ret) return ret; - vfp_sync_hwstate(thread); - thread->vfpstate.hard = new_vfp; vfp_flush_hwstate(thread); + thread->vfpstate.hard = new_vfp; return 0; } diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 129fbd55bde8..a255c39612ca 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -21,7 +21,6 @@ #include <linux/init.h> #include <linux/kexec.h> #include <linux/of_fdt.h> -#include <linux/crash_dump.h> #include <linux/root_dev.h> #include <linux/cpu.h> #include <linux/interrupt.h> @@ -160,7 +159,7 @@ static struct resource mem_res[] = { .flags = IORESOURCE_MEM }, { - .name = "Kernel text", + .name = "Kernel code", .start = 0, .end = 0, .flags = IORESOURCE_MEM @@ -427,6 +426,20 @@ void cpu_init(void) : "r14"); } +int __cpu_logical_map[NR_CPUS]; + +void __init smp_setup_processor_id(void) +{ + int i; + u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0; + + cpu_logical_map(0) = cpu; + for (i = 1; i < NR_CPUS; ++i) + cpu_logical_map(i) = i == cpu ? 0 : i; + + printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu); +} + static void __init setup_processor(void) { struct proc_info_list *list; diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 0340224cf73c..9e617bd4a146 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -227,6 +227,8 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame) if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE) return -EINVAL; + vfp_flush_hwstate(thread); + /* * Copy the floating point registers. There can be unused * registers see asm/hwcap.h for details. @@ -251,9 +253,6 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame) __get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err); __get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err); - if (!err) - vfp_flush_hwstate(thread); - return err ? -EFAULT : 0; } diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 57db122a4f62..cdeb727527d3 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -233,20 +233,6 @@ void __ref cpu_die(void) } #endif /* CONFIG_HOTPLUG_CPU */ -int __cpu_logical_map[NR_CPUS]; - -void __init smp_setup_processor_id(void) -{ - int i; - u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0; - - cpu_logical_map(0) = cpu; - for (i = 1; i < NR_CPUS; ++i) - cpu_logical_map(i) = i == cpu ? 0 : i; - - printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu); -} - /* * Called by both boot and secondaries to move global data into * per-processor storage. @@ -443,9 +429,7 @@ static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent); static void ipi_timer(void) { struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent); - irq_enter(); evt->event_handler(evt); - irq_exit(); } #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST @@ -548,7 +532,9 @@ void handle_IPI(int ipinr, struct pt_regs *regs) switch (ipinr) { case IPI_TIMER: + irq_enter(); ipi_timer(); + irq_exit(); break; case IPI_RESCHEDULE: @@ -556,15 +542,21 @@ void handle_IPI(int ipinr, struct pt_regs *regs) break; case IPI_CALL_FUNC: + irq_enter(); generic_smp_call_function_interrupt(); + irq_exit(); break; case IPI_CALL_FUNC_SINGLE: + irq_enter(); generic_smp_call_function_single_interrupt(); + irq_exit(); break; case IPI_CPU_STOP: + irq_enter(); ipi_cpu_stop(cpu); + irq_exit(); break; default: diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index c8e938553d47..4285daa077b0 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -252,6 +252,8 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) else twd_calibrate_rate(); + __raw_writel(0, twd_base + TWD_TIMER_CONTROL); + clk->name = "local_timer"; clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index f76e75548670..1e19691e0406 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -4,6 +4,7 @@ */ #include <asm-generic/vmlinux.lds.h> +#include <asm/cache.h> #include <asm/thread_info.h> #include <asm/memory.h> #include <asm/page.h> @@ -181,7 +182,7 @@ SECTIONS } #endif - PERCPU_SECTION(32) + PERCPU_SECTION(L1_CACHE_BYTES) #ifdef CONFIG_XIP_KERNEL __data_loc = ALIGN(4); /* location in binary */ @@ -212,13 +213,13 @@ SECTIONS #endif NOSAVE_DATA - CACHELINE_ALIGNED_DATA(32) - READ_MOSTLY_DATA(32) + CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES) + READ_MOSTLY_DATA(L1_CACHE_BYTES) /* * The exception fixup table (might need resorting at runtime) */ - . = ALIGN(32); + . = ALIGN(4); __start___ex_table = .; #ifdef CONFIG_MMU *(__ex_table) diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 1b049cd7a49a..11093a7c3e32 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -31,18 +31,18 @@ #include <asm/domain.h> ENTRY(__get_user_1) -1: T(ldrb) r2, [r0] +1: TUSER(ldrb) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__get_user_1) ENTRY(__get_user_2) #ifdef CONFIG_THUMB2_KERNEL -2: T(ldrb) r2, [r0] -3: T(ldrb) r3, [r0, #1] +2: TUSER(ldrb) r2, [r0] +3: TUSER(ldrb) r3, [r0, #1] #else -2: T(ldrb) r2, [r0], #1 -3: T(ldrb) r3, [r0] +2: TUSER(ldrb) r2, [r0], #1 +3: TUSER(ldrb) r3, [r0] #endif #ifndef __ARMEB__ orr r2, r2, r3, lsl #8 @@ -54,7 +54,7 @@ ENTRY(__get_user_2) ENDPROC(__get_user_2) ENTRY(__get_user_4) -4: T(ldr) r2, [r0] +4: TUSER(ldr) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__get_user_4) diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S index c023fc11e86c..7db25990c589 100644 --- a/arch/arm/lib/putuser.S +++ b/arch/arm/lib/putuser.S @@ -31,7 +31,7 @@ #include <asm/domain.h> ENTRY(__put_user_1) -1: T(strb) r2, [r0] +1: TUSER(strb) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__put_user_1) @@ -40,19 +40,19 @@ ENTRY(__put_user_2) mov ip, r2, lsr #8 #ifdef CONFIG_THUMB2_KERNEL #ifndef __ARMEB__ -2: T(strb) r2, [r0] -3: T(strb) ip, [r0, #1] +2: TUSER(strb) r2, [r0] +3: TUSER(strb) ip, [r0, #1] #else -2: T(strb) ip, [r0] -3: T(strb) r2, [r0, #1] +2: TUSER(strb) ip, [r0] +3: TUSER(strb) r2, [r0, #1] #endif #else /* !CONFIG_THUMB2_KERNEL */ #ifndef __ARMEB__ -2: T(strb) r2, [r0], #1 -3: T(strb) ip, [r0] +2: TUSER(strb) r2, [r0], #1 +3: TUSER(strb) ip, [r0] #else -2: T(strb) ip, [r0], #1 -3: T(strb) r2, [r0] +2: TUSER(strb) ip, [r0], #1 +3: TUSER(strb) r2, [r0] #endif #endif /* CONFIG_THUMB2_KERNEL */ mov r0, #0 @@ -60,18 +60,18 @@ ENTRY(__put_user_2) ENDPROC(__put_user_2) ENTRY(__put_user_4) -4: T(str) r2, [r0] +4: TUSER(str) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__put_user_4) ENTRY(__put_user_8) #ifdef CONFIG_THUMB2_KERNEL -5: T(str) r2, [r0] -6: T(str) r3, [r0, #4] +5: TUSER(str) r2, [r0] +6: TUSER(str) r3, [r0, #4] #else -5: T(str) r2, [r0], #4 -6: T(str) r3, [r0] +5: TUSER(str) r2, [r0], #4 +6: TUSER(str) r3, [r0] #endif mov r0, #0 mov pc, lr diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S index d0ece2aeb70d..5c908b1cb8ed 100644 --- a/arch/arm/lib/uaccess.S +++ b/arch/arm/lib/uaccess.S @@ -32,11 +32,11 @@ rsb ip, ip, #4 cmp ip, #2 ldrb r3, [r1], #1 -USER( T(strb) r3, [r0], #1) @ May fault +USER( TUSER( strb) r3, [r0], #1) @ May fault ldrgeb r3, [r1], #1 -USER( T(strgeb) r3, [r0], #1) @ May fault +USER( TUSER( strgeb) r3, [r0], #1) @ May fault ldrgtb r3, [r1], #1 -USER( T(strgtb) r3, [r0], #1) @ May fault +USER( TUSER( strgtb) r3, [r0], #1) @ May fault sub r2, r2, ip b .Lc2u_dest_aligned @@ -59,7 +59,7 @@ ENTRY(__copy_to_user) addmi ip, r2, #4 bmi .Lc2u_0nowords ldr r3, [r1], #4 -USER( T(str) r3, [r0], #4) @ May fault +USER( TUSER( str) r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction rsb ip, ip, #0 movs ip, ip, lsr #32 - PAGE_SHIFT @@ -88,18 +88,18 @@ USER( T(str) r3, [r0], #4) @ May fault stmneia r0!, {r3 - r4} @ Shouldnt fault tst ip, #4 ldrne r3, [r1], #4 - T(strne) r3, [r0], #4 @ Shouldnt fault + TUSER( strne) r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .Lc2u_0fupi .Lc2u_0nowords: teq ip, #0 beq .Lc2u_finished .Lc2u_nowords: cmp ip, #2 ldrb r3, [r1], #1 -USER( T(strb) r3, [r0], #1) @ May fault +USER( TUSER( strb) r3, [r0], #1) @ May fault ldrgeb r3, [r1], #1 -USER( T(strgeb) r3, [r0], #1) @ May fault +USER( TUSER( strgeb) r3, [r0], #1) @ May fault ldrgtb r3, [r1], #1 -USER( T(strgtb) r3, [r0], #1) @ May fault +USER( TUSER( strgtb) r3, [r0], #1) @ May fault b .Lc2u_finished .Lc2u_not_enough: @@ -120,7 +120,7 @@ USER( T(strgtb) r3, [r0], #1) @ May fault mov r3, r7, pull #8 ldr r7, [r1], #4 orr r3, r3, r7, push #24 -USER( T(str) r3, [r0], #4) @ May fault +USER( TUSER( str) r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 movs ip, ip, lsr #32 - PAGE_SHIFT @@ -155,18 +155,18 @@ USER( T(str) r3, [r0], #4) @ May fault movne r3, r7, pull #8 ldrne r7, [r1], #4 orrne r3, r3, r7, push #24 - T(strne) r3, [r0], #4 @ Shouldnt fault + TUSER( strne) r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .Lc2u_1fupi .Lc2u_1nowords: mov r3, r7, get_byte_1 teq ip, #0 beq .Lc2u_finished cmp ip, #2 -USER( T(strb) r3, [r0], #1) @ May fault +USER( TUSER( strb) r3, [r0], #1) @ May fault movge r3, r7, get_byte_2 -USER( T(strgeb) r3, [r0], #1) @ May fault +USER( TUSER( strgeb) r3, [r0], #1) @ May fault movgt r3, r7, get_byte_3 -USER( T(strgtb) r3, [r0], #1) @ May fault +USER( TUSER( strgtb) r3, [r0], #1) @ May fault b .Lc2u_finished .Lc2u_2fupi: subs r2, r2, #4 @@ -175,7 +175,7 @@ USER( T(strgtb) r3, [r0], #1) @ May fault mov r3, r7, pull #16 ldr r7, [r1], #4 orr r3, r3, r7, push #16 -USER( T(str) r3, [r0], #4) @ May fault +USER( TUSER( str) r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 movs ip, ip, lsr #32 - PAGE_SHIFT @@ -210,18 +210,18 @@ USER( T(str) r3, [r0], #4) @ May fault movne r3, r7, pull #16 ldrne r7, [r1], #4 orrne r3, r3, r7, push #16 - T(strne) r3, [r0], #4 @ Shouldnt fault + TUSER( strne) r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .Lc2u_2fupi .Lc2u_2nowords: mov r3, r7, get_byte_2 teq ip, #0 beq .Lc2u_finished cmp ip, #2 -USER( T(strb) r3, [r0], #1) @ May fault +USER( TUSER( strb) r3, [r0], #1) @ May fault movge r3, r7, get_byte_3 -USER( T(strgeb) r3, [r0], #1) @ May fault +USER( TUSER( strgeb) r3, [r0], #1) @ May fault ldrgtb r3, [r1], #0 -USER( T(strgtb) r3, [r0], #1) @ May fault +USER( TUSER( strgtb) r3, [r0], #1) @ May fault b .Lc2u_finished .Lc2u_3fupi: subs r2, r2, #4 @@ -230,7 +230,7 @@ USER( T(strgtb) r3, [r0], #1) @ May fault mov r3, r7, pull #24 ldr r7, [r1], #4 orr r3, r3, r7, push #8 -USER( T(str) r3, [r0], #4) @ May fault +USER( TUSER( str) r3, [r0], #4) @ May fault mov ip, r0, lsl #32 - PAGE_SHIFT rsb ip, ip, #0 movs ip, ip, lsr #32 - PAGE_SHIFT @@ -265,18 +265,18 @@ USER( T(str) r3, [r0], #4) @ May fault movne r3, r7, pull #24 ldrne r7, [r1], #4 orrne r3, r3, r7, push #8 - T(strne) r3, [r0], #4 @ Shouldnt fault + TUSER( strne) r3, [r0], #4 @ Shouldnt fault ands ip, ip, #3 beq .Lc2u_3fupi .Lc2u_3nowords: mov r3, r7, get_byte_3 teq ip, #0 beq .Lc2u_finished cmp ip, #2 -USER( T(strb) r3, [r0], #1) @ May fault +USER( TUSER( strb) r3, [r0], #1) @ May fault ldrgeb r3, [r1], #1 -USER( T(strgeb) r3, [r0], #1) @ May fault +USER( TUSER( strgeb) r3, [r0], #1) @ May fault ldrgtb r3, [r1], #0 -USER( T(strgtb) r3, [r0], #1) @ May fault +USER( TUSER( strgtb) r3, [r0], #1) @ May fault b .Lc2u_finished ENDPROC(__copy_to_user) @@ -295,11 +295,11 @@ ENDPROC(__copy_to_user) .Lcfu_dest_not_aligned: rsb ip, ip, #4 cmp ip, #2 -USER( T(ldrb) r3, [r1], #1) @ May fault +USER( TUSER( ldrb) r3, [r1], #1) @ May fault strb r3, [r0], #1 -USER( T(ldrgeb) r3, [r1], #1) @ May fault +USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault strgeb r3, [r0], #1 -USER( T(ldrgtb) r3, [r1], #1) @ May fault +USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault strgtb r3, [r0], #1 sub r2, r2, ip b .Lcfu_dest_aligned @@ -322,7 +322,7 @@ ENTRY(__copy_from_user) .Lcfu_0fupi: subs r2, r2, #4 addmi ip, r2, #4 bmi .Lcfu_0nowords -USER( T(ldr) r3, [r1], #4) +USER( TUSER( ldr) r3, [r1], #4) str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction rsb ip, ip, #0 @@ -351,18 +351,18 @@ USER( T(ldr) r3, [r1], #4) ldmneia r1!, {r3 - r4} @ Shouldnt fault stmneia r0!, {r3 - r4} tst ip, #4 - T(ldrne) r3, [r1], #4 @ Shouldnt fault + TUSER( ldrne) r3, [r1], #4 @ Shouldnt fault strne r3, [r0], #4 ands ip, ip, #3 beq .Lcfu_0fupi .Lcfu_0nowords: teq ip, #0 beq .Lcfu_finished .Lcfu_nowords: cmp ip, #2 -USER( T(ldrb) r3, [r1], #1) @ May fault +USER( TUSER( ldrb) r3, [r1], #1) @ May fault strb r3, [r0], #1 -USER( T(ldrgeb) r3, [r1], #1) @ May fault +USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault strgeb r3, [r0], #1 -USER( T(ldrgtb) r3, [r1], #1) @ May fault +USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault strgtb r3, [r0], #1 b .Lcfu_finished @@ -375,7 +375,7 @@ USER( T(ldrgtb) r3, [r1], #1) @ May fault .Lcfu_src_not_aligned: bic r1, r1, #3 -USER( T(ldr) r7, [r1], #4) @ May fault +USER( TUSER( ldr) r7, [r1], #4) @ May fault cmp ip, #2 bgt .Lcfu_3fupi beq .Lcfu_2fupi @@ -383,7 +383,7 @@ USER( T(ldr) r7, [r1], #4) @ May fault addmi ip, r2, #4 bmi .Lcfu_1nowords mov r3, r7, pull #8 -USER( T(ldr) r7, [r1], #4) @ May fault +USER( TUSER( ldr) r7, [r1], #4) @ May fault orr r3, r3, r7, push #24 str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT @@ -418,7 +418,7 @@ USER( T(ldr) r7, [r1], #4) @ May fault stmneia r0!, {r3 - r4} tst ip, #4 movne r3, r7, pull #8 -USER( T(ldrne) r7, [r1], #4) @ May fault +USER( TUSER( ldrne) r7, [r1], #4) @ May fault orrne r3, r3, r7, push #24 strne r3, [r0], #4 ands ip, ip, #3 @@ -438,7 +438,7 @@ USER( T(ldrne) r7, [r1], #4) @ May fault addmi ip, r2, #4 bmi .Lcfu_2nowords mov r3, r7, pull #16 -USER( T(ldr) r7, [r1], #4) @ May fault +USER( TUSER( ldr) r7, [r1], #4) @ May fault orr r3, r3, r7, push #16 str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT @@ -474,7 +474,7 @@ USER( T(ldr) r7, [r1], #4) @ May fault stmneia r0!, {r3 - r4} tst ip, #4 movne r3, r7, pull #16 -USER( T(ldrne) r7, [r1], #4) @ May fault +USER( TUSER( ldrne) r7, [r1], #4) @ May fault orrne r3, r3, r7, push #16 strne r3, [r0], #4 ands ip, ip, #3 @@ -486,7 +486,7 @@ USER( T(ldrne) r7, [r1], #4) @ May fault strb r3, [r0], #1 movge r3, r7, get_byte_3 strgeb r3, [r0], #1 -USER( T(ldrgtb) r3, [r1], #0) @ May fault +USER( TUSER( ldrgtb) r3, [r1], #0) @ May fault strgtb r3, [r0], #1 b .Lcfu_finished @@ -494,7 +494,7 @@ USER( T(ldrgtb) r3, [r1], #0) @ May fault addmi ip, r2, #4 bmi .Lcfu_3nowords mov r3, r7, pull #24 -USER( T(ldr) r7, [r1], #4) @ May fault +USER( TUSER( ldr) r7, [r1], #4) @ May fault orr r3, r3, r7, push #8 str r3, [r0], #4 mov ip, r1, lsl #32 - PAGE_SHIFT @@ -529,7 +529,7 @@ USER( T(ldr) r7, [r1], #4) @ May fault stmneia r0!, {r3 - r4} tst ip, #4 movne r3, r7, pull #24 -USER( T(ldrne) r7, [r1], #4) @ May fault +USER( TUSER( ldrne) r7, [r1], #4) @ May fault orrne r3, r3, r7, push #8 strne r3, [r0], #4 ands ip, ip, #3 @@ -539,9 +539,9 @@ USER( T(ldrne) r7, [r1], #4) @ May fault beq .Lcfu_finished cmp ip, #2 strb r3, [r0], #1 -USER( T(ldrgeb) r3, [r1], #1) @ May fault +USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault strgeb r3, [r0], #1 -USER( T(ldrgtb) r3, [r1], #1) @ May fault +USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault strgtb r3, [r0], #1 b .Lcfu_finished ENDPROC(__copy_from_user) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 4f991f295284..71feb00a1e99 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -18,6 +18,12 @@ config HAVE_AT91_USART4 config HAVE_AT91_USART5 bool +config AT91_SAM9_ALT_RESET + bool + +config AT91_SAM9G45_RESET + bool + menu "Atmel AT91 System-on-Chip" choice @@ -39,6 +45,7 @@ config ARCH_AT91SAM9260 select HAVE_AT91_USART4 select HAVE_AT91_USART5 select HAVE_NET_MACB + select AT91_SAM9_ALT_RESET config ARCH_AT91SAM9261 bool "AT91SAM9261" @@ -46,6 +53,7 @@ config ARCH_AT91SAM9261 select GENERIC_CLOCKEVENTS select HAVE_FB_ATMEL select HAVE_AT91_DBGU0 + select AT91_SAM9_ALT_RESET config ARCH_AT91SAM9G10 bool "AT91SAM9G10" @@ -53,6 +61,7 @@ config ARCH_AT91SAM9G10 select GENERIC_CLOCKEVENTS select HAVE_AT91_DBGU0 select HAVE_FB_ATMEL + select AT91_SAM9_ALT_RESET config ARCH_AT91SAM9263 bool "AT91SAM9263" @@ -61,6 +70,7 @@ config ARCH_AT91SAM9263 select HAVE_FB_ATMEL select HAVE_NET_MACB select HAVE_AT91_DBGU1 + select AT91_SAM9_ALT_RESET config ARCH_AT91SAM9RL bool "AT91SAM9RL" @@ -69,6 +79,7 @@ config ARCH_AT91SAM9RL select HAVE_AT91_USART3 select HAVE_FB_ATMEL select HAVE_AT91_DBGU0 + select AT91_SAM9_ALT_RESET config ARCH_AT91SAM9G20 bool "AT91SAM9G20" @@ -79,6 +90,7 @@ config ARCH_AT91SAM9G20 select HAVE_AT91_USART4 select HAVE_AT91_USART5 select HAVE_NET_MACB + select AT91_SAM9_ALT_RESET config ARCH_AT91SAM9G45 bool "AT91SAM9G45" @@ -88,6 +100,7 @@ config ARCH_AT91SAM9G45 select HAVE_FB_ATMEL select HAVE_NET_MACB select HAVE_AT91_DBGU1 + select AT91_SAM9G45_RESET config ARCH_AT91CAP9 bool "AT91CAP9" @@ -96,6 +109,7 @@ config ARCH_AT91CAP9 select HAVE_FB_ATMEL select HAVE_NET_MACB select HAVE_AT91_DBGU1 + select AT91_SAM9G45_RESET config ARCH_AT91X40 bool "AT91x40" diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 242174f9f355..705e1fbded39 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -8,15 +8,17 @@ obj-n := obj- := obj-$(CONFIG_AT91_PMC_UNIT) += clock.o +obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o +obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o # CPU-specific support obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o -obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o at91sam9_alt_reset.o -obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o at91sam9_alt_reset.o -obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o at91sam9_alt_reset.o -obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o at91sam9_alt_reset.o -obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o at91sam9_alt_reset.o -obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o at91sam9_alt_reset.o +obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91CAP9) += at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c index edb879ac04c8..a42edc25a87e 100644 --- a/arch/arm/mach-at91/at91cap9.c +++ b/arch/arm/mach-at91/at91cap9.c @@ -21,7 +21,6 @@ #include <mach/cpu.h> #include <mach/at91cap9.h> #include <mach/at91_pmc.h> -#include <mach/at91_rstc.h> #include "soc.h" #include "generic.h" @@ -314,11 +313,6 @@ static struct at91_gpio_bank at91cap9_gpio[] __initdata = { } }; -static void at91cap9_restart(char mode, const char *cmd) -{ - at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); -} - /* -------------------------------------------------------------------- * AT91CAP9 processor initialization * -------------------------------------------------------------------- */ @@ -331,13 +325,14 @@ static void __init at91cap9_map_io(void) static void __init at91cap9_ioremap_registers(void) { at91_ioremap_shdwc(AT91CAP9_BASE_SHDWC); + at91_ioremap_rstc(AT91CAP9_BASE_RSTC); at91sam926x_ioremap_pit(AT91CAP9_BASE_PIT); at91sam9_ioremap_smc(0, AT91CAP9_BASE_SMC); } static void __init at91cap9_initialize(void) { - arm_pm_restart = at91cap9_restart; + arm_pm_restart = at91sam9g45_restart; at91_extern_irq = (1 << AT91CAP9_ID_IRQ0) | (1 << AT91CAP9_ID_IRQ1); /* Register GPIO subsystem */ diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index 5e46e4a96430..d4036ba43612 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -323,6 +323,7 @@ static void __init at91sam9260_map_io(void) static void __init at91sam9260_ioremap_registers(void) { at91_ioremap_shdwc(AT91SAM9260_BASE_SHDWC); + at91_ioremap_rstc(AT91SAM9260_BASE_RSTC); at91sam926x_ioremap_pit(AT91SAM9260_BASE_PIT); at91sam9_ioremap_smc(0, AT91SAM9260_BASE_SMC); } diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index b85b9ea60170..023c2ff138df 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -281,6 +281,7 @@ static void __init at91sam9261_map_io(void) static void __init at91sam9261_ioremap_registers(void) { at91_ioremap_shdwc(AT91SAM9261_BASE_SHDWC); + at91_ioremap_rstc(AT91SAM9261_BASE_RSTC); at91sam926x_ioremap_pit(AT91SAM9261_BASE_PIT); at91sam9_ioremap_smc(0, AT91SAM9261_BASE_SMC); } diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 79e3669b1117..75e876c258af 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -301,6 +301,7 @@ static void __init at91sam9263_map_io(void) static void __init at91sam9263_ioremap_registers(void) { at91_ioremap_shdwc(AT91SAM9263_BASE_SHDWC); + at91_ioremap_rstc(AT91SAM9263_BASE_RSTC); at91sam926x_ioremap_pit(AT91SAM9263_BASE_PIT); at91sam9_ioremap_smc(0, AT91SAM9263_BASE_SMC0); at91sam9_ioremap_smc(1, AT91SAM9263_BASE_SMC1); diff --git a/arch/arm/mach-at91/at91sam9_alt_reset.S b/arch/arm/mach-at91/at91sam9_alt_reset.S index d3f931c5942e..518e42377171 100644 --- a/arch/arm/mach-at91/at91sam9_alt_reset.S +++ b/arch/arm/mach-at91/at91sam9_alt_reset.S @@ -23,7 +23,8 @@ .globl at91sam9_alt_restart at91sam9_alt_restart: ldr r0, .at91_va_base_sdramc @ preload constants - ldr r1, .at91_va_base_rstc_cr + ldr r1, =at91_rstc_base + ldr r1, [r1] mov r2, #1 mov r3, #AT91_SDRAMC_LPCB_POWER_DOWN @@ -33,11 +34,9 @@ at91sam9_alt_restart: ldr r0, .at91_va_base_sdramc @ preload constants str r2, [r0, #AT91_SDRAMC_TR] @ disable SDRAM access str r3, [r0, #AT91_SDRAMC_LPR] @ power down SDRAM - str r4, [r1] @ reset processor + str r4, [r1, #AT91_RSTC_CR] @ reset processor b . .at91_va_base_sdramc: .word AT91_VA_BASE_SYS + AT91_SDRAMC0 -.at91_va_base_rstc_cr: - .word AT91_VA_BASE_SYS + AT91_RSTC_CR diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 7032dd32cdf0..1cb6a96b1c1e 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -18,7 +18,6 @@ #include <asm/mach/map.h> #include <mach/at91sam9g45.h> #include <mach/at91_pmc.h> -#include <mach/at91_rstc.h> #include <mach/cpu.h> #include "soc.h" @@ -318,11 +317,6 @@ static struct at91_gpio_bank at91sam9g45_gpio[] __initdata = { } }; -static void at91sam9g45_restart(char mode, const char *cmd) -{ - at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); -} - /* -------------------------------------------------------------------- * AT91SAM9G45 processor initialization * -------------------------------------------------------------------- */ @@ -336,6 +330,7 @@ static void __init at91sam9g45_map_io(void) static void __init at91sam9g45_ioremap_registers(void) { at91_ioremap_shdwc(AT91SAM9G45_BASE_SHDWC); + at91_ioremap_rstc(AT91SAM9G45_BASE_RSTC); at91sam926x_ioremap_pit(AT91SAM9G45_BASE_PIT); at91sam9_ioremap_smc(0, AT91SAM9G45_BASE_SMC); } diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S new file mode 100644 index 000000000000..0468be10980b --- /dev/null +++ b/arch/arm/mach-at91/at91sam9g45_reset.S @@ -0,0 +1,40 @@ +/* + * reset AT91SAM9G45 as per errata + * + * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcosoft.com> + * + * unless the SDRAM is cleanly shutdown before we hit the + * reset register it can be left driving the data bus and + * killing the chance of a subsequent boot from NAND + * + * GPLv2 Only + */ + +#include <linux/linkage.h> +#include <mach/hardware.h> +#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_rstc.h> + + .arm + + .globl at91sam9g45_restart + +at91sam9g45_restart: + ldr r0, .at91_va_base_sdramc0 @ preload constants + ldr r1, =at91_rstc_base + ldr r1, [r1] + + mov r2, #1 + mov r3, #AT91_DDRSDRC_LPCB_POWER_DOWN + ldr r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST + + .balign 32 @ align to cache line + + str r2, [r0, #AT91_DDRSDRC_RTR] @ disable DDR0 access + str r3, [r0, #AT91_DDRSDRC_LPR] @ power down DDR0 + str r4, [r1, #AT91_RSTC_CR] @ reset processor + + b . + +.at91_va_base_sdramc0: + .word AT91_VA_BASE_SYS + AT91_DDRSDRC0 diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index d6bcb1da11df..d2c91a841cb8 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -286,6 +286,7 @@ static void __init at91sam9rl_map_io(void) static void __init at91sam9rl_ioremap_registers(void) { at91_ioremap_shdwc(AT91SAM9RL_BASE_SHDWC); + at91_ioremap_rstc(AT91SAM9RL_BASE_RSTC); at91sam926x_ioremap_pit(AT91SAM9RL_BASE_PIT); at91sam9_ioremap_smc(0, AT91SAM9RL_BASE_SMC); } diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 4866b8180d66..594133451c0c 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -58,7 +58,9 @@ extern void at91_irq_suspend(void); extern void at91_irq_resume(void); /* reset */ +extern void at91_ioremap_rstc(u32 base_addr); extern void at91sam9_alt_restart(char, const char *); +extern void at91sam9g45_restart(char, const char *); /* shutdown */ extern void at91_ioremap_shdwc(u32 base_addr); diff --git a/arch/arm/mach-at91/include/mach/at91_rstc.h b/arch/arm/mach-at91/include/mach/at91_rstc.h index cbd2bf052c1f..875fa336800b 100644 --- a/arch/arm/mach-at91/include/mach/at91_rstc.h +++ b/arch/arm/mach-at91/include/mach/at91_rstc.h @@ -16,13 +16,25 @@ #ifndef AT91_RSTC_H #define AT91_RSTC_H -#define AT91_RSTC_CR (AT91_RSTC + 0x00) /* Reset Controller Control Register */ +#ifndef __ASSEMBLY__ +extern void __iomem *at91_rstc_base; + +#define at91_rstc_read(field) \ + __raw_readl(at91_rstc_base + field) + +#define at91_rstc_write(field, value) \ + __raw_writel(value, at91_rstc_base + field); +#else +.extern at91_rstc_base +#endif + +#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */ #define AT91_RSTC_PROCRST (1 << 0) /* Processor Reset */ #define AT91_RSTC_PERRST (1 << 2) /* Peripheral Reset */ #define AT91_RSTC_EXTRST (1 << 3) /* External Reset */ #define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */ -#define AT91_RSTC_SR (AT91_RSTC + 0x04) /* Reset Controller Status Register */ +#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */ #define AT91_RSTC_URSTS (1 << 0) /* User Reset Status */ #define AT91_RSTC_RSTTYP (7 << 8) /* Reset Type */ #define AT91_RSTC_RSTTYP_GENERAL (0 << 8) @@ -33,7 +45,7 @@ #define AT91_RSTC_NRSTL (1 << 16) /* NRST Pin Level */ #define AT91_RSTC_SRCMP (1 << 17) /* Software Reset Command in Progress */ -#define AT91_RSTC_MR (AT91_RSTC + 0x08) /* Reset Controller Mode Register */ +#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */ #define AT91_RSTC_URSTEN (1 << 0) /* User Reset Enable */ #define AT91_RSTC_URSTIEN (1 << 4) /* User Reset Interrupt Enable */ #define AT91_RSTC_ERSTL (0xf << 8) /* External Reset Length */ diff --git a/arch/arm/mach-at91/include/mach/at91cap9.h b/arch/arm/mach-at91/include/mach/at91cap9.h index 4c0e2f6011d7..61d952902f2b 100644 --- a/arch/arm/mach-at91/include/mach/at91cap9.h +++ b/arch/arm/mach-at91/include/mach/at91cap9.h @@ -83,7 +83,6 @@ #define AT91_DDRSDRC0 (0xffffe600 - AT91_BASE_SYS) #define AT91_MATRIX (0xffffea00 - AT91_BASE_SYS) #define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) -#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) #define AT91_GPBR (cpu_is_at91cap9_revB() ? \ (0xfffffd50 - AT91_BASE_SYS) : \ (0xfffffd60 - AT91_BASE_SYS)) @@ -96,6 +95,7 @@ #define AT91CAP9_BASE_PIOB 0xfffff400 #define AT91CAP9_BASE_PIOC 0xfffff600 #define AT91CAP9_BASE_PIOD 0xfffff800 +#define AT91CAP9_BASE_RSTC 0xfffffd00 #define AT91CAP9_BASE_SHDWC 0xfffffd10 #define AT91CAP9_BASE_RTT 0xfffffd20 #define AT91CAP9_BASE_PIT 0xfffffd30 diff --git a/arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h b/arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h deleted file mode 100644 index 976f4a6c3353..000000000000 --- a/arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h - * - * (C) 2008 Andrew Victor - * - * DDR/SDR Controller (DDRSDRC) - System peripherals registers. - * Based on AT91CAP9 datasheet revision B. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef AT91CAP9_DDRSDR_H -#define AT91CAP9_DDRSDR_H - -#define AT91_DDRSDRC_MR 0x00 /* Mode Register */ -#define AT91_DDRSDRC_MODE (0xf << 0) /* Command Mode */ -#define AT91_DDRSDRC_MODE_NORMAL 0 -#define AT91_DDRSDRC_MODE_NOP 1 -#define AT91_DDRSDRC_MODE_PRECHARGE 2 -#define AT91_DDRSDRC_MODE_LMR 3 -#define AT91_DDRSDRC_MODE_REFRESH 4 -#define AT91_DDRSDRC_MODE_EXT_LMR 5 -#define AT91_DDRSDRC_MODE_DEEP 6 - -#define AT91_DDRSDRC_RTR 0x04 /* Refresh Timer Register */ -#define AT91_DDRSDRC_COUNT (0xfff << 0) /* Refresh Timer Counter */ - -#define AT91_DDRSDRC_CR 0x08 /* Configuration Register */ -#define AT91_DDRSDRC_NC (3 << 0) /* Number of Column Bits */ -#define AT91_DDRSDRC_NC_SDR8 (0 << 0) -#define AT91_DDRSDRC_NC_SDR9 (1 << 0) -#define AT91_DDRSDRC_NC_SDR10 (2 << 0) -#define AT91_DDRSDRC_NC_SDR11 (3 << 0) -#define AT91_DDRSDRC_NC_DDR9 (0 << 0) -#define AT91_DDRSDRC_NC_DDR10 (1 << 0) -#define AT91_DDRSDRC_NC_DDR11 (2 << 0) -#define AT91_DDRSDRC_NC_DDR12 (3 << 0) -#define AT91_DDRSDRC_NR (3 << 2) /* Number of Row Bits */ -#define AT91_DDRSDRC_NR_11 (0 << 2) -#define AT91_DDRSDRC_NR_12 (1 << 2) -#define AT91_DDRSDRC_NR_13 (2 << 2) -#define AT91_DDRSDRC_CAS (7 << 4) /* CAS Latency */ -#define AT91_DDRSDRC_CAS_2 (2 << 4) -#define AT91_DDRSDRC_CAS_3 (3 << 4) -#define AT91_DDRSDRC_CAS_25 (6 << 4) -#define AT91_DDRSDRC_DLL (1 << 7) /* Reset DLL */ -#define AT91_DDRSDRC_DICDS (1 << 8) /* Output impedance control */ - -#define AT91_DDRSDRC_T0PR 0x0C /* Timing 0 Register */ -#define AT91_DDRSDRC_TRAS (0xf << 0) /* Active to Precharge delay */ -#define AT91_DDRSDRC_TRCD (0xf << 4) /* Row to Column delay */ -#define AT91_DDRSDRC_TWR (0xf << 8) /* Write recovery delay */ -#define AT91_DDRSDRC_TRC (0xf << 12) /* Row cycle delay */ -#define AT91_DDRSDRC_TRP (0xf << 16) /* Row precharge delay */ -#define AT91_DDRSDRC_TRRD (0xf << 20) /* Active BankA to BankB */ -#define AT91_DDRSDRC_TWTR (1 << 24) /* Internal Write to Read delay */ -#define AT91_DDRSDRC_TMRD (0xf << 28) /* Load mode to active/refresh delay */ - -#define AT91_DDRSDRC_T1PR 0x10 /* Timing 1 Register */ -#define AT91_DDRSDRC_TRFC (0x1f << 0) /* Row Cycle Delay */ -#define AT91_DDRSDRC_TXSNR (0xff << 8) /* Exit self-refresh to non-read */ -#define AT91_DDRSDRC_TXSRD (0xff << 16) /* Exit self-refresh to read */ -#define AT91_DDRSDRC_TXP (0xf << 24) /* Exit power-down delay */ - -#define AT91_DDRSDRC_LPR 0x18 /* Low Power Register */ -#define AT91_DDRSDRC_LPCB (3 << 0) /* Low-power Configurations */ -#define AT91_DDRSDRC_LPCB_DISABLE 0 -#define AT91_DDRSDRC_LPCB_SELF_REFRESH 1 -#define AT91_DDRSDRC_LPCB_POWER_DOWN 2 -#define AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN 3 -#define AT91_DDRSDRC_CLKFR (1 << 2) /* Clock Frozen */ -#define AT91_DDRSDRC_PASR (7 << 4) /* Partial Array Self Refresh */ -#define AT91_DDRSDRC_TCSR (3 << 8) /* Temperature Compensated Self Refresh */ -#define AT91_DDRSDRC_DS (3 << 10) /* Drive Strength */ -#define AT91_DDRSDRC_TIMEOUT (3 << 12) /* Time to define when Low Power Mode is enabled */ -#define AT91_DDRSDRC_TIMEOUT_0_CLK_CYCLES (0 << 12) -#define AT91_DDRSDRC_TIMEOUT_64_CLK_CYCLES (1 << 12) -#define AT91_DDRSDRC_TIMEOUT_128_CLK_CYCLES (2 << 12) - -#define AT91_DDRSDRC_MDR 0x1C /* Memory Device Register */ -#define AT91_DDRSDRC_MD (3 << 0) /* Memory Device Type */ -#define AT91_DDRSDRC_MD_SDR 0 -#define AT91_DDRSDRC_MD_LOW_POWER_SDR 1 -#define AT91_DDRSDRC_MD_DDR 2 -#define AT91_DDRSDRC_MD_LOW_POWER_DDR 3 - -#define AT91_DDRSDRC_DLLR 0x20 /* DLL Information Register */ -#define AT91_DDRSDRC_MDINC (1 << 0) /* Master Delay increment */ -#define AT91_DDRSDRC_MDDEC (1 << 1) /* Master Delay decrement */ -#define AT91_DDRSDRC_MDOVF (1 << 2) /* Master Delay Overflow */ -#define AT91_DDRSDRC_SDCOVF (1 << 3) /* Slave Delay Correction Overflow */ -#define AT91_DDRSDRC_SDCUDF (1 << 4) /* Slave Delay Correction Underflow */ -#define AT91_DDRSDRC_SDERF (1 << 5) /* Slave Delay Correction error */ -#define AT91_DDRSDRC_MDVAL (0xff << 8) /* Master Delay value */ -#define AT91_DDRSDRC_SDVAL (0xff << 16) /* Slave Delay value */ -#define AT91_DDRSDRC_SDCVAL (0xff << 24) /* Slave Delay Correction value */ - -/* Register access macros */ -#define at91_ramc_read(num, reg) \ - at91_sys_read(AT91_DDRSDRC##num + reg) -#define at91_ramc_write(num, reg, value) \ - at91_sys_write(AT91_DDRSDRC##num + reg, value) - - -#endif diff --git a/arch/arm/mach-at91/include/mach/at91sam9260.h b/arch/arm/mach-at91/include/mach/at91sam9260.h index f937c476bb67..fa5ca278adeb 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9260.h +++ b/arch/arm/mach-at91/include/mach/at91sam9260.h @@ -83,7 +83,6 @@ #define AT91_SDRAMC0 (0xffffea00 - AT91_BASE_SYS) #define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS) #define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) -#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) #define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS) #define AT91SAM9260_BASE_ECC 0xffffe800 @@ -92,6 +91,7 @@ #define AT91SAM9260_BASE_PIOA 0xfffff400 #define AT91SAM9260_BASE_PIOB 0xfffff600 #define AT91SAM9260_BASE_PIOC 0xfffff800 +#define AT91SAM9260_BASE_RSTC 0xfffffd00 #define AT91SAM9260_BASE_SHDWC 0xfffffd10 #define AT91SAM9260_BASE_RTT 0xfffffd20 #define AT91SAM9260_BASE_PIT 0xfffffd30 diff --git a/arch/arm/mach-at91/include/mach/at91sam9261.h b/arch/arm/mach-at91/include/mach/at91sam9261.h index 175604e261be..7cde2d36570e 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9261.h +++ b/arch/arm/mach-at91/include/mach/at91sam9261.h @@ -68,7 +68,6 @@ #define AT91_SDRAMC0 (0xffffea00 - AT91_BASE_SYS) #define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS) #define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) -#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) #define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS) #define AT91SAM9261_BASE_SMC 0xffffec00 @@ -76,6 +75,7 @@ #define AT91SAM9261_BASE_PIOA 0xfffff400 #define AT91SAM9261_BASE_PIOB 0xfffff600 #define AT91SAM9261_BASE_PIOC 0xfffff800 +#define AT91SAM9261_BASE_RSTC 0xfffffd00 #define AT91SAM9261_BASE_SHDWC 0xfffffd10 #define AT91SAM9261_BASE_RTT 0xfffffd20 #define AT91SAM9261_BASE_PIT 0xfffffd30 diff --git a/arch/arm/mach-at91/include/mach/at91sam9263.h b/arch/arm/mach-at91/include/mach/at91sam9263.h index 80c915002d83..5949abda962b 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9263.h +++ b/arch/arm/mach-at91/include/mach/at91sam9263.h @@ -78,7 +78,6 @@ #define AT91_SDRAMC1 (0xffffe800 - AT91_BASE_SYS) #define AT91_MATRIX (0xffffec00 - AT91_BASE_SYS) #define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) -#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) #define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS) #define AT91SAM9263_BASE_ECC0 0xffffe000 @@ -91,6 +90,7 @@ #define AT91SAM9263_BASE_PIOC 0xfffff600 #define AT91SAM9263_BASE_PIOD 0xfffff800 #define AT91SAM9263_BASE_PIOE 0xfffffa00 +#define AT91SAM9263_BASE_RSTC 0xfffffd00 #define AT91SAM9263_BASE_SHDWC 0xfffffd10 #define AT91SAM9263_BASE_RTT0 0xfffffd20 #define AT91SAM9263_BASE_PIT 0xfffffd30 diff --git a/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h b/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h index d27b15ba8ebf..e2f8da8ce5bc 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h +++ b/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h @@ -46,10 +46,10 @@ #define AT91_DDRSDRC_CAS_25 (6 << 4) #define AT91_DDRSDRC_RST_DLL (1 << 7) /* Reset DLL */ #define AT91_DDRSDRC_DICDS (1 << 8) /* Output impedance control */ -#define AT91_DDRSDRC_DIS_DLL (1 << 9) /* Disable DLL */ -#define AT91_DDRSDRC_OCD (1 << 12) /* Off-Chip Driver */ -#define AT91_DDRSDRC_DQMS (1 << 16) /* Mask Data is Shared */ -#define AT91_DDRSDRC_ACTBST (1 << 18) /* Active Bank X to Burst Stop Read Access Bank Y */ +#define AT91_DDRSDRC_DIS_DLL (1 << 9) /* Disable DLL [SAM9 Only] */ +#define AT91_DDRSDRC_OCD (1 << 12) /* Off-Chip Driver [SAM9 Only] */ +#define AT91_DDRSDRC_DQMS (1 << 16) /* Mask Data is Shared [SAM9 Only] */ +#define AT91_DDRSDRC_ACTBST (1 << 18) /* Active Bank X to Burst Stop Read Access Bank Y [SAM9 Only] */ #define AT91_DDRSDRC_T0PR 0x0C /* Timing 0 Register */ #define AT91_DDRSDRC_TRAS (0xf << 0) /* Active to Precharge delay */ @@ -59,7 +59,8 @@ #define AT91_DDRSDRC_TRP (0xf << 16) /* Row precharge delay */ #define AT91_DDRSDRC_TRRD (0xf << 20) /* Active BankA to BankB */ #define AT91_DDRSDRC_TWTR (0x7 << 24) /* Internal Write to Read delay */ -#define AT91_DDRSDRC_RED_WRRD (0x1 << 27) /* Reduce Write to Read Delay */ +#define AT91CAP9_DDRSDRC_TWTR (1 << 24) /* Internal Write to Read delay */ +#define AT91_DDRSDRC_RED_WRRD (0x1 << 27) /* Reduce Write to Read Delay [SAM9 Only] */ #define AT91_DDRSDRC_TMRD (0xf << 28) /* Load mode to active/refresh delay */ #define AT91_DDRSDRC_T1PR 0x10 /* Timing 1 Register */ @@ -68,13 +69,14 @@ #define AT91_DDRSDRC_TXSRD (0xff << 16) /* Exit self-refresh to read */ #define AT91_DDRSDRC_TXP (0xf << 24) /* Exit power-down delay */ -#define AT91_DDRSDRC_T2PR 0x14 /* Timing 2 Register */ +#define AT91_DDRSDRC_T2PR 0x14 /* Timing 2 Register [SAM9 Only] */ #define AT91_DDRSDRC_TXARD (0xf << 0) /* Exit active power down delay to read command in mode "Fast Exit" */ #define AT91_DDRSDRC_TXARDS (0xf << 4) /* Exit active power down delay to read command in mode "Slow Exit" */ #define AT91_DDRSDRC_TRPA (0xf << 8) /* Row Precharge All delay */ #define AT91_DDRSDRC_TRTP (0x7 << 12) /* Read to Precharge delay */ #define AT91_DDRSDRC_LPR 0x1C /* Low Power Register */ +#define AT91CAP9_DDRSDRC_LPR 0x18 /* Low Power Register */ #define AT91_DDRSDRC_LPCB (3 << 0) /* Low-power Configurations */ #define AT91_DDRSDRC_LPCB_DISABLE 0 #define AT91_DDRSDRC_LPCB_SELF_REFRESH 1 @@ -92,32 +94,40 @@ #define AT91_DDRSDRC_UPD_MR (3 << 20) /* Update load mode register and extended mode register */ #define AT91_DDRSDRC_MDR 0x20 /* Memory Device Register */ +#define AT91CAP9_DDRSDRC_MDR 0x1C /* Memory Device Register */ #define AT91_DDRSDRC_MD (3 << 0) /* Memory Device Type */ #define AT91_DDRSDRC_MD_SDR 0 #define AT91_DDRSDRC_MD_LOW_POWER_SDR 1 +#define AT91CAP9_DDRSDRC_MD_DDR 2 #define AT91_DDRSDRC_MD_LOW_POWER_DDR 3 -#define AT91_DDRSDRC_MD_DDR2 6 +#define AT91_DDRSDRC_MD_DDR2 6 /* [SAM9 Only] */ #define AT91_DDRSDRC_DBW (1 << 4) /* Data Bus Width */ #define AT91_DDRSDRC_DBW_32BITS (0 << 4) #define AT91_DDRSDRC_DBW_16BITS (1 << 4) #define AT91_DDRSDRC_DLL 0x24 /* DLL Information Register */ +#define AT91CAP9_DDRSDRC_DLL 0x20 /* DLL Information Register */ #define AT91_DDRSDRC_MDINC (1 << 0) /* Master Delay increment */ #define AT91_DDRSDRC_MDDEC (1 << 1) /* Master Delay decrement */ #define AT91_DDRSDRC_MDOVF (1 << 2) /* Master Delay Overflow */ +#define AT91CAP9_DDRSDRC_SDCOVF (1 << 3) /* Slave Delay Correction Overflow */ +#define AT91CAP9_DDRSDRC_SDCUDF (1 << 4) /* Slave Delay Correction Underflow */ +#define AT91CAP9_DDRSDRC_SDERF (1 << 5) /* Slave Delay Correction error */ #define AT91_DDRSDRC_MDVAL (0xff << 8) /* Master Delay value */ +#define AT91CAP9_DDRSDRC_SDVAL (0xff << 16) /* Slave Delay value */ +#define AT91CAP9_DDRSDRC_SDCVAL (0xff << 24) /* Slave Delay Correction value */ -#define AT91_DDRSDRC_HS 0x2C /* High Speed Register */ +#define AT91_DDRSDRC_HS 0x2C /* High Speed Register [SAM9 Only] */ #define AT91_DDRSDRC_DIS_ATCP_RD (1 << 2) /* Anticip read access is disabled */ #define AT91_DDRSDRC_DELAY(n) (0x30 + (0x4 * (n))) /* Delay I/O Register n */ -#define AT91_DDRSDRC_WPMR 0xE4 /* Write Protect Mode Register */ +#define AT91_DDRSDRC_WPMR 0xE4 /* Write Protect Mode Register [SAM9 Only] */ #define AT91_DDRSDRC_WP (1 << 0) /* Write protect enable */ #define AT91_DDRSDRC_WPKEY (0xffffff << 8) /* Write protect key */ #define AT91_DDRSDRC_KEY (0x444452 << 8) /* Write protect key = "DDR" */ -#define AT91_DDRSDRC_WPSR 0xE8 /* Write Protect Status Register */ +#define AT91_DDRSDRC_WPSR 0xE8 /* Write Protect Status Register [SAM9 Only] */ #define AT91_DDRSDRC_WPVS (1 << 0) /* Write protect violation status */ #define AT91_DDRSDRC_WPVSRC (0xffff << 8) /* Write protect violation source */ diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h index f0c23c960dec..dd9c95ea0862 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9g45.h +++ b/arch/arm/mach-at91/include/mach/at91sam9g45.h @@ -90,7 +90,6 @@ #define AT91_DDRSDRC0 (0xffffe600 - AT91_BASE_SYS) #define AT91_MATRIX (0xffffea00 - AT91_BASE_SYS) #define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) -#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) #define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS) #define AT91SAM9G45_BASE_ECC 0xffffe200 @@ -102,6 +101,7 @@ #define AT91SAM9G45_BASE_PIOC 0xfffff600 #define AT91SAM9G45_BASE_PIOD 0xfffff800 #define AT91SAM9G45_BASE_PIOE 0xfffffa00 +#define AT91SAM9G45_BASE_RSTC 0xfffffd00 #define AT91SAM9G45_BASE_SHDWC 0xfffffd10 #define AT91SAM9G45_BASE_RTT 0xfffffd20 #define AT91SAM9G45_BASE_PIT 0xfffffd30 diff --git a/arch/arm/mach-at91/include/mach/at91sam9rl.h b/arch/arm/mach-at91/include/mach/at91sam9rl.h index 2bb359e60b97..d7bead7118da 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9rl.h +++ b/arch/arm/mach-at91/include/mach/at91sam9rl.h @@ -72,7 +72,6 @@ #define AT91_SDRAMC0 (0xffffea00 - AT91_BASE_SYS) #define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS) #define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) -#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS) #define AT91_SCKCR (0xfffffd50 - AT91_BASE_SYS) #define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS) @@ -84,6 +83,7 @@ #define AT91SAM9RL_BASE_PIOB 0xfffff600 #define AT91SAM9RL_BASE_PIOC 0xfffff800 #define AT91SAM9RL_BASE_PIOD 0xfffffa00 +#define AT91SAM9RL_BASE_RSTC 0xfffffd00 #define AT91SAM9RL_BASE_SHDWC 0xfffffd10 #define AT91SAM9RL_BASE_RTT 0xfffffd20 #define AT91SAM9RL_BASE_PIT 0xfffffd30 diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index d0b377b21bd7..3b33f07b1e11 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -88,7 +88,7 @@ extern void __init at91_add_device_eth(struct macb_platform_data *data); struct at91_usbh_data { u8 ports; /* number of ports on root hub */ int vbus_pin[2]; /* port power-control pin */ - u8 vbus_pin_inverted; + u8 vbus_pin_active_low[2]; u8 overcurrent_supported; int overcurrent_pin[2]; u8 overcurrent_status[2]; diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 62ad95556c36..1606379ac284 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -34,7 +34,6 @@ /* * Show the reason for the previous system reset. */ -#if defined(AT91_RSTC) #include <mach/at91_rstc.h> #include <mach/at91_shdwc.h> @@ -58,10 +57,10 @@ static void __init show_reset_status(void) char *reason, *r2 = reset; u32 reset_type, wake_type; - if (!at91_shdwc_base) + if (!at91_shdwc_base || !at91_rstc_base) return; - reset_type = at91_sys_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP; + reset_type = at91_rstc_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP; wake_type = at91_shdwc_read(AT91_SHDW_SR); switch (reset_type) { @@ -102,10 +101,6 @@ static void __init show_reset_status(void) } pr_info("AT91: Starting after %s %s\n", reason, r2); } -#else -static void __init show_reset_status(void) {} -#endif - static int at91_pm_valid_state(suspend_state_t state) { diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index ce9a20699111..7eb40d24242f 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -25,21 +25,21 @@ static inline u32 sdram_selfrefresh_enable(void) : : "r" (0)) #elif defined(CONFIG_ARCH_AT91CAP9) -#include <mach/at91cap9_ddrsdr.h> +#include <mach/at91sam9_ddrsdr.h> static inline u32 sdram_selfrefresh_enable(void) { u32 saved_lpr, lpr; - saved_lpr = at91_ramc_read(0, AT91_DDRSDRC_LPR); + saved_lpr = at91_ramc_read(0, AT91CAP9_DDRSDRC_LPR); lpr = saved_lpr & ~AT91_DDRSDRC_LPCB; - at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr | AT91_DDRSDRC_LPCB_SELF_REFRESH); + at91_ramc_write(0, AT91CAP9_DDRSDRC_LPR, lpr | AT91_DDRSDRC_LPCB_SELF_REFRESH); return saved_lpr; } -#define sdram_selfrefresh_disable(saved_lpr) at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr) +#define sdram_selfrefresh_disable(saved_lpr) at91_ramc_write(0, AT91CAP9_DDRSDRC_LPR, saved_lpr) #define wait_for_interrupt_enable() cpu_do_idle() #elif defined(CONFIG_ARCH_AT91SAM9G45) diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S index f7922a436172..92dfb8461392 100644 --- a/arch/arm/mach-at91/pm_slowclock.S +++ b/arch/arm/mach-at91/pm_slowclock.S @@ -18,9 +18,8 @@ #if defined(CONFIG_ARCH_AT91RM9200) #include <mach/at91rm9200_mc.h> -#elif defined(CONFIG_ARCH_AT91CAP9) -#include <mach/at91cap9_ddrsdr.h> -#elif defined(CONFIG_ARCH_AT91SAM9G45) +#elif defined(CONFIG_ARCH_AT91CAP9) \ + || defined(CONFIG_ARCH_AT91SAM9G45) #include <mach/at91sam9_ddrsdr.h> #else #include <mach/at91sam9_sdramc.h> diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 8bdcc3cb6012..69d3fc4c46f3 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -29,9 +29,12 @@ EXPORT_SYMBOL(at91_soc_initdata); void __init at91rm9200_set_type(int type) { if (type == ARCH_REVISON_9200_PQFP) - at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA; - else at91_soc_initdata.subtype = AT91_SOC_RM9200_PQFP; + else + at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA; + + pr_info("AT91: filled in soc subtype: %s\n", + at91_get_soc_subtype(&at91_soc_initdata)); } void __init at91_init_irq_default(void) @@ -281,6 +284,15 @@ void __init at91_ioremap_shdwc(u32 base_addr) pm_power_off = at91sam9_poweroff; } +void __iomem *at91_rstc_base; + +void __init at91_ioremap_rstc(u32 base_addr) +{ + at91_rstc_base = ioremap(base_addr, 16); + if (!at91_rstc_base) + panic("Impossible to ioremap at91_rstc_base\n"); +} + void __init at91_initialize(unsigned long main_clock) { at91_boot_soc.ioremap_registers(); diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c index 9e5e7552498c..45c97b1ee9b1 100644 --- a/arch/arm/mach-bcmring/arch.c +++ b/arch/arm/mach-bcmring/arch.c @@ -194,6 +194,6 @@ MACHINE_START(BCMRING, "BCMRING") .init_early = bcmring_init_early, .init_irq = bcmring_init_irq, .timer = &bcmring_timer, - .init_machine = bcmring_init_machine + .init_machine = bcmring_init_machine, .restart = bcmring_restart, MACHINE_END diff --git a/arch/arm/mach-bcmring/dma.c b/arch/arm/mach-bcmring/dma.c index 1a1a27dd5654..1024396797e1 100644 --- a/arch/arm/mach-bcmring/dma.c +++ b/arch/arm/mach-bcmring/dma.c @@ -33,17 +33,11 @@ #include <mach/timer.h> -#include <linux/mm.h> #include <linux/pfn.h> #include <linux/atomic.h> #include <linux/sched.h> #include <mach/dma.h> -/* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */ -/* especially since dc4 doesn't use kmalloc'd memory. */ - -#define ALLOW_MAP_OF_KMALLOC_MEMORY 0 - /* ---- Public Variables ------------------------------------------------- */ /* ---- Private Constants and Types -------------------------------------- */ @@ -53,24 +47,12 @@ #define CONTROLLER_FROM_HANDLE(handle) (((handle) >> 4) & 0x0f) #define CHANNEL_FROM_HANDLE(handle) ((handle) & 0x0f) -#define DMA_MAP_DEBUG 0 - -#if DMA_MAP_DEBUG -# define DMA_MAP_PRINT(fmt, args...) printk("%s: " fmt, __func__, ## args) -#else -# define DMA_MAP_PRINT(fmt, args...) -#endif /* ---- Private Variables ------------------------------------------------ */ static DMA_Global_t gDMA; static struct proc_dir_entry *gDmaDir; -static atomic_t gDmaStatMemTypeKmalloc = ATOMIC_INIT(0); -static atomic_t gDmaStatMemTypeVmalloc = ATOMIC_INIT(0); -static atomic_t gDmaStatMemTypeUser = ATOMIC_INIT(0); -static atomic_t gDmaStatMemTypeCoherent = ATOMIC_INIT(0); - #include "dma_device.c" /* ---- Private Function Prototypes -------------------------------------- */ @@ -79,34 +61,6 @@ static atomic_t gDmaStatMemTypeCoherent = ATOMIC_INIT(0); /****************************************************************************/ /** -* Displays information for /proc/dma/mem-type -*/ -/****************************************************************************/ - -static int dma_proc_read_mem_type(char *buf, char **start, off_t offset, - int count, int *eof, void *data) -{ - int len = 0; - - len += sprintf(buf + len, "dma_map_mem statistics\n"); - len += - sprintf(buf + len, "coherent: %d\n", - atomic_read(&gDmaStatMemTypeCoherent)); - len += - sprintf(buf + len, "kmalloc: %d\n", - atomic_read(&gDmaStatMemTypeKmalloc)); - len += - sprintf(buf + len, "vmalloc: %d\n", - atomic_read(&gDmaStatMemTypeVmalloc)); - len += - sprintf(buf + len, "user: %d\n", - atomic_read(&gDmaStatMemTypeUser)); - - return len; -} - -/****************************************************************************/ -/** * Displays information for /proc/dma/channels */ /****************************************************************************/ @@ -846,8 +800,6 @@ int dma_init(void) dma_proc_read_channels, NULL); create_proc_read_entry("devices", 0, gDmaDir, dma_proc_read_devices, NULL); - create_proc_read_entry("mem-type", 0, gDmaDir, - dma_proc_read_mem_type, NULL); } out: @@ -1565,767 +1517,3 @@ int dma_set_device_handler(DMA_Device_t dev, /* Device to set the callback for. } EXPORT_SYMBOL(dma_set_device_handler); - -/****************************************************************************/ -/** -* Initializes a memory mapping structure -*/ -/****************************************************************************/ - -int dma_init_mem_map(DMA_MemMap_t *memMap) -{ - memset(memMap, 0, sizeof(*memMap)); - - sema_init(&memMap->lock, 1); - - return 0; -} - -EXPORT_SYMBOL(dma_init_mem_map); - -/****************************************************************************/ -/** -* Releases any memory currently being held by a memory mapping structure. -*/ -/****************************************************************************/ - -int dma_term_mem_map(DMA_MemMap_t *memMap) -{ - down(&memMap->lock); /* Just being paranoid */ - - /* Free up any allocated memory */ - - up(&memMap->lock); - memset(memMap, 0, sizeof(*memMap)); - - return 0; -} - -EXPORT_SYMBOL(dma_term_mem_map); - -/****************************************************************************/ -/** -* Looks at a memory address and categorizes it. -* -* @return One of the values from the DMA_MemType_t enumeration. -*/ -/****************************************************************************/ - -DMA_MemType_t dma_mem_type(void *addr) -{ - unsigned long addrVal = (unsigned long)addr; - - if (addrVal >= CONSISTENT_BASE) { - /* NOTE: DMA virtual memory space starts at 0xFFxxxxxx */ - - /* dma_alloc_xxx pages are physically and virtually contiguous */ - - return DMA_MEM_TYPE_DMA; - } - - /* Technically, we could add one more classification. Addresses between VMALLOC_END */ - /* and the beginning of the DMA virtual address could be considered to be I/O space. */ - /* Right now, nobody cares about this particular classification, so we ignore it. */ - - if (is_vmalloc_addr(addr)) { - /* Address comes from the vmalloc'd region. Pages are virtually */ - /* contiguous but NOT physically contiguous */ - - return DMA_MEM_TYPE_VMALLOC; - } - - if (addrVal >= PAGE_OFFSET) { - /* PAGE_OFFSET is typically 0xC0000000 */ - - /* kmalloc'd pages are physically contiguous */ - - return DMA_MEM_TYPE_KMALLOC; - } - - return DMA_MEM_TYPE_USER; -} - -EXPORT_SYMBOL(dma_mem_type); - -/****************************************************************************/ -/** -* Looks at a memory address and determines if we support DMA'ing to/from -* that type of memory. -* -* @return boolean - -* return value != 0 means dma supported -* return value == 0 means dma not supported -*/ -/****************************************************************************/ - -int dma_mem_supports_dma(void *addr) -{ - DMA_MemType_t memType = dma_mem_type(addr); - - return (memType == DMA_MEM_TYPE_DMA) -#if ALLOW_MAP_OF_KMALLOC_MEMORY - || (memType == DMA_MEM_TYPE_KMALLOC) -#endif - || (memType == DMA_MEM_TYPE_USER); -} - -EXPORT_SYMBOL(dma_mem_supports_dma); - -/****************************************************************************/ -/** -* Maps in a memory region such that it can be used for performing a DMA. -* -* @return -*/ -/****************************************************************************/ - -int dma_map_start(DMA_MemMap_t *memMap, /* Stores state information about the map */ - enum dma_data_direction dir /* Direction that the mapping will be going */ - ) { - int rc; - - down(&memMap->lock); - - DMA_MAP_PRINT("memMap: %p\n", memMap); - - if (memMap->inUse) { - printk(KERN_ERR "%s: memory map %p is already being used\n", - __func__, memMap); - rc = -EBUSY; - goto out; - } - - memMap->inUse = 1; - memMap->dir = dir; - memMap->numRegionsUsed = 0; - - rc = 0; - -out: - - DMA_MAP_PRINT("returning %d", rc); - - up(&memMap->lock); - - return rc; -} - -EXPORT_SYMBOL(dma_map_start); - -/****************************************************************************/ -/** -* Adds a segment of memory to a memory map. Each segment is both -* physically and virtually contiguous. -* -* @return 0 on success, error code otherwise. -*/ -/****************************************************************************/ - -static int dma_map_add_segment(DMA_MemMap_t *memMap, /* Stores state information about the map */ - DMA_Region_t *region, /* Region that the segment belongs to */ - void *virtAddr, /* Virtual address of the segment being added */ - dma_addr_t physAddr, /* Physical address of the segment being added */ - size_t numBytes /* Number of bytes of the segment being added */ - ) { - DMA_Segment_t *segment; - - DMA_MAP_PRINT("memMap:%p va:%p pa:0x%x #:%d\n", memMap, virtAddr, - physAddr, numBytes); - - /* Sanity check */ - - if (((unsigned long)virtAddr < (unsigned long)region->virtAddr) - || (((unsigned long)virtAddr + numBytes)) > - ((unsigned long)region->virtAddr + region->numBytes)) { - printk(KERN_ERR - "%s: virtAddr %p is outside region @ %p len: %d\n", - __func__, virtAddr, region->virtAddr, region->numBytes); - return -EINVAL; - } - - if (region->numSegmentsUsed > 0) { - /* Check to see if this segment is physically contiguous with the previous one */ - - segment = ®ion->segment[region->numSegmentsUsed - 1]; - - if ((segment->physAddr + segment->numBytes) == physAddr) { - /* It is - just add on to the end */ - - DMA_MAP_PRINT("appending %d bytes to last segment\n", - numBytes); - - segment->numBytes += numBytes; - - return 0; - } - } - - /* Reallocate to hold more segments, if required. */ - - if (region->numSegmentsUsed >= region->numSegmentsAllocated) { - DMA_Segment_t *newSegment; - size_t oldSize = - region->numSegmentsAllocated * sizeof(*newSegment); - int newAlloc = region->numSegmentsAllocated + 4; - size_t newSize = newAlloc * sizeof(*newSegment); - - newSegment = kmalloc(newSize, GFP_KERNEL); - if (newSegment == NULL) { - return -ENOMEM; - } - memcpy(newSegment, region->segment, oldSize); - memset(&((uint8_t *) newSegment)[oldSize], 0, - newSize - oldSize); - kfree(region->segment); - - region->numSegmentsAllocated = newAlloc; - region->segment = newSegment; - } - - segment = ®ion->segment[region->numSegmentsUsed]; - region->numSegmentsUsed++; - - segment->virtAddr = virtAddr; - segment->physAddr = physAddr; - segment->numBytes = numBytes; - - DMA_MAP_PRINT("returning success\n"); - - return 0; -} - -/****************************************************************************/ -/** -* Adds a region of memory to a memory map. Each region is virtually -* contiguous, but not necessarily physically contiguous. -* -* @return 0 on success, error code otherwise. -*/ -/****************************************************************************/ - -int dma_map_add_region(DMA_MemMap_t *memMap, /* Stores state information about the map */ - void *mem, /* Virtual address that we want to get a map of */ - size_t numBytes /* Number of bytes being mapped */ - ) { - unsigned long addr = (unsigned long)mem; - unsigned int offset; - int rc = 0; - DMA_Region_t *region; - dma_addr_t physAddr; - - down(&memMap->lock); - - DMA_MAP_PRINT("memMap:%p va:%p #:%d\n", memMap, mem, numBytes); - - if (!memMap->inUse) { - printk(KERN_ERR "%s: Make sure you call dma_map_start first\n", - __func__); - rc = -EINVAL; - goto out; - } - - /* Reallocate to hold more regions. */ - - if (memMap->numRegionsUsed >= memMap->numRegionsAllocated) { - DMA_Region_t *newRegion; - size_t oldSize = - memMap->numRegionsAllocated * sizeof(*newRegion); - int newAlloc = memMap->numRegionsAllocated + 4; - size_t newSize = newAlloc * sizeof(*newRegion); - - newRegion = kmalloc(newSize, GFP_KERNEL); - if (newRegion == NULL) { - rc = -ENOMEM; - goto out; - } - memcpy(newRegion, memMap->region, oldSize); - memset(&((uint8_t *) newRegion)[oldSize], 0, newSize - oldSize); - - kfree(memMap->region); - - memMap->numRegionsAllocated = newAlloc; - memMap->region = newRegion; - } - - region = &memMap->region[memMap->numRegionsUsed]; - memMap->numRegionsUsed++; - - offset = addr & ~PAGE_MASK; - - region->memType = dma_mem_type(mem); - region->virtAddr = mem; - region->numBytes = numBytes; - region->numSegmentsUsed = 0; - region->numLockedPages = 0; - region->lockedPages = NULL; - - switch (region->memType) { - case DMA_MEM_TYPE_VMALLOC: - { - atomic_inc(&gDmaStatMemTypeVmalloc); - - /* printk(KERN_ERR "%s: vmalloc'd pages are not supported\n", __func__); */ - - /* vmalloc'd pages are not physically contiguous */ - - rc = -EINVAL; - break; - } - - case DMA_MEM_TYPE_KMALLOC: - { - atomic_inc(&gDmaStatMemTypeKmalloc); - - /* kmalloc'd pages are physically contiguous, so they'll have exactly */ - /* one segment */ - -#if ALLOW_MAP_OF_KMALLOC_MEMORY - physAddr = - dma_map_single(NULL, mem, numBytes, memMap->dir); - rc = dma_map_add_segment(memMap, region, mem, physAddr, - numBytes); -#else - rc = -EINVAL; -#endif - break; - } - - case DMA_MEM_TYPE_DMA: - { - /* dma_alloc_xxx pages are physically contiguous */ - - atomic_inc(&gDmaStatMemTypeCoherent); - - physAddr = (vmalloc_to_pfn(mem) << PAGE_SHIFT) + offset; - - dma_sync_single_for_cpu(NULL, physAddr, numBytes, - memMap->dir); - rc = dma_map_add_segment(memMap, region, mem, physAddr, - numBytes); - break; - } - - case DMA_MEM_TYPE_USER: - { - size_t firstPageOffset; - size_t firstPageSize; - struct page **pages; - struct task_struct *userTask; - - atomic_inc(&gDmaStatMemTypeUser); - -#if 1 - /* If the pages are user pages, then the dma_mem_map_set_user_task function */ - /* must have been previously called. */ - - if (memMap->userTask == NULL) { - printk(KERN_ERR - "%s: must call dma_mem_map_set_user_task when using user-mode memory\n", - __func__); - return -EINVAL; - } - - /* User pages need to be locked. */ - - firstPageOffset = - (unsigned long)region->virtAddr & (PAGE_SIZE - 1); - firstPageSize = PAGE_SIZE - firstPageOffset; - - region->numLockedPages = (firstPageOffset - + region->numBytes + - PAGE_SIZE - 1) / PAGE_SIZE; - pages = - kmalloc(region->numLockedPages * - sizeof(struct page *), GFP_KERNEL); - - if (pages == NULL) { - region->numLockedPages = 0; - return -ENOMEM; - } - - userTask = memMap->userTask; - - down_read(&userTask->mm->mmap_sem); - rc = get_user_pages(userTask, /* task */ - userTask->mm, /* mm */ - (unsigned long)region->virtAddr, /* start */ - region->numLockedPages, /* len */ - memMap->dir == DMA_FROM_DEVICE, /* write */ - 0, /* force */ - pages, /* pages (array of pointers to page) */ - NULL); /* vmas */ - up_read(&userTask->mm->mmap_sem); - - if (rc != region->numLockedPages) { - kfree(pages); - region->numLockedPages = 0; - - if (rc >= 0) { - rc = -EINVAL; - } - } else { - uint8_t *virtAddr = region->virtAddr; - size_t bytesRemaining; - int pageIdx; - - rc = 0; /* Since get_user_pages returns +ve number */ - - region->lockedPages = pages; - - /* We've locked the user pages. Now we need to walk them and figure */ - /* out the physical addresses. */ - - /* The first page may be partial */ - - dma_map_add_segment(memMap, - region, - virtAddr, - PFN_PHYS(page_to_pfn - (pages[0])) + - firstPageOffset, - firstPageSize); - - virtAddr += firstPageSize; - bytesRemaining = - region->numBytes - firstPageSize; - - for (pageIdx = 1; - pageIdx < region->numLockedPages; - pageIdx++) { - size_t bytesThisPage = - (bytesRemaining > - PAGE_SIZE ? PAGE_SIZE : - bytesRemaining); - - DMA_MAP_PRINT - ("pageIdx:%d pages[pageIdx]=%p pfn=%u phys=%u\n", - pageIdx, pages[pageIdx], - page_to_pfn(pages[pageIdx]), - PFN_PHYS(page_to_pfn - (pages[pageIdx]))); - - dma_map_add_segment(memMap, - region, - virtAddr, - PFN_PHYS(page_to_pfn - (pages - [pageIdx])), - bytesThisPage); - - virtAddr += bytesThisPage; - bytesRemaining -= bytesThisPage; - } - } -#else - printk(KERN_ERR - "%s: User mode pages are not yet supported\n", - __func__); - - /* user pages are not physically contiguous */ - - rc = -EINVAL; -#endif - break; - } - - default: - { - printk(KERN_ERR "%s: Unsupported memory type: %d\n", - __func__, region->memType); - - rc = -EINVAL; - break; - } - } - - if (rc != 0) { - memMap->numRegionsUsed--; - } - -out: - - DMA_MAP_PRINT("returning %d\n", rc); - - up(&memMap->lock); - - return rc; -} - -EXPORT_SYMBOL(dma_map_add_segment); - -/****************************************************************************/ -/** -* Maps in a memory region such that it can be used for performing a DMA. -* -* @return 0 on success, error code otherwise. -*/ -/****************************************************************************/ - -int dma_map_mem(DMA_MemMap_t *memMap, /* Stores state information about the map */ - void *mem, /* Virtual address that we want to get a map of */ - size_t numBytes, /* Number of bytes being mapped */ - enum dma_data_direction dir /* Direction that the mapping will be going */ - ) { - int rc; - - rc = dma_map_start(memMap, dir); - if (rc == 0) { - rc = dma_map_add_region(memMap, mem, numBytes); - if (rc < 0) { - /* Since the add fails, this function will fail, and the caller won't */ - /* call unmap, so we need to do it here. */ - - dma_unmap(memMap, 0); - } - } - - return rc; -} - -EXPORT_SYMBOL(dma_map_mem); - -/****************************************************************************/ -/** -* Setup a descriptor ring for a given memory map. -* -* It is assumed that the descriptor ring has already been initialized, and -* this routine will only reallocate a new descriptor ring if the existing -* one is too small. -* -* @return 0 on success, error code otherwise. -*/ -/****************************************************************************/ - -int dma_map_create_descriptor_ring(DMA_Device_t dev, /* DMA device (where the ring is stored) */ - DMA_MemMap_t *memMap, /* Memory map that will be used */ - dma_addr_t devPhysAddr /* Physical address of device */ - ) { - int rc; - int numDescriptors; - DMA_DeviceAttribute_t *devAttr; - DMA_Region_t *region; - DMA_Segment_t *segment; - dma_addr_t srcPhysAddr; - dma_addr_t dstPhysAddr; - int regionIdx; - int segmentIdx; - - devAttr = &DMA_gDeviceAttribute[dev]; - - down(&memMap->lock); - - /* Figure out how many descriptors we need */ - - numDescriptors = 0; - for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) { - region = &memMap->region[regionIdx]; - - for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed; - segmentIdx++) { - segment = ®ion->segment[segmentIdx]; - - if (memMap->dir == DMA_TO_DEVICE) { - srcPhysAddr = segment->physAddr; - dstPhysAddr = devPhysAddr; - } else { - srcPhysAddr = devPhysAddr; - dstPhysAddr = segment->physAddr; - } - - rc = - dma_calculate_descriptor_count(dev, srcPhysAddr, - dstPhysAddr, - segment-> - numBytes); - if (rc < 0) { - printk(KERN_ERR - "%s: dma_calculate_descriptor_count failed: %d\n", - __func__, rc); - goto out; - } - numDescriptors += rc; - } - } - - /* Adjust the size of the ring, if it isn't big enough */ - - if (numDescriptors > devAttr->ring.descriptorsAllocated) { - dma_free_descriptor_ring(&devAttr->ring); - rc = - dma_alloc_descriptor_ring(&devAttr->ring, - numDescriptors); - if (rc < 0) { - printk(KERN_ERR - "%s: dma_alloc_descriptor_ring failed: %d\n", - __func__, rc); - goto out; - } - } else { - rc = - dma_init_descriptor_ring(&devAttr->ring, - numDescriptors); - if (rc < 0) { - printk(KERN_ERR - "%s: dma_init_descriptor_ring failed: %d\n", - __func__, rc); - goto out; - } - } - - /* Populate the descriptors */ - - for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) { - region = &memMap->region[regionIdx]; - - for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed; - segmentIdx++) { - segment = ®ion->segment[segmentIdx]; - - if (memMap->dir == DMA_TO_DEVICE) { - srcPhysAddr = segment->physAddr; - dstPhysAddr = devPhysAddr; - } else { - srcPhysAddr = devPhysAddr; - dstPhysAddr = segment->physAddr; - } - - rc = - dma_add_descriptors(&devAttr->ring, dev, - srcPhysAddr, dstPhysAddr, - segment->numBytes); - if (rc < 0) { - printk(KERN_ERR - "%s: dma_add_descriptors failed: %d\n", - __func__, rc); - goto out; - } - } - } - - rc = 0; - -out: - - up(&memMap->lock); - return rc; -} - -EXPORT_SYMBOL(dma_map_create_descriptor_ring); - -/****************************************************************************/ -/** -* Maps in a memory region such that it can be used for performing a DMA. -* -* @return -*/ -/****************************************************************************/ - -int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */ - int dirtied /* non-zero if any of the pages were modified */ - ) { - - int rc = 0; - int regionIdx; - int segmentIdx; - DMA_Region_t *region; - DMA_Segment_t *segment; - - down(&memMap->lock); - - for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) { - region = &memMap->region[regionIdx]; - - for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed; - segmentIdx++) { - segment = ®ion->segment[segmentIdx]; - - switch (region->memType) { - case DMA_MEM_TYPE_VMALLOC: - { - printk(KERN_ERR - "%s: vmalloc'd pages are not yet supported\n", - __func__); - rc = -EINVAL; - goto out; - } - - case DMA_MEM_TYPE_KMALLOC: - { -#if ALLOW_MAP_OF_KMALLOC_MEMORY - dma_unmap_single(NULL, - segment->physAddr, - segment->numBytes, - memMap->dir); -#endif - break; - } - - case DMA_MEM_TYPE_DMA: - { - dma_sync_single_for_cpu(NULL, - segment-> - physAddr, - segment-> - numBytes, - memMap->dir); - break; - } - - case DMA_MEM_TYPE_USER: - { - /* Nothing to do here. */ - - break; - } - - default: - { - printk(KERN_ERR - "%s: Unsupported memory type: %d\n", - __func__, region->memType); - rc = -EINVAL; - goto out; - } - } - - segment->virtAddr = NULL; - segment->physAddr = 0; - segment->numBytes = 0; - } - - if (region->numLockedPages > 0) { - int pageIdx; - - /* Some user pages were locked. We need to go and unlock them now. */ - - for (pageIdx = 0; pageIdx < region->numLockedPages; - pageIdx++) { - struct page *page = - region->lockedPages[pageIdx]; - - if (memMap->dir == DMA_FROM_DEVICE) { - SetPageDirty(page); - } - page_cache_release(page); - } - kfree(region->lockedPages); - region->numLockedPages = 0; - region->lockedPages = NULL; - } - - region->memType = DMA_MEM_TYPE_NONE; - region->virtAddr = NULL; - region->numBytes = 0; - region->numSegmentsUsed = 0; - } - memMap->userTask = NULL; - memMap->numRegionsUsed = 0; - memMap->inUse = 0; - -out: - up(&memMap->lock); - - return rc; -} - -EXPORT_SYMBOL(dma_unmap); diff --git a/arch/arm/mach-bcmring/include/mach/dma.h b/arch/arm/mach-bcmring/include/mach/dma.h index 1f2c5319c056..72543781207b 100644 --- a/arch/arm/mach-bcmring/include/mach/dma.h +++ b/arch/arm/mach-bcmring/include/mach/dma.h @@ -26,15 +26,9 @@ /* ---- Include Files ---------------------------------------------------- */ #include <linux/kernel.h> -#include <linux/wait.h> #include <linux/semaphore.h> #include <csp/dmacHw.h> #include <mach/timer.h> -#include <linux/scatterlist.h> -#include <linux/dma-mapping.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <linux/pagemap.h> /* ---- Constants and Types ---------------------------------------------- */ @@ -113,78 +107,6 @@ typedef struct { /**************************************************************************** * -* The DMA_MemType_t and DMA_MemMap_t are helper structures used to setup -* DMA chains from a variety of memory sources. -* -*****************************************************************************/ - -#define DMA_MEM_MAP_MIN_SIZE 4096 /* Pages less than this size are better */ - /* off not being DMA'd. */ - -typedef enum { - DMA_MEM_TYPE_NONE, /* Not a valid setting */ - DMA_MEM_TYPE_VMALLOC, /* Memory came from vmalloc call */ - DMA_MEM_TYPE_KMALLOC, /* Memory came from kmalloc call */ - DMA_MEM_TYPE_DMA, /* Memory came from dma_alloc_xxx call */ - DMA_MEM_TYPE_USER, /* Memory came from user space. */ - -} DMA_MemType_t; - -/* A segment represents a physically and virtually contiguous chunk of memory. */ -/* i.e. each segment can be DMA'd */ -/* A user of the DMA code will add memory regions. Each region may need to be */ -/* represented by one or more segments. */ - -typedef struct { - void *virtAddr; /* Virtual address used for this segment */ - dma_addr_t physAddr; /* Physical address this segment maps to */ - size_t numBytes; /* Size of the segment, in bytes */ - -} DMA_Segment_t; - -/* A region represents a virtually contiguous chunk of memory, which may be */ -/* made up of multiple segments. */ - -typedef struct { - DMA_MemType_t memType; - void *virtAddr; - size_t numBytes; - - /* Each region (virtually contiguous) consists of one or more segments. Each */ - /* segment is virtually and physically contiguous. */ - - int numSegmentsUsed; - int numSegmentsAllocated; - DMA_Segment_t *segment; - - /* When a region corresponds to user memory, we need to lock all of the pages */ - /* down before we can figure out the physical addresses. The lockedPage array contains */ - /* the pages that were locked, and which subsequently need to be unlocked once the */ - /* memory is unmapped. */ - - unsigned numLockedPages; - struct page **lockedPages; - -} DMA_Region_t; - -typedef struct { - int inUse; /* Is this mapping currently being used? */ - struct semaphore lock; /* Acquired when using this structure */ - enum dma_data_direction dir; /* Direction this transfer is intended for */ - - /* In the event that we're mapping user memory, we need to know which task */ - /* the memory is for, so that we can obtain the correct mm locks. */ - - struct task_struct *userTask; - - int numRegionsUsed; - int numRegionsAllocated; - DMA_Region_t *region; - -} DMA_MemMap_t; - -/**************************************************************************** -* * The DMA_DeviceAttribute_t contains information which describes a * particular DMA device (or peripheral). * @@ -570,124 +492,6 @@ int dma_alloc_double_dst_descriptors(DMA_Handle_t handle, /* DMA Handle */ /****************************************************************************/ /** -* Initializes a DMA_MemMap_t data structure -*/ -/****************************************************************************/ - -int dma_init_mem_map(DMA_MemMap_t *memMap /* Stores state information about the map */ - ); - -/****************************************************************************/ -/** -* Releases any memory currently being held by a memory mapping structure. -*/ -/****************************************************************************/ - -int dma_term_mem_map(DMA_MemMap_t *memMap /* Stores state information about the map */ - ); - -/****************************************************************************/ -/** -* Looks at a memory address and categorizes it. -* -* @return One of the values from the DMA_MemType_t enumeration. -*/ -/****************************************************************************/ - -DMA_MemType_t dma_mem_type(void *addr); - -/****************************************************************************/ -/** -* Sets the process (aka userTask) associated with a mem map. This is -* required if user-mode segments will be added to the mapping. -*/ -/****************************************************************************/ - -static inline void dma_mem_map_set_user_task(DMA_MemMap_t *memMap, - struct task_struct *task) -{ - memMap->userTask = task; -} - -/****************************************************************************/ -/** -* Looks at a memory address and determines if we support DMA'ing to/from -* that type of memory. -* -* @return boolean - -* return value != 0 means dma supported -* return value == 0 means dma not supported -*/ -/****************************************************************************/ - -int dma_mem_supports_dma(void *addr); - -/****************************************************************************/ -/** -* Initializes a memory map for use. Since this function acquires a -* sempaphore within the memory map, it is VERY important that dma_unmap -* be called when you're finished using the map. -*/ -/****************************************************************************/ - -int dma_map_start(DMA_MemMap_t *memMap, /* Stores state information about the map */ - enum dma_data_direction dir /* Direction that the mapping will be going */ - ); - -/****************************************************************************/ -/** -* Adds a segment of memory to a memory map. -* -* @return 0 on success, error code otherwise. -*/ -/****************************************************************************/ - -int dma_map_add_region(DMA_MemMap_t *memMap, /* Stores state information about the map */ - void *mem, /* Virtual address that we want to get a map of */ - size_t numBytes /* Number of bytes being mapped */ - ); - -/****************************************************************************/ -/** -* Creates a descriptor ring from a memory mapping. -* -* @return 0 on success, error code otherwise. -*/ -/****************************************************************************/ - -int dma_map_create_descriptor_ring(DMA_Device_t dev, /* DMA device (where the ring is stored) */ - DMA_MemMap_t *memMap, /* Memory map that will be used */ - dma_addr_t devPhysAddr /* Physical address of device */ - ); - -/****************************************************************************/ -/** -* Maps in a memory region such that it can be used for performing a DMA. -* -* @return -*/ -/****************************************************************************/ - -int dma_map_mem(DMA_MemMap_t *memMap, /* Stores state information about the map */ - void *addr, /* Virtual address that we want to get a map of */ - size_t count, /* Number of bytes being mapped */ - enum dma_data_direction dir /* Direction that the mapping will be going */ - ); - -/****************************************************************************/ -/** -* Maps in a memory region such that it can be used for performing a DMA. -* -* @return -*/ -/****************************************************************************/ - -int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */ - int dirtied /* non-zero if any of the pages were modified */ - ); - -/****************************************************************************/ -/** * Initiates a transfer when the descriptors have already been setup. * * This is a special case, and normally, the dma_transfer_xxx functions should diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 6b22b543a83f..d5088900af6c 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -44,7 +44,7 @@ #include <mach/aemif.h> #include <mach/spi.h> -#define DA850_EVM_PHY_ID "0:00" +#define DA850_EVM_PHY_ID "davinci_mdio-0:00" #define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8) #define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15) diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index 346e1de2f5a8..849311d3cb7c 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -54,7 +54,7 @@ static inline int have_tvp7002(void) return 0; } -#define DM365_EVM_PHY_ID "0:01" +#define DM365_EVM_PHY_ID "davinci_mdio-0:01" /* * A MAX-II CPLD is used for various board control functions. */ diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index a64b49cfedca..1247ecdcf752 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -40,7 +40,7 @@ #include <mach/usb.h> #include <mach/aemif.h> -#define DM644X_EVM_PHY_ID "0:01" +#define DM644X_EVM_PHY_ID "davinci_mdio-0:01" #define LXT971_PHY_ID (0x001378e2) #define LXT971_PHY_MASK (0xfffffff0) diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 64017558860b..872ac69fa049 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -736,7 +736,7 @@ static struct davinci_uart_config uart_config __initdata = { .enabled_uarts = (1 << 0), }; -#define DM646X_EVM_PHY_ID "0:01" +#define DM646X_EVM_PHY_ID "davinci_mdio-0:01" /* * The following EDMA channels/slots are not being used by drivers (for * example: Timer, GPIO, UART events etc) on dm646x, hence they are being diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 6c4a16415d47..8d34f513d415 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -39,7 +39,7 @@ #include <mach/mmc.h> #include <mach/usb.h> -#define NEUROS_OSD2_PHY_ID "0:01" +#define NEUROS_OSD2_PHY_ID "davinci_mdio-0:01" #define LXT971_PHY_ID 0x001378e2 #define LXT971_PHY_MASK 0xfffffff0 diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c index e7c0c7c53493..45e815760a27 100644 --- a/arch/arm/mach-davinci/board-omapl138-hawk.c +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -21,7 +21,7 @@ #include <mach/da8xx.h> #include <mach/mux.h> -#define HAWKBOARD_PHY_ID "0:07" +#define HAWKBOARD_PHY_ID "davinci_mdio-0:07" #define DA850_HAWK_MMCSD_CD_PIN GPIO_TO_PIN(3, 12) #define DA850_HAWK_MMCSD_WP_PIN GPIO_TO_PIN(3, 13) diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 0b136a831c59..31da3c5b2ba3 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -42,7 +42,7 @@ #include <mach/mux.h> #include <mach/usb.h> -#define SFFSDR_PHY_ID "0:01" +#define SFFSDR_PHY_ID "davinci_mdio-0:01" static struct mtd_partition davinci_sffsdr_nandflash_partition[] = { /* U-Boot Environment: Block 0 * UBL: Block 1 diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 0ed7fdb64efb..992c4c410185 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -153,34 +153,6 @@ static struct clk pll1_sysclk3 = { .div_reg = PLLDIV3, }; -static struct clk pll1_sysclk4 = { - .name = "pll1_sysclk4", - .parent = &pll1_clk, - .flags = CLK_PLL, - .div_reg = PLLDIV4, -}; - -static struct clk pll1_sysclk5 = { - .name = "pll1_sysclk5", - .parent = &pll1_clk, - .flags = CLK_PLL, - .div_reg = PLLDIV5, -}; - -static struct clk pll1_sysclk6 = { - .name = "pll0_sysclk6", - .parent = &pll0_clk, - .flags = CLK_PLL, - .div_reg = PLLDIV6, -}; - -static struct clk pll1_sysclk7 = { - .name = "pll1_sysclk7", - .parent = &pll1_clk, - .flags = CLK_PLL, - .div_reg = PLLDIV7, -}; - static struct clk i2c0_clk = { .name = "i2c0", .parent = &pll0_aux_clk, @@ -397,10 +369,6 @@ static struct clk_lookup da850_clks[] = { CLK(NULL, "pll1_aux", &pll1_aux_clk), CLK(NULL, "pll1_sysclk2", &pll1_sysclk2), CLK(NULL, "pll1_sysclk3", &pll1_sysclk3), - CLK(NULL, "pll1_sysclk4", &pll1_sysclk4), - CLK(NULL, "pll1_sysclk5", &pll1_sysclk5), - CLK(NULL, "pll1_sysclk6", &pll1_sysclk6), - CLK(NULL, "pll1_sysclk7", &pll1_sysclk7), CLK("i2c_davinci.1", NULL, &i2c0_clk), CLK(NULL, "timer0", &timerp64_0_clk), CLK("watchdog", NULL, &timerp64_1_clk), diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c index da70e7e39937..dd1ad55524c9 100644 --- a/arch/arm/mach-exynos/hotplug.c +++ b/arch/arm/mach-exynos/hotplug.c @@ -16,6 +16,7 @@ #include <linux/io.h> #include <asm/cacheflush.h> +#include <asm/smp_plat.h> #include <mach/regs-pmu.h> diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 683aec786b78..0f2035a1eb6e 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -23,6 +23,7 @@ #include <asm/cacheflush.h> #include <asm/hardware/gic.h> +#include <asm/smp_plat.h> #include <asm/smp_scu.h> #include <mach/hardware.h> diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 7afbe1e55beb..8394d512a402 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -25,6 +25,7 @@ #include <linux/smp.h> #include <asm/cacheflush.h> +#include <asm/smp_plat.h> #include <asm/smp_scu.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/timer-sp.h> @@ -72,9 +73,7 @@ static void __init highbank_map_io(void) void highbank_set_cpu_jump(int cpu, void *jump_addr) { -#ifdef CONFIG_SMP cpu = cpu_logical_map(cpu); -#endif writel(virt_to_phys(jump_addr), HB_JUMP_TABLE_VIRT(cpu)); __cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16); outer_clean_range(HB_JUMP_TABLE_PHYS(cpu), diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 09f357bcecde..4defb97bbfc8 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -87,7 +87,6 @@ config SOC_IMX35 config SOC_IMX5 select CPU_V7 - select ARM_L1_CACHE_SHIFT_6 select MXC_TZIC select ARCH_MXC_IOMUX_V3 select ARCH_MXC_AUDMUX_V2 diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c index 9273c2a24b54..2d88f8b9a454 100644 --- a/arch/arm/mach-imx/clock-imx6q.c +++ b/arch/arm/mach-imx/clock-imx6q.c @@ -814,6 +814,16 @@ DEF_PFD(pll3_pfd_540m, PFD_480, PFD1, &pll3_usb_otg); DEF_PFD(pll3_pfd_508m, PFD_480, PFD2, &pll3_usb_otg); DEF_PFD(pll3_pfd_454m, PFD_480, PFD3, &pll3_usb_otg); +static unsigned long twd_clk_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / 2; +} + +static struct clk twd_clk = { + .parent = &arm_clk, + .get_rate = twd_clk_get_rate, +}; + static unsigned long pll2_200m_get_rate(struct clk *clk) { return clk_get_rate(clk->parent) / 2; @@ -1894,6 +1904,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("20ec000.sdma", NULL, sdma_clk), _REGISTER_CLOCK("20bc000.wdog", NULL, dummy_clk), _REGISTER_CLOCK("20c0000.wdog", NULL, dummy_clk), + _REGISTER_CLOCK("smp_twd", NULL, twd_clk), _REGISTER_CLOCK(NULL, "ckih", ckih_clk), _REGISTER_CLOCK(NULL, "ckil_clk", ckil_clk), _REGISTER_CLOCK(NULL, "aips_tz1_clk", aips_tz1_clk), diff --git a/arch/arm/mach-imx/mach-mx53_ard.c b/arch/arm/mach-imx/mach-mx53_ard.c index 08dfb7628d2d..753f4fc9ec04 100644 --- a/arch/arm/mach-imx/mach-mx53_ard.c +++ b/arch/arm/mach-imx/mach-mx53_ard.c @@ -188,8 +188,10 @@ static int weim_cs_config(void) return -ENOMEM; iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K); - if (!iomuxc_base) + if (!iomuxc_base) { + iounmap(weim_base); return -ENOMEM; + } /* CS1 timings for LAN9220 */ writel(0x20001, (weim_base + 0x18)); diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c index 29bd1243781e..e15f1555c59b 100644 --- a/arch/arm/mach-imx/src.c +++ b/arch/arm/mach-imx/src.c @@ -15,6 +15,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/smp.h> +#include <asm/smp_plat.h> #define SRC_SCR 0x000 #define SRC_GPR1 0x020 @@ -24,10 +25,6 @@ static void __iomem *src_base; -#ifndef CONFIG_SMP -#define cpu_logical_map(cpu) 0 -#endif - void imx_enable_cpu(int cpu, bool enable) { u32 mask, val; diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c index 41c252de0215..a446fc14221f 100644 --- a/arch/arm/mach-msm/hotplug.c +++ b/arch/arm/mach-msm/hotplug.c @@ -11,6 +11,7 @@ #include <linux/smp.h> #include <asm/cacheflush.h> +#include <asm/smp_plat.h> extern volatile int pen_release; diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index 0b3e357c4c8c..db0117ec55f4 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -20,6 +20,7 @@ #include <asm/cacheflush.h> #include <asm/cputype.h> #include <asm/mach-types.h> +#include <asm/smp_plat.h> #include <mach/msm_iomap.h> diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index a8ba7b96dcd1..d965da45160e 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -33,7 +33,6 @@ config ARCH_OMAP3 default y select CPU_V7 select USB_ARCH_HAS_EHCI - select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4 select ARCH_HAS_OPP select PM_OPP if PM select ARM_CPU_SUSPEND if PM @@ -214,13 +213,12 @@ config MACH_OMAP3_PANDORA depends on ARCH_OMAP3 default y select OMAP_PACKAGE_CBB - select REGULATOR_FIXED_VOLTAGE + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_OMAP3_TOUCHBOOK bool "OMAP3 Touch Book" depends on ARCH_OMAP3 default y - select BACKLIGHT_CLASS_DEVICE config MACH_OMAP_3430SDP bool "OMAP 3430 SDP board" @@ -266,7 +264,7 @@ config MACH_OMAP_ZOOM2 select SERIAL_8250 select SERIAL_CORE_CONSOLE select SERIAL_8250_CONSOLE - select REGULATOR_FIXED_VOLTAGE + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_OMAP_ZOOM3 bool "OMAP3630 Zoom3 board" @@ -276,7 +274,7 @@ config MACH_OMAP_ZOOM3 select SERIAL_8250 select SERIAL_CORE_CONSOLE select SERIAL_8250_CONSOLE - select REGULATOR_FIXED_VOLTAGE + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_CM_T35 bool "CompuLab CM-T35/CM-T3730 modules" @@ -335,7 +333,7 @@ config MACH_OMAP_4430SDP depends on ARCH_OMAP4 select OMAP_PACKAGE_CBL select OMAP_PACKAGE_CBS - select REGULATOR_FIXED_VOLTAGE + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_OMAP4_PANDA bool "OMAP4 Panda Board" @@ -343,7 +341,7 @@ config MACH_OMAP4_PANDA depends on ARCH_OMAP4 select OMAP_PACKAGE_CBL select OMAP_PACKAGE_CBS - select REGULATOR_FIXED_VOLTAGE + select REGULATOR_FIXED_VOLTAGE if REGULATOR config OMAP3_EMU bool "OMAP3 debugging peripherals" diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 0b510ad01a00..283d11eae693 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -405,6 +405,7 @@ static int omap_mcspi_init(struct omap_hwmod *oh, void *unused) break; default: pr_err("Invalid McSPI Revision value\n"); + kfree(pdata); return -EINVAL; } diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 130034bf01d5..dfffbbf4c009 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -528,7 +528,13 @@ int gpmc_cs_configure(int cs, int cmd, int wval) case GPMC_CONFIG_DEV_SIZE: regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + /* clear 2 target bits */ + regval &= ~GPMC_CONFIG1_DEVICESIZE(3); + + /* set the proper value */ regval |= GPMC_CONFIG1_DEVICESIZE(wval); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); break; diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index bd844af13af5..ad0adb5a1e0e 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -175,14 +175,15 @@ static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) { u32 reg; - if (mmc->slots[0].internal_clock) { - reg = omap_ctrl_readl(control_devconf1_offset); + reg = omap_ctrl_readl(control_devconf1_offset); + if (mmc->slots[0].internal_clock) reg |= OMAP2_MMCSDIO2ADPCLKISEL; - omap_ctrl_writel(reg, control_devconf1_offset); - } + else + reg &= ~OMAP2_MMCSDIO2ADPCLKISEL; + omap_ctrl_writel(reg, control_devconf1_offset); } -static void hsmmc23_before_set_reg(struct device *dev, int slot, +static void hsmmc2_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { struct omap_mmc_platform_data *mmc = dev->platform_data; @@ -407,14 +408,13 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, c->caps &= ~MMC_CAP_8_BIT_DATA; c->caps |= MMC_CAP_4_BIT_DATA; } - /* FALLTHROUGH */ - case 3: if (mmc->slots[0].features & HSMMC_HAS_PBIAS) { /* off-chip level shifting, or none */ - mmc->slots[0].before_set_reg = hsmmc23_before_set_reg; + mmc->slots[0].before_set_reg = hsmmc2_before_set_reg; mmc->slots[0].after_set_reg = NULL; } break; + case 3: case 4: case 5: mmc->slots[0].before_set_reg = NULL; diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 3f174d51f67f..eb50c29fb644 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -388,7 +388,7 @@ static void __init omap_hwmod_init_postsetup(void) omap_pm_if_early_init(); } -#ifdef CONFIG_ARCH_OMAP2 +#ifdef CONFIG_SOC_OMAP2420 void __init omap2420_init_early(void) { omap2_set_globals_242x(); @@ -400,7 +400,9 @@ void __init omap2420_init_early(void) omap_hwmod_init_postsetup(); omap2420_clk_init(); } +#endif +#ifdef CONFIG_SOC_OMAP2430 void __init omap2430_init_early(void) { omap2_set_globals_243x(); diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c index c11273da5dcc..f08e442af397 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c @@ -56,27 +56,6 @@ struct omap_hwmod_class omap2_dss_hwmod_class = { }; /* - * 'dispc' class - * display controller - */ - -static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = { - .rev_offs = 0x0000, - .sysc_offs = 0x0010, - .syss_offs = 0x0014, - .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE | - SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | - MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), - .sysc_fields = &omap_hwmod_sysc_type1, -}; - -struct omap_hwmod_class omap2_dispc_hwmod_class = { - .name = "dispc", - .sysc = &omap2_dispc_sysc, -}; - -/* * 'rfbi' class * remote frame buffer interface */ diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c index 177dee20faef..2a6729741b06 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c @@ -28,6 +28,28 @@ struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = { { .name = "dispc", .dma_req = 5 }, { .dma_req = -1 } }; + +/* + * 'dispc' class + * display controller + */ + +static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE | + SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +struct omap_hwmod_class omap2_dispc_hwmod_class = { + .name = "dispc", + .sysc = &omap2_dispc_sysc, +}; + /* OMAP2xxx Timer Common */ static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = { .rev_offs = 0x0000, diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 5324e8d93bc0..3c8dd928628e 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1480,6 +1480,28 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = { .masters_cnt = ARRAY_SIZE(omap3xxx_dss_masters), }; +/* + * 'dispc' class + * display controller + */ + +static struct omap_hwmod_class_sysconfig omap3_dispc_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE | + SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | + SYSC_HAS_ENAWAKEUP), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap3_dispc_hwmod_class = { + .name = "dispc", + .sysc = &omap3_dispc_sysc, +}; + /* l4_core -> dss_dispc */ static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = { .master = &omap3xxx_l4_core_hwmod, @@ -1503,7 +1525,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = { static struct omap_hwmod omap3xxx_dss_dispc_hwmod = { .name = "dss_dispc", - .class = &omap2_dispc_hwmod_class, + .class = &omap3_dispc_hwmod_class, .mpu_irqs = omap2_dispc_irqs, .main_clk = "dss1_alwon_fck", .prcm = { @@ -3523,12 +3545,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { &omap3xxx_uart2_hwmod, &omap3xxx_uart3_hwmod, - /* dss class */ - &omap3xxx_dss_dispc_hwmod, - &omap3xxx_dss_dsi1_hwmod, - &omap3xxx_dss_rfbi_hwmod, - &omap3xxx_dss_venc_hwmod, - /* i2c class */ &omap3xxx_i2c1_hwmod, &omap3xxx_i2c2_hwmod, @@ -3635,6 +3651,15 @@ static __initdata struct omap_hwmod *am35xx_hwmods[] = { NULL }; +static __initdata struct omap_hwmod *omap3xxx_dss_hwmods[] = { + /* dss class */ + &omap3xxx_dss_dispc_hwmod, + &omap3xxx_dss_dsi1_hwmod, + &omap3xxx_dss_rfbi_hwmod, + &omap3xxx_dss_venc_hwmod, + NULL +}; + int __init omap3xxx_hwmod_init(void) { int r; @@ -3708,6 +3733,21 @@ int __init omap3xxx_hwmod_init(void) if (h) r = omap_hwmod_register(h); + if (r < 0) + return r; + + /* + * DSS code presumes that dss_core hwmod is handled first, + * _before_ any other DSS related hwmods so register common + * DSS hwmods last to ensure that dss_core is already registered. + * Otherwise some change things may happen, for ex. if dispc + * is handled before dss_core and DSS is enabled in bootloader + * DIPSC will be reset with outputs enabled which sometimes leads + * to unrecoverable L3 error. + * XXX The long-term fix to this is to ensure modules are set up + * in dependency order in the hwmod core code. + */ + r = omap_hwmod_register(omap3xxx_dss_hwmods); return r; } diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index f9f151081760..ef0524c10a84 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1031,6 +1031,7 @@ static struct omap_hwmod_dma_info omap44xx_dmic_sdma_reqs[] = { static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = { { + .name = "mpu", .pa_start = 0x4012e000, .pa_end = 0x4012e07f, .flags = ADDR_TYPE_RT @@ -1049,6 +1050,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic = { static struct omap_hwmod_addr_space omap44xx_dmic_dma_addrs[] = { { + .name = "dma", .pa_start = 0x4902e000, .pa_end = 0x4902e07f, .flags = ADDR_TYPE_RT diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index c1c4d86a79a8..9ce765407ad5 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c @@ -19,6 +19,7 @@ #include "common.h" #include <plat/cpu.h> #include <plat/prcm.h> +#include <plat/irqs.h> #include "vp.h" diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index 9dd93453e563..7e755bb0ffc4 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -897,7 +897,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) ret = sr_late_init(sr_info); if (ret) { pr_warning("%s: Error in SR late init\n", __func__); - return ret; + goto err_iounmap; } } diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 6eeff0e0ae01..5c9acea95761 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -270,7 +270,7 @@ static struct clocksource clocksource_gpt = { static u32 notrace dmtimer_read_sched_clock(void) { if (clksrc.reserved) - return __omap_dm_timer_read_counter(clksrc.io_base, 1); + return __omap_dm_timer_read_counter(&clksrc, 1); return 0; } diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 18fd177073f4..5bc13121eac5 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -415,29 +415,9 @@ static struct resource pxa_rtc_resources[] = { }, }; -static struct resource sa1100_rtc_resources[] = { - [0] = { - .start = 0x40900000, - .end = 0x409000ff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_RTC1Hz, - .end = IRQ_RTC1Hz, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_RTCAlrm, - .end = IRQ_RTCAlrm, - .flags = IORESOURCE_IRQ, - }, -}; - struct platform_device sa1100_device_rtc = { .name = "sa1100-rtc", .id = -1, - .num_resources = ARRAY_SIZE(sa1100_rtc_resources), - .resource = sa1100_rtc_resources, }; struct platform_device pxa_device_rtc = { diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index adf058fa97ee..91e4f6c03766 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -209,8 +209,6 @@ static struct clk_lookup pxa25x_clkregs[] = { INIT_CLKREG(&clk_pxa25x_gpio11, NULL, "GPIO11_CLK"), INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"), INIT_CLKREG(&clk_pxa25x_mem, "pxa2xx-pcmcia", NULL), - INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL), - INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL), }; static struct clk_lookup pxa25x_hwuart_clkreg = diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 180bd8675d4b..aed6cbcf3866 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -230,8 +230,6 @@ static struct clk_lookup pxa27x_clkregs[] = { INIT_CLKREG(&clk_pxa27x_im, NULL, "IMCLK"), INIT_CLKREG(&clk_pxa27x_memc, NULL, "MEMCLK"), INIT_CLKREG(&clk_pxa27x_mem, "pxa2xx-pcmcia", NULL), - INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL), - INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL), }; #ifdef CONFIG_PM diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c index 0388eda7878a..40bb16501d86 100644 --- a/arch/arm/mach-pxa/pxa300.c +++ b/arch/arm/mach-pxa/pxa300.c @@ -89,7 +89,6 @@ static DEFINE_PXA3_CKEN(gcu, PXA300_GCU, 0, 0); static struct clk_lookup common_clkregs[] = { INIT_CLKREG(&clk_common_nand, "pxa3xx-nand", NULL), INIT_CLKREG(&clk_gcu, "pxa3xx-gcu", NULL), - INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL), }; static DEFINE_PXA3_CKEN(pxa310_mmc3, MMC3, 19500000, 0); diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c index d487e1ff4c9a..8d614ecd8e99 100644 --- a/arch/arm/mach-pxa/pxa320.c +++ b/arch/arm/mach-pxa/pxa320.c @@ -83,7 +83,6 @@ static DEFINE_PXA3_CKEN(gcu, PXA320_GCU, 0, 0); static struct clk_lookup pxa320_clkregs[] = { INIT_CLKREG(&clk_pxa320_nand, "pxa3xx-nand", NULL), INIT_CLKREG(&clk_gcu, "pxa3xx-gcu", NULL), - INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL), }; static int __init pxa320_init(void) diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index f107c71c7589..4f402afa6609 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -67,7 +67,6 @@ static struct clk_lookup pxa3xx_clkregs[] = { INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"), /* Power I2C clock is always on */ INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL), - INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL), INIT_CLKREG(&clk_pxa3xx_lcd, "pxa2xx-fb", NULL), INIT_CLKREG(&clk_pxa3xx_camera, NULL, "CAMCLK"), INIT_CLKREG(&clk_pxa3xx_ac97, NULL, "AC97CLK"), diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c index fccc644702e6..d082a583df78 100644 --- a/arch/arm/mach-pxa/pxa95x.c +++ b/arch/arm/mach-pxa/pxa95x.c @@ -217,7 +217,6 @@ static struct clk_lookup pxa95x_clkregs[] = { INIT_CLKREG(&clk_pxa95x_pout, NULL, "CLK_POUT"), /* Power I2C clock is always on */ INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL), - INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL), INIT_CLKREG(&clk_pxa95x_lcd, "pxa2xx-fb", NULL), INIT_CLKREG(&clk_pxa95x_ffuart, "pxa2xx-uart.0", NULL), INIT_CLKREG(&clk_pxa95x_btuart, "pxa2xx-uart.1", NULL), diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c index ac1aed2a8da4..eb55f05bef3a 100644 --- a/arch/arm/mach-realview/hotplug.c +++ b/arch/arm/mach-realview/hotplug.c @@ -13,6 +13,7 @@ #include <linux/smp.h> #include <asm/cacheflush.h> +#include <asm/smp_plat.h> extern volatile int pen_release; diff --git a/arch/arm/mach-realview/include/mach/board-eb.h b/arch/arm/mach-realview/include/mach/board-eb.h index 794a8d91a6a6..124bce6b4d7b 100644 --- a/arch/arm/mach-realview/include/mach/board-eb.h +++ b/arch/arm/mach-realview/include/mach/board-eb.h @@ -47,21 +47,23 @@ #define REALVIEW_EB_USB_BASE 0x4F000000 /* USB */ #ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB -#define REALVIEW_EB11MP_SCU_BASE 0x10100000 /* SCU registers */ -#define REALVIEW_EB11MP_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ -#define REALVIEW_EB11MP_TWD_BASE 0x10100600 -#define REALVIEW_EB11MP_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ +#define REALVIEW_EB11MP_PRIV_MEM_BASE 0x1F000000 #define REALVIEW_EB11MP_L220_BASE 0x10102000 /* L220 registers */ #define REALVIEW_EB11MP_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */ #else -#define REALVIEW_EB11MP_SCU_BASE 0x1F000000 /* SCU registers */ -#define REALVIEW_EB11MP_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */ -#define REALVIEW_EB11MP_TWD_BASE 0x1F000600 -#define REALVIEW_EB11MP_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */ +#define REALVIEW_EB11MP_PRIV_MEM_BASE 0x1F000000 #define REALVIEW_EB11MP_L220_BASE 0x1F002000 /* L220 registers */ #define REALVIEW_EB11MP_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */ #endif +#define REALVIEW_EB11MP_PRIV_MEM_SIZE SZ_8K +#define REALVIEW_EB11MP_PRIV_MEM_OFF(x) (REALVIEW_EB11MP_PRIV_MEM_BASE + (x)) + +#define REALVIEW_EB11MP_SCU_BASE REALVIEW_EB11MP_PRIV_MEM_OFF(0) /* SCU registers */ +#define REALVIEW_EB11MP_GIC_CPU_BASE REALVIEW_EB11MP_PRIV_MEM_OFF(0x0100) /* Generic interrupt controller CPU interface */ +#define REALVIEW_EB11MP_TWD_BASE REALVIEW_EB11MP_PRIV_MEM_OFF(0x0600) +#define REALVIEW_EB11MP_GIC_DIST_BASE REALVIEW_EB11MP_PRIV_MEM_OFF(0x1000) /* Generic interrupt controller distributor */ + /* * Core tile identification (REALVIEW_SYS_PROCID) */ diff --git a/arch/arm/mach-realview/include/mach/board-pb11mp.h b/arch/arm/mach-realview/include/mach/board-pb11mp.h index 7abf918b77e9..aa2d4e02ea2c 100644 --- a/arch/arm/mach-realview/include/mach/board-pb11mp.h +++ b/arch/arm/mach-realview/include/mach/board-pb11mp.h @@ -75,6 +75,8 @@ /* * Testchip peripheral and fpga gic regions */ +#define REALVIEW_TC11MP_PRIV_MEM_BASE 0x1F000000 +#define REALVIEW_TC11MP_PRIV_MEM_SIZE SZ_8K #define REALVIEW_TC11MP_SCU_BASE 0x1F000000 /* IRQ, Test chip */ #define REALVIEW_TC11MP_GIC_CPU_BASE 0x1F000100 /* Test chip interrupt controller CPU interface */ #define REALVIEW_TC11MP_TWD_BASE 0x1F000600 diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index e62962117763..9578145f2df0 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -91,14 +91,9 @@ static struct map_desc realview_eb_io_desc[] __initdata = { static struct map_desc realview_eb11mp_io_desc[] __initdata = { { - .virtual = IO_ADDRESS(REALVIEW_EB11MP_SCU_BASE), - .pfn = __phys_to_pfn(REALVIEW_EB11MP_SCU_BASE), - .length = SZ_4K, - .type = MT_DEVICE, - }, { - .virtual = IO_ADDRESS(REALVIEW_EB11MP_GIC_DIST_BASE), - .pfn = __phys_to_pfn(REALVIEW_EB11MP_GIC_DIST_BASE), - .length = SZ_4K, + .virtual = IO_ADDRESS(REALVIEW_EB11MP_PRIV_MEM_BASE), + .pfn = __phys_to_pfn(REALVIEW_EB11MP_PRIV_MEM_BASE), + .length = REALVIEW_EB11MP_PRIV_MEM_SIZE, .type = MT_DEVICE, }, { .virtual = IO_ADDRESS(REALVIEW_EB11MP_L220_BASE), diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 127a3fd42ab1..2147335f66f5 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -64,15 +64,10 @@ static struct map_desc realview_pb11mp_io_desc[] __initdata = { .pfn = __phys_to_pfn(REALVIEW_PB11MP_GIC_DIST_BASE), .length = SZ_4K, .type = MT_DEVICE, - }, { - .virtual = IO_ADDRESS(REALVIEW_TC11MP_GIC_CPU_BASE), - .pfn = __phys_to_pfn(REALVIEW_TC11MP_GIC_CPU_BASE), - .length = SZ_4K, - .type = MT_DEVICE, - }, { - .virtual = IO_ADDRESS(REALVIEW_TC11MP_GIC_DIST_BASE), - .pfn = __phys_to_pfn(REALVIEW_TC11MP_GIC_DIST_BASE), - .length = SZ_4K, + }, { /* Maps the SCU, GIC CPU interface, TWD, GIC DIST */ + .virtual = IO_ADDRESS(REALVIEW_TC11MP_PRIV_MEM_BASE), + .pfn = __phys_to_pfn(REALVIEW_TC11MP_PRIV_MEM_BASE), + .length = REALVIEW_TC11MP_PRIV_MEM_SIZE, .type = MT_DEVICE, }, { .virtual = IO_ADDRESS(REALVIEW_SCTL_BASE), diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index ebafe8aa8956..0c4b76ab4d8e 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -202,7 +202,6 @@ static struct irda_platform_data assabet_irda_data = { static struct mcp_plat_data assabet_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1x00", }; static void __init assabet_init(void) @@ -253,17 +252,6 @@ static void __init assabet_init(void) sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources, ARRAY_SIZE(assabet_flash_resources)); sa11x0_register_irda(&assabet_irda_data); - - /* - * Setup the PPC unit correctly. - */ - PPDR &= ~PPC_RXD4; - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PSDR |= PPC_RXD4; - PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - - ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); sa11x0_register_mcp(&assabet_mcp_data); } diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index d12d0f48b1dc..11bb6d0b9be3 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c @@ -124,23 +124,12 @@ static void __init cerf_map_io(void) static struct mcp_plat_data cerf_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1x00", }; static void __init cerf_init(void) { platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices)); sa11x0_register_mtd(&cerf_flash_data, &cerf_flash_resource, 1); - - /* - * Setup the PPC unit correctly. - */ - PPDR &= ~PPC_RXD4; - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PSDR |= PPC_RXD4; - PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - sa11x0_register_mcp(&cerf_mcp_data); } diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c index d6df9f6c9f7e..dab3c6347a8f 100644 --- a/arch/arm/mach-sa1100/clock.c +++ b/arch/arm/mach-sa1100/clock.c @@ -11,39 +11,17 @@ #include <linux/clk.h> #include <linux/spinlock.h> #include <linux/mutex.h> -#include <linux/io.h> -#include <linux/clkdev.h> #include <mach/hardware.h> -struct clkops { - void (*enable)(struct clk *); - void (*disable)(struct clk *); - unsigned long (*getrate)(struct clk *); -}; - +/* + * Very simple clock implementation - we only have one clock to deal with. + */ struct clk { - const struct clkops *ops; - unsigned long rate; unsigned int enabled; }; -#define INIT_CLKREG(_clk, _devname, _conname) \ - { \ - .clk = _clk, \ - .dev_id = _devname, \ - .con_id = _conname, \ - } - -#define DEFINE_CLK(_name, _ops, _rate) \ -struct clk clk_##_name = { \ - .ops = _ops, \ - .rate = _rate, \ - } - -static DEFINE_SPINLOCK(clocks_lock); - -static void clk_gpio27_enable(struct clk *clk) +static void clk_gpio27_enable(void) { /* * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: @@ -54,22 +32,38 @@ static void clk_gpio27_enable(struct clk *clk) TUCR = TUCR_3_6864MHz; } -static void clk_gpio27_disable(struct clk *clk) +static void clk_gpio27_disable(void) { TUCR = 0; GPDR &= ~GPIO_32_768kHz; GAFR &= ~GPIO_32_768kHz; } +static struct clk clk_gpio27; + +static DEFINE_SPINLOCK(clocks_lock); + +struct clk *clk_get(struct device *dev, const char *id) +{ + const char *devname = dev_name(dev); + + return strcmp(devname, "sa1111.0") ? ERR_PTR(-ENOENT) : &clk_gpio27; +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); + int clk_enable(struct clk *clk) { unsigned long flags; spin_lock_irqsave(&clocks_lock, flags); if (clk->enabled++ == 0) - clk->ops->enable(clk); + clk_gpio27_enable(); spin_unlock_irqrestore(&clocks_lock, flags); - return 0; } EXPORT_SYMBOL(clk_enable); @@ -82,48 +76,13 @@ void clk_disable(struct clk *clk) spin_lock_irqsave(&clocks_lock, flags); if (--clk->enabled == 0) - clk->ops->disable(clk); + clk_gpio27_disable(); spin_unlock_irqrestore(&clocks_lock, flags); } EXPORT_SYMBOL(clk_disable); unsigned long clk_get_rate(struct clk *clk) { - unsigned long rate; - - rate = clk->rate; - if (clk->ops->getrate) - rate = clk->ops->getrate(clk); - - return rate; + return 3686400; } EXPORT_SYMBOL(clk_get_rate); - -const struct clkops clk_gpio27_ops = { - .enable = clk_gpio27_enable, - .disable = clk_gpio27_disable, -}; - -static void clk_dummy_enable(struct clk *clk) { } -static void clk_dummy_disable(struct clk *clk) { } - -const struct clkops clk_dummy_ops = { - .enable = clk_dummy_enable, - .disable = clk_dummy_disable, -}; - -static DEFINE_CLK(gpio27, &clk_gpio27_ops, 3686400); -static DEFINE_CLK(dummy, &clk_dummy_ops, 0); - -static struct clk_lookup sa11xx_clkregs[] = { - INIT_CLKREG(&clk_gpio27, "sa1111.0", NULL), - INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL), -}; - -static int __init sa11xx_clk_init(void) -{ - clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs)); - return 0; -} - -postcore_initcall(sa11xx_clk_init); diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index c483912d08af..fd5652118ed1 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -27,7 +27,6 @@ #include <linux/timer.h> #include <linux/gpio.h> #include <linux/pda_power.h> -#include <linux/mfd/ucb1x00.h> #include <mach/hardware.h> #include <asm/mach-types.h> @@ -86,15 +85,10 @@ static struct scoop_pcmcia_config collie_pcmcia_config = { .num_devs = 1, }; -static struct ucb1x00_plat_data collie_ucb1x00_data = { - .gpio_base = COLLIE_TC35143_GPIO_BASE, -}; - static struct mcp_plat_data collie_mcp_data = { .mccr0 = MCCR0_ADM | MCCR0_ExtClk, .sclk_rate = 9216000, - .codec = "ucb1x00", - .codec_pdata = &collie_ucb1x00_data, + .gpio_base = COLLIE_TC35143_GPIO_BASE, }; /* @@ -144,8 +138,6 @@ static struct pda_power_pdata collie_power_data = { static struct resource collie_power_resource[] = { { .name = "ac", - .start = gpio_to_irq(COLLIE_GPIO_AC_IN), - .end = gpio_to_irq(COLLIE_GPIO_AC_IN), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, @@ -347,7 +339,8 @@ static void __init collie_init(void) GPSR |= _COLLIE_GPIO_UCB1x00_RESET; - + collie_power_resource[0].start = gpio_to_irq(COLLIE_GPIO_AC_IN); + collie_power_resource[0].end = gpio_to_irq(COLLIE_GPIO_AC_IN); platform_scoop_config = &collie_pcmcia_config; ret = platform_add_devices(devices, ARRAY_SIZE(devices)); @@ -357,16 +350,6 @@ static void __init collie_init(void) sa11x0_register_mtd(&collie_flash_data, collie_flash_resources, ARRAY_SIZE(collie_flash_resources)); - - /* - * Setup the PPC unit correctly. - */ - PPDR &= ~PPC_RXD4; - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PSDR |= PPC_RXD4; - PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - sa11x0_register_mcp(&collie_mcp_data); sharpsl_save_param(); diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c index aaa8acf76b7b..19b2053f5af4 100644 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/arch/arm/mach-sa1100/cpu-sa1100.c @@ -228,7 +228,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy) return 0; } -static struct cpufreq_driver sa1100_driver = { +static struct cpufreq_driver sa1100_driver __refdata = { .flags = CPUFREQ_STICKY, .verify = sa11x0_verify_speed, .target = sa1100_target, diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index e3a28ca2a7b7..bb10ee2cb89f 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -217,15 +217,10 @@ static struct platform_device sa11x0uart3_device = { static struct resource sa11x0mcp_resources[] = { [0] = { .start = __PREG(Ser4MCCR0), - .end = __PREG(Ser4MCCR0) + 0x1C - 1, + .end = __PREG(Ser4MCCR0) + 0xffff, .flags = IORESOURCE_MEM, }, [1] = { - .start = __PREG(Ser4MCCR1), - .end = __PREG(Ser4MCCR1) + 0x4 - 1, - .flags = IORESOURCE_MEM, - }, - [2] = { .start = IRQ_Ser4MCP, .end = IRQ_Ser4MCP, .flags = IORESOURCE_IRQ, @@ -350,29 +345,9 @@ void sa11x0_register_irda(struct irda_platform_data *irda) sa11x0_register_device(&sa11x0ir_device, irda); } -static struct resource sa11x0rtc_resources[] = { - [0] = { - .start = 0x90010000, - .end = 0x900100ff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_RTC1Hz, - .end = IRQ_RTC1Hz, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_RTCAlrm, - .end = IRQ_RTCAlrm, - .flags = IORESOURCE_IRQ, - }, -}; - static struct platform_device sa11x0rtc_device = { .name = "sa1100-rtc", .id = -1, - .resource = sa11x0rtc_resources, - .num_resources = ARRAY_SIZE(sa11x0rtc_resources), }; static struct platform_device *sa11x0_devices[] __initdata = { diff --git a/arch/arm/mach-sa1100/include/mach/mcp.h b/arch/arm/mach-sa1100/include/mach/mcp.h index 586cec898b35..ed1a331508a7 100644 --- a/arch/arm/mach-sa1100/include/mach/mcp.h +++ b/arch/arm/mach-sa1100/include/mach/mcp.h @@ -17,8 +17,6 @@ struct mcp_plat_data { u32 mccr1; unsigned int sclk_rate; int gpio_base; - const char *codec; - void *codec_pdata; }; #endif diff --git a/arch/arm/mach-sa1100/jornada720_ssp.c b/arch/arm/mach-sa1100/jornada720_ssp.c index f50b00bd18a0..b412fc09c80c 100644 --- a/arch/arm/mach-sa1100/jornada720_ssp.c +++ b/arch/arm/mach-sa1100/jornada720_ssp.c @@ -198,3 +198,5 @@ static int __init jornada_ssp_init(void) { return platform_driver_register(&jornadassp_driver); } + +module_init(jornada_ssp_init); diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c index d117ceab6215..af4e2761f3db 100644 --- a/arch/arm/mach-sa1100/lart.c +++ b/arch/arm/mach-sa1100/lart.c @@ -24,20 +24,10 @@ static struct mcp_plat_data lart_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1x00", }; static void __init lart_init(void) { - /* - * Setup the PPC unit correctly. - */ - PPDR &= ~PPC_RXD4; - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PSDR |= PPC_RXD4; - PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - sa11x0_register_mcp(&lart_mcp_data); } diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c index 748d34435b3f..318b2b766a0b 100644 --- a/arch/arm/mach-sa1100/shannon.c +++ b/arch/arm/mach-sa1100/shannon.c @@ -55,22 +55,11 @@ static struct resource shannon_flash_resource = { static struct mcp_plat_data shannon_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1x00", }; static void __init shannon_init(void) { sa11x0_register_mtd(&shannon_flash_data, &shannon_flash_resource, 1); - - /* - * Setup the PPC unit correctly. - */ - PPDR &= ~PPC_RXD4; - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PSDR |= PPC_RXD4; - PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - sa11x0_register_mcp(&shannon_mcp_data); } diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index 458ececefa58..e17c04d6e324 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c @@ -14,7 +14,6 @@ #include <linux/mtd/partitions.h> #include <linux/io.h> #include <linux/gpio.h> -#include <linux/mfd/ucb1x00.h> #include <asm/irq.h> #include <mach/hardware.h> @@ -188,15 +187,10 @@ static struct resource simpad_flash_resources [] = { } }; -static struct ucb1x00_plat_data simpad_ucb1x00_data = { - .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, -}; - static struct mcp_plat_data simpad_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, - .codec = "ucb1300", - .codec_pdata = &simpad_ucb1x00_data, + .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, }; @@ -384,16 +378,6 @@ static int __init simpad_init(void) sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources, ARRAY_SIZE(simpad_flash_resources)); - - /* - * Setup the PPC unit correctly. - */ - PPDR &= ~PPC_RXD4; - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PSDR |= PPC_RXD4; - PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); - sa11x0_register_mcp(&simpad_mcp_data); ret = platform_add_devices(devices, ARRAY_SIZE(devices)); diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 6fcf304d3cdf..a83cf51fc099 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -662,6 +662,7 @@ static struct sh_dmae_pdata usb_dma0_platform_data = { .dmaor_is_32bit = 1, .needs_tend_set = 1, .no_dmars = 1, + .slave_only = 1, }; static struct resource sh7372_usb_dmae0_resources[] = { @@ -723,6 +724,7 @@ static struct sh_dmae_pdata usb_dma1_platform_data = { .dmaor_is_32bit = 1, .needs_tend_set = 1, .no_dmars = 1, + .slave_only = 1, }; static struct resource sh7372_usb_dmae1_resources[] = { diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index cc97ef892d1b..4fe2e9eaf501 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c @@ -25,6 +25,7 @@ #include <linux/delay.h> #include <mach/common.h> #include <mach/r8a7779.h> +#include <asm/smp_plat.h> #include <asm/smp_scu.h> #include <asm/smp_twd.h> #include <asm/hardware/gic.h> diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index be1ade76ccc8..0d159d64a345 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c @@ -23,6 +23,7 @@ #include <linux/spinlock.h> #include <linux/io.h> #include <mach/common.h> +#include <asm/smp_plat.h> #include <asm/smp_scu.h> #include <asm/smp_twd.h> #include <asm/hardware/gic.h> diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index a3e0c8692f0d..52af00446a63 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -7,6 +7,7 @@ config UX500_SOC_COMMON select HAS_MTU select ARM_ERRATA_753970 select ARM_ERRATA_754322 + select ARM_ERRATA_764369 menu "Ux500 SoC" diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 23be34b3bb6e..5dde4d4ebe88 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -261,6 +261,8 @@ void __init mop500_sdi_init(void) void __init snowball_sdi_init(void) { + /* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */ + mop500_sdi0_data.capabilities &= ~MMC_CAP_SD_HIGHSPEED; /* On-board eMMC */ db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID); /* External Micro SD slot */ diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c index 122ddde00ba7..da5569d83d58 100644 --- a/arch/arm/mach-ux500/cache-l2x0.c +++ b/arch/arm/mach-ux500/cache-l2x0.c @@ -12,44 +12,6 @@ static void __iomem *l2x0_base; -static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask) -{ - /* wait for the operation to complete */ - while (readl_relaxed(reg) & mask) - cpu_relax(); -} - -static inline void ux500_cache_sync(void) -{ - writel_relaxed(0, l2x0_base + L2X0_CACHE_SYNC); - ux500_cache_wait(l2x0_base + L2X0_CACHE_SYNC, 1); -} - -/* - * The L2 cache cannot be turned off in the non-secure world. - * Dummy until a secure service is in place. - */ -static void ux500_l2x0_disable(void) -{ -} - -/* - * This is only called when doing a kexec, just after turning off the L2 - * and L1 cache, and it is surrounded by a spinlock in the generic version. - * However, we're not really turning off the L2 cache right now and the - * PL310 does not support exclusive accesses (used to implement the spinlock). - * So, the invalidation needs to be done without the spinlock. - */ -static void ux500_l2x0_inv_all(void) -{ - uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */ - - /* invalidate all ways */ - writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); - ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); - ux500_cache_sync(); -} - static int __init ux500_l2x0_unlock(void) { int i; @@ -85,9 +47,13 @@ static int __init ux500_l2x0_init(void) /* 64KB way size, 8 way associativity, force WA */ l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); - /* Override invalidate function */ - outer_cache.disable = ux500_l2x0_disable; - outer_cache.inv_all = ux500_l2x0_inv_all; + /* + * We can't disable l2 as we are in non secure mode, currently + * this seems be called only during kexec path. So let's + * override outer.disable with nasty assignment until we have + * some SMI service available. + */ + outer_cache.disable = NULL; return 0; } diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c index 572015e57cd9..c76f0f456f04 100644 --- a/arch/arm/mach-ux500/hotplug.c +++ b/arch/arm/mach-ux500/hotplug.c @@ -13,6 +13,7 @@ #include <linux/smp.h> #include <asm/cacheflush.h> +#include <asm/smp_plat.h> extern volatile int pen_release; diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index a19e398dade3..d2058ef8345f 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -19,6 +19,7 @@ #include <asm/cacheflush.h> #include <asm/hardware/gic.h> +#include <asm/smp_plat.h> #include <asm/smp_scu.h> #include <mach/hardware.h> #include <mach/setup.h> diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c index 0a01cbdfe063..9f9e1c203061 100644 --- a/arch/arm/mach-ux500/usb.c +++ b/arch/arm/mach-ux500/usb.c @@ -95,13 +95,7 @@ static struct musb_hdrc_config musb_hdrc_config = { }; static struct musb_hdrc_platform_data musb_platform_data = { -#if defined(CONFIG_USB_MUSB_OTG) .mode = MUSB_OTG, -#elif defined(CONFIG_USB_MUSB_PERIPHERAL) - .mode = MUSB_PERIPHERAL, -#else /* defined(CONFIG_USB_MUSB_HOST) */ - .mode = MUSB_HOST, -#endif .config = &musb_hdrc_config, .board_data = &musb_board_data, }; diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 2b1e836a76ed..b1e87c184e54 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -217,7 +217,7 @@ static void __init ct_ca9x4_init(void) } #ifdef CONFIG_SMP -static void ct_ca9x4_init_cpu_map(void) +static void __init ct_ca9x4_init_cpu_map(void) { int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU)); @@ -233,7 +233,7 @@ static void ct_ca9x4_init_cpu_map(void) set_smp_cross_call(gic_raise_softirq); } -static void ct_ca9x4_smp_enable(unsigned int max_cpus) +static void __init ct_ca9x4_smp_enable(unsigned int max_cpus) { scu_enable(MMIO_P2V(A9_MPCORE_SCU)); } diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c index 813ee08f96e6..3034a4dab4a1 100644 --- a/arch/arm/mach-vexpress/hotplug.c +++ b/arch/arm/mach-vexpress/hotplug.c @@ -13,6 +13,7 @@ #include <linux/smp.h> #include <asm/cacheflush.h> +#include <asm/smp_plat.h> #include <asm/system.h> extern volatile int pen_release; diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 4cefb57d9ed2..1a3ca2488164 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -882,6 +882,7 @@ config CACHE_XSC3L2 config ARM_L1_CACHE_SHIFT_6 bool + default y if CPU_V7 help Setting ARM L1 cache line size to 64 Bytes. diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 6ec1226fc62d..5dc7d127a40f 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -310,7 +310,7 @@ static void arm_memory_present(void) static bool arm_memblock_steal_permitted = true; -phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align) +phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align) { phys_addr_t phys; diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 7e9b5bf910c1..0404ccbb8aa3 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -148,10 +148,6 @@ ENDPROC(cpu_v7_do_resume) * Initialise TLB, Caches, and MMU state ready to switch the MMU * on. Return in r0 the new CP15 C1 control register setting. * - * We automatically detect if we have a Harvard cache, and use the - * Harvard cache control instructions insead of the unified cache - * control instructions. - * * This should be able to cover all ARMv7 cores. * * It is assumed that: @@ -251,9 +247,7 @@ __v7_setup: #endif 3: mov r10, #0 -#ifdef HARVARD_CACHE mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate -#endif dsb #ifdef CONFIG_MMU mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs @@ -330,16 +324,6 @@ __v7_ca5mp_proc_info: .size __v7_ca5mp_proc_info, . - __v7_ca5mp_proc_info /* - * ARM Ltd. Cortex A7 processor. - */ - .type __v7_ca7mp_proc_info, #object -__v7_ca7mp_proc_info: - .long 0x410fc070 - .long 0xff0ffff0 - __v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV - .size __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info - - /* * ARM Ltd. Cortex A9 processor. */ .type __v7_ca9mp_proc_info, #object @@ -351,6 +335,16 @@ __v7_ca9mp_proc_info: #endif /* CONFIG_ARM_LPAE */ /* + * ARM Ltd. Cortex A7 processor. + */ + .type __v7_ca7mp_proc_info, #object +__v7_ca7mp_proc_info: + .long 0x410fc070 + .long 0xff0ffff0 + __v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV + .size __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info + + /* * ARM Ltd. Cortex A15 processor. */ .type __v7_ca15mp_proc_info, #object diff --git a/arch/arm/plat-mxc/include/mach/iomux-v1.h b/arch/arm/plat-mxc/include/mach/iomux-v1.h index 6fa8a707b9a0..f7d18046c04f 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-v1.h +++ b/arch/arm/plat-mxc/include/mach/iomux-v1.h @@ -96,6 +96,6 @@ extern int mxc_gpio_mode(int gpio_mode); extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count, const char *label); -extern int __init imx_iomuxv1_init(void __iomem *base, int numports); +extern int imx_iomuxv1_init(void __iomem *base, int numports); #endif /* __MACH_IOMUX_V1_H__ */ diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c index 92f18d372b69..49c7db48c7f1 100644 --- a/arch/arm/plat-versatile/platsmp.c +++ b/arch/arm/plat-versatile/platsmp.c @@ -16,6 +16,7 @@ #include <linux/smp.h> #include <asm/cacheflush.h> +#include <asm/smp_plat.h> #include <asm/hardware/gic.h> /* diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 197e96f70405..3dea7231f637 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -8,6 +8,7 @@ config AVR32 select HAVE_KPROBES select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE + select GENERIC_ATOMIC64 select HARDIRQS_SW_RESEND select GENERIC_IRQ_SHOW select ARCH_HAVE_NMI_SAFE_CMPXCHG diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c index 4203d101363c..c4ac15c4f065 100644 --- a/arch/m68k/atari/config.c +++ b/arch/m68k/atari/config.c @@ -414,9 +414,9 @@ void __init config_atari(void) * FDC val = 4 -> Supervisor only */ asm volatile ("\n" " .chip 68030\n" - " pmove %0@,%/tt1\n" + " pmove %0,%/tt1\n" " .chip 68k" - : : "a" (&tt1_val)); + : : "m" (tt1_val)); } else { asm volatile ("\n" " .chip 68040\n" @@ -569,10 +569,10 @@ static void atari_reset(void) : "d0"); } else asm volatile ("\n" - " pmove %0@,%%tc\n" + " pmove %0,%%tc\n" " jmp %1@" : /* no outputs */ - : "a" (&tc_val), "a" (reset_addr)); + : "m" (tc_val), "a" (reset_addr)); } diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 0e89fa05de0e..c1155f0e22cc 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -50,19 +50,6 @@ #define IRQ_USER 8 -/* - * various flags for request_irq() - the Amiga now uses the standard - * mechanism like all other architectures - IRQF_DISABLED and - * IRQF_SHARED are your friends. - */ -#ifndef MACH_AMIGA_ONLY -#define IRQ_FLG_LOCK (0x0001) /* handler is not replaceable */ -#define IRQ_FLG_REPLACE (0x0002) /* replace existing handler */ -#define IRQ_FLG_FAST (0x0004) -#define IRQ_FLG_SLOW (0x0008) -#define IRQ_FLG_STD (0x8000) /* internally used */ -#endif - struct irq_data; struct irq_chip; struct irq_desc; diff --git a/arch/m68k/kernel/process_mm.c b/arch/m68k/kernel/process_mm.c index 125f34e00bf0..099283ee1a8f 100644 --- a/arch/m68k/kernel/process_mm.c +++ b/arch/m68k/kernel/process_mm.c @@ -172,7 +172,7 @@ void flush_thread(void) current->thread.fs = __USER_DS; if (!FPU_IS_EMU) - asm volatile ("frestore %0@" : : "a" (&zero) : "memory"); + asm volatile("frestore %0": :"m" (zero)); } /* diff --git a/arch/m68k/kernel/process_no.c b/arch/m68k/kernel/process_no.c index 69c1803fcf1b..5e1078cabe0e 100644 --- a/arch/m68k/kernel/process_no.c +++ b/arch/m68k/kernel/process_no.c @@ -163,8 +163,8 @@ void flush_thread(void) #ifdef CONFIG_FPU if (!FPU_IS_EMU) asm volatile (".chip 68k/68881\n\t" - "frestore %0@\n\t" - ".chip 68k" : : "a" (&zero)); + "frestore %0\n\t" + ".chip 68k" : : "m" (zero)); #endif } diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index a76452ca964e..daaa9187654c 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -552,13 +552,13 @@ static inline void bus_error030 (struct frame *fp) #ifdef DEBUG asm volatile ("ptestr %3,%2@,#7,%0\n\t" - "pmove %%psr,%1@" - : "=a&" (desc) - : "a" (&temp), "a" (addr), "d" (ssw)); + "pmove %%psr,%1" + : "=a&" (desc), "=m" (temp) + : "a" (addr), "d" (ssw)); #else asm volatile ("ptestr %2,%1@,#7\n\t" - "pmove %%psr,%0@" - : : "a" (&temp), "a" (addr), "d" (ssw)); + "pmove %%psr,%0" + : "=m" (temp) : "a" (addr), "d" (ssw)); #endif mmusr = temp; @@ -605,20 +605,18 @@ static inline void bus_error030 (struct frame *fp) !(ssw & RW) ? "write" : "read", addr, fp->ptregs.pc, ssw); asm volatile ("ptestr #1,%1@,#0\n\t" - "pmove %%psr,%0@" - : /* no outputs */ - : "a" (&temp), "a" (addr)); + "pmove %%psr,%0" + : "=m" (temp) + : "a" (addr)); mmusr = temp; printk ("level 0 mmusr is %#x\n", mmusr); #if 0 - asm volatile ("pmove %%tt0,%0@" - : /* no outputs */ - : "a" (&tlong)); + asm volatile ("pmove %%tt0,%0" + : "=m" (tlong)); printk("tt0 is %#lx, ", tlong); - asm volatile ("pmove %%tt1,%0@" - : /* no outputs */ - : "a" (&tlong)); + asm volatile ("pmove %%tt1,%0" + : "=m" (tlong)); printk("tt1 is %#lx\n", tlong); #endif #ifdef DEBUG @@ -668,13 +666,13 @@ static inline void bus_error030 (struct frame *fp) #ifdef DEBUG asm volatile ("ptestr #1,%2@,#7,%0\n\t" - "pmove %%psr,%1@" - : "=a&" (desc) - : "a" (&temp), "a" (addr)); + "pmove %%psr,%1" + : "=a&" (desc), "=m" (temp) + : "a" (addr)); #else asm volatile ("ptestr #1,%1@,#7\n\t" - "pmove %%psr,%0@" - : : "a" (&temp), "a" (addr)); + "pmove %%psr,%0" + : "=m" (temp) : "a" (addr)); #endif mmusr = temp; diff --git a/arch/m68k/mm/cache.c b/arch/m68k/mm/cache.c index 95d0bf66e2e2..3d84c1f2ffb2 100644 --- a/arch/m68k/mm/cache.c +++ b/arch/m68k/mm/cache.c @@ -52,9 +52,9 @@ static unsigned long virt_to_phys_slow(unsigned long vaddr) unsigned long *descaddr; asm volatile ("ptestr %3,%2@,#7,%0\n\t" - "pmove %%psr,%1@" - : "=a&" (descaddr) - : "a" (&mmusr), "a" (vaddr), "d" (get_fs().seg)); + "pmove %%psr,%1" + : "=a&" (descaddr), "=m" (mmusr) + : "a" (vaddr), "d" (get_fs().seg)); if (mmusr & (MMU_I|MMU_B|MMU_L)) return 0; descaddr = phys_to_virt((unsigned long)descaddr); diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 74f23a460ba2..c8d6efb99dbf 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -19,6 +19,7 @@ config MICROBLAZE select GENERIC_IRQ_SHOW select GENERIC_PCI_IOMAP select GENERIC_CPU_DEVICES + select GENERIC_ATOMIC64 config SWAP def_bool n diff --git a/arch/microblaze/include/asm/atomic.h b/arch/microblaze/include/asm/atomic.h index 6d2e1d418be7..615f53992c65 100644 --- a/arch/microblaze/include/asm/atomic.h +++ b/arch/microblaze/include/asm/atomic.h @@ -2,6 +2,7 @@ #define _ASM_MICROBLAZE_ATOMIC_H #include <asm-generic/atomic.h> +#include <asm-generic/atomic64.h> /* * Atomically test *v and decrement if it is greater than 0. diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index d4fc1a971779..604cd9dd1333 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -26,7 +26,6 @@ #include <linux/cache.h> #include <linux/of_platform.h> #include <linux/dma-mapping.h> -#include <linux/cpu.h> #include <asm/cacheflush.h> #include <asm/entry.h> #include <asm/cpuinfo.h> @@ -227,23 +226,5 @@ static int __init setup_bus_notifier(void) return 0; } -arch_initcall(setup_bus_notifier); - -static DEFINE_PER_CPU(struct cpu, cpu_devices); - -static int __init topology_init(void) -{ - int i, ret; - - for_each_present_cpu(i) { - struct cpu *c = &per_cpu(cpu_devices, i); - ret = register_cpu(c, i); - if (ret) - printk(KERN_WARNING "topology_init: register_cpu %d " - "failed (%d)\n", i, ret); - } - - return 0; -} -subsys_initcall(topology_init); +arch_initcall(setup_bus_notifier); diff --git a/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi index 89af62637707..b37da56018b6 100644 --- a/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi @@ -236,6 +236,10 @@ }; /include/ "pq3-esdhc-0.dtsi" + sdhc@2e000 { + compatible = "fsl,mpc8536-esdhc", "fsl,esdhc"; + }; + /include/ "pq3-sec3.0-0.dtsi" /include/ "pq3-mpic.dtsi" /include/ "pq3-mpic-timer-B.dtsi" diff --git a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi index bd9e163c764b..a97d1263372c 100644 --- a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi @@ -158,7 +158,8 @@ /include/ "pq3-usb2-dr-0.dtsi" /include/ "pq3-esdhc-0.dtsi" sdhc@2e000 { - fsl,sdhci-auto-cmd12; + compatible = "fsl,p1010-esdhc", "fsl,esdhc"; + sdhci,auto-cmd12; }; /include/ "pq3-sec4.4-0.dtsi" diff --git a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi index fc924c5ffebe..5de5fc351314 100644 --- a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi @@ -145,6 +145,10 @@ /include/ "pq3-usb2-dr-1.dtsi" /include/ "pq3-esdhc-0.dtsi" + sdhc@2e000 { + compatible = "fsl,p1020-esdhc", "fsl,esdhc"; + sdhci,auto-cmd12; + }; /include/ "pq3-sec3.3-0.dtsi" /include/ "pq3-mpic.dtsi" diff --git a/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi index 16239b199d0a..ff9ed1d87929 100644 --- a/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi @@ -203,7 +203,8 @@ /include/ "pq3-esdhc-0.dtsi" sdhc@2e000 { - fsl,sdhci-auto-cmd12; + compatible = "fsl,p1022-esdhc", "fsl,esdhc"; + sdhci,auto-cmd12; }; /include/ "pq3-sec3.3-0.dtsi" diff --git a/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi index c041050561a7..332e9e75e6c2 100644 --- a/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi @@ -182,6 +182,10 @@ /include/ "pq3-etsec1-1.dtsi" /include/ "pq3-etsec1-2.dtsi" /include/ "pq3-esdhc-0.dtsi" + sdhc@2e000 { + compatible = "fsl,p2020-esdhc", "fsl,esdhc"; + }; + /include/ "pq3-sec3.1-0.dtsi" /include/ "pq3-mpic.dtsi" /include/ "pq3-mpic-timer-B.dtsi" diff --git a/arch/powerpc/boot/dts/p1020rdb.dtsi b/arch/powerpc/boot/dts/p1020rdb.dtsi index b5bd86f4baf2..1fb7e0e0940f 100644 --- a/arch/powerpc/boot/dts/p1020rdb.dtsi +++ b/arch/powerpc/boot/dts/p1020rdb.dtsi @@ -1,7 +1,7 @@ /* * P1020 RDB Device Tree Source stub (no addresses or top-level ranges) * - * Copyright 2011 Freescale Semiconductor Inc. + * Copyright 2011-2012 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -190,17 +190,16 @@ usb@22000 { phy_type = "ulpi"; + dr_mode = "host"; }; - /* USB2 is shared with localbus, so it must be disabled - by default. We can't put 'status = "disabled";' here - since U-Boot doesn't clear the status property when - it enables USB2. OTOH, U-Boot does create a new node - when there isn't any. So, just comment it out. + /* USB2 is shared with localbus. It is used + only in case of SPI and SD boot after + appropriate device-tree fixup done by uboot */ usb@23000 { phy_type = "ulpi"; + dr_mode = "host"; }; - */ mdio@24000 { phy0: ethernet-phy@0 { diff --git a/arch/powerpc/boot/dts/p1021mds.dts b/arch/powerpc/boot/dts/p1021mds.dts index d9540791e434..97116f198a37 100644 --- a/arch/powerpc/boot/dts/p1021mds.dts +++ b/arch/powerpc/boot/dts/p1021mds.dts @@ -1,7 +1,7 @@ /* * P1021 MDS Device Tree Source * - * Copyright 2010 Freescale Semiconductor Inc. + * Copyright 2010,2012 Freescale Semiconductor Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -151,6 +151,7 @@ usb@22000 { phy_type = "ulpi"; + dr_mode = "host"; }; mdio@24000 { diff --git a/arch/powerpc/boot/dts/p2020ds.dtsi b/arch/powerpc/boot/dts/p2020ds.dtsi index c1cf6cef4dd6..d3b939c573b0 100644 --- a/arch/powerpc/boot/dts/p2020ds.dtsi +++ b/arch/powerpc/boot/dts/p2020ds.dtsi @@ -1,7 +1,7 @@ /* * P2020DS Device Tree Source stub (no addresses or top-level ranges) * - * Copyright 2011 Freescale Semiconductor Inc. + * Copyright 2011-2012 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -134,6 +134,7 @@ &board_soc { usb@22000 { phy_type = "ulpi"; + dr_mode = "host"; }; mdio@24520 { diff --git a/arch/powerpc/boot/dts/p2020rdb.dts b/arch/powerpc/boot/dts/p2020rdb.dts index 26759a591712..eb8a6aa2bda5 100644 --- a/arch/powerpc/boot/dts/p2020rdb.dts +++ b/arch/powerpc/boot/dts/p2020rdb.dts @@ -1,7 +1,7 @@ /* * P2020 RDB Device Tree Source * - * Copyright 2009-2011 Freescale Semiconductor Inc. + * Copyright 2009-2012 Freescale Semiconductor Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -197,6 +197,7 @@ usb@22000 { phy_type = "ulpi"; + dr_mode = "host"; }; mdio@24520 { diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 28be3452e67a..abef75176c07 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -46,7 +46,6 @@ /* This keeps a track of which one is the crashing cpu. */ int crashing_cpu = -1; -static atomic_t cpus_in_crash; static int time_to_dump; #define CRASH_HANDLER_MAX 3 @@ -66,6 +65,7 @@ static int handle_fault(struct pt_regs *regs) #ifdef CONFIG_SMP +static atomic_t cpus_in_crash; void crash_ipi_callback(struct pt_regs *regs) { static cpumask_t cpus_state_saved = CPU_MASK_NONE; diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index 3fea3689527e..bedd12e1cfbc 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -442,8 +442,10 @@ static void __init fixup_port_irq(int index, port->irq = virq; +#ifdef CONFIG_SERIAL_8250_FSL if (of_device_is_compatible(np, "fsl,ns16550")) port->handle_irq = fsl8250_handle_irq; +#endif } static void __init fixup_port_pio(int index, diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index bb3d84f4046f..b0984ada3f83 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -25,6 +25,7 @@ #include <sysdev/fsl_soc.h> #include <sysdev/fsl_pci.h> +#include <asm/udbg.h> #include <asm/fsl_guts.h> #include "smp.h" diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index f31162cfdaa9..5e155dfc4320 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -204,11 +204,10 @@ static void __devinit pnv_ioda_offset_bus(struct pci_bus *bus, pr_devel(" -> OBR %s [%x] +%016llx\n", bus->self ? pci_name(bus->self) : "root", flags, offset); - for (i = 0; i < 2; i++) { - r = bus->resource[i]; + pci_bus_for_each_resource(bus, r, i) { if (r && (r->flags & flags)) { - bus->resource[i]->start += offset; - bus->resource[i]->end += offset; + r->start += offset; + r->end += offset; } } list_for_each_entry(dev, &bus->devices, bus_list) @@ -288,12 +287,17 @@ static void __devinit pnv_ioda_calc_bus(struct pci_bus *bus, unsigned int flags, * assignment algorithm is going to be uber-trivial for now, we * can try to be smarter later at filling out holes. */ - start = bus->self ? 0 : bus->resource[bres]->start; - - /* Don't hand out IO 0 */ - if ((flags & IORESOURCE_IO) && !bus->self) - start += 0x1000; - + if (bus->self) { + /* No offset for downstream bridges */ + start = 0; + } else { + /* Offset from the root */ + if (flags & IORESOURCE_IO) + /* Don't hand out IO 0 */ + start = hose->io_resource.start + 0x1000; + else + start = hose->mem_resources[0].start; + } while(!list_empty(&head)) { w = list_first_entry(&head, struct resource_wrap, link); list_del(&w->link); @@ -321,13 +325,20 @@ static void __devinit pnv_ioda_calc_bus(struct pci_bus *bus, unsigned int flags, empty: /* Only setup P2P's, not the PHB itself */ if (bus->self) { - WARN_ON(bus->resource[bres] == NULL); - bus->resource[bres]->start = 0; - bus->resource[bres]->flags = (*size) ? flags : 0; - bus->resource[bres]->end = (*size) ? (*size - 1) : 0; + struct resource *res = bus->resource[bres]; + + if (WARN_ON(res == NULL)) + return; - /* Clear prefetch bus resources for now */ - bus->resource[2]->flags = 0; + /* + * FIXME: We should probably export and call + * pci_bridge_check_ranges() to properly re-initialize + * the PCI portion of the flags here, and to detect + * what the bridge actually supports. + */ + res->start = 0; + res->flags = (*size) ? flags : 0; + res->end = (*size) ? (*size - 1) : 0; } pr_devel("<- CBR %s [%x] *size=%016llx *align=%016llx\n", diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index ae7b6d41fed3..31f22c1f657d 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -122,7 +122,7 @@ config DTL Say N if you are unsure. config PSERIES_IDLE - tristate "Cpuidle driver for pSeries platforms" + bool "Cpuidle driver for pSeries platforms" depends on CPU_IDLE depends on PPC_PSERIES default y diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 3b61e8cf3421..30eb17ecad49 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -205,12 +205,12 @@ static void __init setup_pci_atmu(struct pci_controller *hose, if (paddr_hi == paddr_lo) { pr_err("%s: No outbound window space\n", name); - return ; + goto out; } if (paddr_lo == 0) { pr_err("%s: No space for inbound window\n", name); - return ; + goto out; } /* setup PCSRBAR/PEXCSRBAR */ @@ -357,6 +357,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose, (u64)hose->dma_window_size); } +out: iounmap(pci); } diff --git a/arch/s390/Makefile b/arch/s390/Makefile index e9f353341693..0ad2f1e1ce9e 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -88,7 +88,6 @@ KBUILD_CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare KBUILD_AFLAGS += $(aflags-y) OBJCOPYFLAGS := -O binary -LDFLAGS_vmlinux := -e start head-y := arch/s390/kernel/head.o head-y += arch/s390/kernel/$(if $(CONFIG_64BIT),head64.o,head31.o) diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index e4c79ebb40e6..21109c63eb12 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -9,12 +9,12 @@ #ifndef CONFIG_64BIT OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") OUTPUT_ARCH(s390) -ENTRY(_start) +ENTRY(startup) jiffies = jiffies_64 + 4; #else OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") OUTPUT_ARCH(s390:64-bit) -ENTRY(_start) +ENTRY(startup) jiffies = jiffies_64; #endif diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 96657992a72e..ca5580e4d813 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -33,6 +33,7 @@ config SPARC config SPARC32 def_bool !64BIT select GENERIC_ATOMIC64 + select CLZ_TAB config SPARC64 def_bool 64BIT diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 422c16dad1f6..e61165161dd3 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -399,6 +399,9 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) timers_global = (void __iomem *) (unsigned long) addr[num_cpu_timers]; + /* Every per-cpu timer works in timer mode */ + sbus_writel(0x00000000, &timers_global->timer_config); + sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit); master_l10_counter = &timers_global->l10_count; diff --git a/arch/sparc/lib/divdi3.S b/arch/sparc/lib/divdi3.S index 681b3683da9e..d74bc0925f2d 100644 --- a/arch/sparc/lib/divdi3.S +++ b/arch/sparc/lib/divdi3.S @@ -17,23 +17,9 @@ along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - .data - .align 8 - .globl __clz_tab -__clz_tab: - .byte 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 - .byte 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 - .byte 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 - .byte 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 - .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - .size __clz_tab,256 - .global .udiv - .text .align 4 + .global .udiv .globl __divdi3 __divdi3: save %sp,-104,%sp diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 864cc6e6ac8e..5bed94e189fa 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -360,7 +360,6 @@ config X86_NUMACHIP depends on NUMA depends on SMP depends on X86_X2APIC - depends on !EDAC_AMD64 ---help--- Adds support for Numascale NumaChip large-SMP systems. Needed to enable more than ~168 cores. diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 3a19d04cebeb..7116dcba0c9e 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -321,6 +321,8 @@ static void parse_elf(void *output) default: /* Ignore other PT_* */ break; } } + + free(phdrs); } asmlinkage void decompress_kernel(void *rmode, memptr heap, diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h index 0c9fa2745f13..b3b733262909 100644 --- a/arch/x86/include/asm/cmpxchg.h +++ b/arch/x86/include/asm/cmpxchg.h @@ -145,13 +145,13 @@ extern void __add_wrong_size(void) #ifdef __HAVE_ARCH_CMPXCHG #define cmpxchg(ptr, old, new) \ - __cmpxchg((ptr), (old), (new), sizeof(*ptr)) + __cmpxchg(ptr, old, new, sizeof(*(ptr))) #define sync_cmpxchg(ptr, old, new) \ - __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr)) + __sync_cmpxchg(ptr, old, new, sizeof(*(ptr))) #define cmpxchg_local(ptr, old, new) \ - __cmpxchg_local((ptr), (old), (new), sizeof(*ptr)) + __cmpxchg_local(ptr, old, new, sizeof(*(ptr))) #endif /* diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 17c5d4bdee5e..8d67d428b0f9 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -159,6 +159,7 @@ #define X86_FEATURE_WDT (6*32+13) /* Watchdog timer */ #define X86_FEATURE_LWP (6*32+15) /* Light Weight Profiling */ #define X86_FEATURE_FMA4 (6*32+16) /* 4 operands MAC instructions */ +#define X86_FEATURE_TCE (6*32+17) /* translation cache extension */ #define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */ #define X86_FEATURE_TBM (6*32+21) /* trailing bit manipulations */ #define X86_FEATURE_TOPOEXT (6*32+22) /* topology extensions CPUID leafs */ diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index ab4092e3214e..7b9cfc4878af 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -190,6 +190,9 @@ struct x86_emulate_ops { int (*intercept)(struct x86_emulate_ctxt *ctxt, struct x86_instruction_info *info, enum x86_intercept_stage stage); + + bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt, + u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); }; typedef u32 __attribute__((vector_size(16))) sse128_t; @@ -298,6 +301,19 @@ struct x86_emulate_ctxt { #define X86EMUL_MODE_PROT (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \ X86EMUL_MODE_PROT64) +/* CPUID vendors */ +#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541 +#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163 +#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65 + +#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41 +#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574 +#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273 + +#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547 +#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e +#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69 + enum x86_intercept_stage { X86_ICTP_NONE = 0, /* Allow zero-init to not match anything */ X86_ICPT_PRE_EXCEPT, diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h index 54a13aaebc40..21f7385badb8 100644 --- a/arch/x86/include/asm/uv/uv_hub.h +++ b/arch/x86/include/asm/uv/uv_hub.h @@ -318,13 +318,13 @@ uv_gpa_in_mmr_space(unsigned long gpa) /* UV global physical address --> socket phys RAM */ static inline unsigned long uv_gpa_to_soc_phys_ram(unsigned long gpa) { - unsigned long paddr = gpa & uv_hub_info->gpa_mask; + unsigned long paddr; unsigned long remap_base = uv_hub_info->lowmem_remap_base; unsigned long remap_top = uv_hub_info->lowmem_remap_top; gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) | ((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val); - gpa = gpa & uv_hub_info->gpa_mask; + paddr = gpa & uv_hub_info->gpa_mask; if (paddr >= remap_base && paddr < remap_base + remap_top) paddr -= remap_base; return paddr; diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 1aae78f775fc..4025fe4f928f 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -252,7 +252,8 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err) unsigned short ss; unsigned long sp; #endif - printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter); + printk(KERN_DEFAULT + "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter); #ifdef CONFIG_PREEMPT printk("PREEMPT "); #endif diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 6d728d9284bd..17107bd6e1f0 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -129,7 +129,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, if (!stack) { if (regs) stack = (unsigned long *)regs->sp; - else if (task && task != current) + else if (task != current) stack = (unsigned long *)task->thread.sp; else stack = &dummy; @@ -269,11 +269,11 @@ void show_registers(struct pt_regs *regs) unsigned char c; u8 *ip; - printk(KERN_EMERG "Stack:\n"); + printk(KERN_DEFAULT "Stack:\n"); show_stack_log_lvl(NULL, regs, (unsigned long *)sp, - 0, KERN_EMERG); + 0, KERN_DEFAULT); - printk(KERN_EMERG "Code: "); + printk(KERN_DEFAULT "Code: "); ip = (u8 *)regs->ip - code_prologue; if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index fe86493f3ed1..ac0417be9131 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -311,13 +311,33 @@ out: return state; } +/* + * AMD microcode firmware naming convention, up to family 15h they are in + * the legacy file: + * + * amd-ucode/microcode_amd.bin + * + * This legacy file is always smaller than 2K in size. + * + * Starting at family 15h they are in family specific firmware files: + * + * amd-ucode/microcode_amd_fam15h.bin + * amd-ucode/microcode_amd_fam16h.bin + * ... + * + * These might be larger than 2K. + */ static enum ucode_state request_microcode_amd(int cpu, struct device *device) { - const char *fw_name = "amd-ucode/microcode_amd.bin"; + char fw_name[36] = "amd-ucode/microcode_amd.bin"; const struct firmware *fw; enum ucode_state ret = UCODE_NFOUND; + struct cpuinfo_x86 *c = &cpu_data(cpu); + + if (c->x86 >= 0x15) + snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); - if (request_firmware(&fw, fw_name, device)) { + if (request_firmware(&fw, (const char *)fw_name, device)) { pr_err("failed to load file %s\n", fw_name); goto out; } diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 37a458b521a6..d840e69a853c 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -39,6 +39,14 @@ static int reboot_mode; enum reboot_type reboot_type = BOOT_ACPI; int reboot_force; +/* This variable is used privately to keep track of whether or not + * reboot_type is still set to its default value (i.e., reboot= hasn't + * been set on the command line). This is needed so that we can + * suppress DMI scanning for reboot quirks. Without it, it's + * impossible to override a faulty reboot quirk without recompiling. + */ +static int reboot_default = 1; + #if defined(CONFIG_X86_32) && defined(CONFIG_SMP) static int reboot_cpu = -1; #endif @@ -67,6 +75,12 @@ bool port_cf9_safe = false; static int __init reboot_setup(char *str) { for (;;) { + /* Having anything passed on the command line via + * reboot= will cause us to disable DMI checking + * below. + */ + reboot_default = 0; + switch (*str) { case 'w': reboot_mode = 0x1234; @@ -295,14 +309,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "P4S800"), }, }, - { /* Handle problems with rebooting on VersaLogic Menlow boards */ - .callback = set_bios_reboot, - .ident = "VersaLogic Menlow based board", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "VersaLogic Corporation"), - DMI_MATCH(DMI_BOARD_NAME, "VersaLogic Menlow board"), - }, - }, { /* Handle reboot issue on Acer Aspire one */ .callback = set_kbd_reboot, .ident = "Acer Aspire One A110", @@ -316,7 +322,12 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { static int __init reboot_init(void) { - dmi_check_system(reboot_dmi_table); + /* Only do the DMI check if reboot_type hasn't been overridden + * on the command line + */ + if (reboot_default) { + dmi_check_system(reboot_dmi_table); + } return 0; } core_initcall(reboot_init); @@ -465,7 +476,12 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { static int __init pci_reboot_init(void) { - dmi_check_system(pci_reboot_dmi_table); + /* Only do the DMI check if reboot_type hasn't been overridden + * on the command line + */ + if (reboot_default) { + dmi_check_system(pci_reboot_dmi_table); + } return 0; } core_initcall(pci_reboot_init); diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 05a562b85025..0982507b962a 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -1891,6 +1891,51 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, ss->p = 1; } +static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt) +{ + struct x86_emulate_ops *ops = ctxt->ops; + u32 eax, ebx, ecx, edx; + + /* + * syscall should always be enabled in longmode - so only become + * vendor specific (cpuid) if other modes are active... + */ + if (ctxt->mode == X86EMUL_MODE_PROT64) + return true; + + eax = 0x00000000; + ecx = 0x00000000; + if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) { + /* + * Intel ("GenuineIntel") + * remark: Intel CPUs only support "syscall" in 64bit + * longmode. Also an 64bit guest with a + * 32bit compat-app running will #UD !! While this + * behaviour can be fixed (by emulating) into AMD + * response - CPUs of AMD can't behave like Intel. + */ + if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx && + ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx && + edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx) + return false; + + /* AMD ("AuthenticAMD") */ + if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx && + ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx && + edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx) + return true; + + /* AMD ("AMDisbetter!") */ + if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx && + ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx && + edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx) + return true; + } + + /* default: (not Intel, not AMD), apply Intel's stricter rules... */ + return false; +} + static int em_syscall(struct x86_emulate_ctxt *ctxt) { struct x86_emulate_ops *ops = ctxt->ops; @@ -1904,9 +1949,15 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt) ctxt->mode == X86EMUL_MODE_VM86) return emulate_ud(ctxt); + if (!(em_syscall_is_enabled(ctxt))) + return emulate_ud(ctxt); + ops->get_msr(ctxt, MSR_EFER, &efer); setup_syscalls_segments(ctxt, &cs, &ss); + if (!(efer & EFER_SCE)) + return emulate_ud(ctxt); + ops->get_msr(ctxt, MSR_STAR, &msr_data); msr_data >>= 32; cs_sel = (u16)(msr_data & 0xfffc); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 14d6cadc4ba6..9cbfc0698118 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1495,6 +1495,8 @@ static void record_steal_time(struct kvm_vcpu *vcpu) int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) { + bool pr = false; + switch (msr) { case MSR_EFER: return set_efer(vcpu, data); @@ -1635,6 +1637,18 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) pr_unimpl(vcpu, "unimplemented perfctr wrmsr: " "0x%x data 0x%llx\n", msr, data); break; + case MSR_P6_PERFCTR0: + case MSR_P6_PERFCTR1: + pr = true; + case MSR_P6_EVNTSEL0: + case MSR_P6_EVNTSEL1: + if (kvm_pmu_msr(vcpu, msr)) + return kvm_pmu_set_msr(vcpu, msr, data); + + if (pr || data != 0) + pr_unimpl(vcpu, "disabled perfctr wrmsr: " + "0x%x data 0x%llx\n", msr, data); + break; case MSR_K7_CLK_CTL: /* * Ignore all writes to this no longer documented MSR. @@ -1835,6 +1849,14 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) case MSR_FAM10H_MMIO_CONF_BASE: data = 0; break; + case MSR_P6_PERFCTR0: + case MSR_P6_PERFCTR1: + case MSR_P6_EVNTSEL0: + case MSR_P6_EVNTSEL1: + if (kvm_pmu_msr(vcpu, msr)) + return kvm_pmu_get_msr(vcpu, msr, pdata); + data = 0; + break; case MSR_IA32_UCODE_REV: data = 0x100000000ULL; break; @@ -4180,6 +4202,28 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt, return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage); } +static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt, + u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) +{ + struct kvm_cpuid_entry2 *cpuid = NULL; + + if (eax && ecx) + cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt), + *eax, *ecx); + + if (cpuid) { + *eax = cpuid->eax; + *ecx = cpuid->ecx; + if (ebx) + *ebx = cpuid->ebx; + if (edx) + *edx = cpuid->edx; + return true; + } + + return false; +} + static struct x86_emulate_ops emulate_ops = { .read_std = kvm_read_guest_virt_system, .write_std = kvm_write_guest_virt_system, @@ -4211,6 +4255,7 @@ static struct x86_emulate_ops emulate_ops = { .get_fpu = emulator_get_fpu, .put_fpu = emulator_put_fpu, .intercept = emulator_intercept, + .get_cpuid = emulator_get_cpuid, }; static void cache_all_regs(struct kvm_vcpu *vcpu) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 9d74824a708d..f0b4caf85c1a 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -673,7 +673,7 @@ no_context(struct pt_regs *regs, unsigned long error_code, stackend = end_of_stack(tsk); if (tsk != &init_task && *stackend != STACK_END_MAGIC) - printk(KERN_ALERT "Thread overran stack, or stack corrupted\n"); + printk(KERN_EMERG "Thread overran stack, or stack corrupted\n"); tsk->thread.cr2 = address; tsk->thread.trap_no = 14; @@ -684,7 +684,7 @@ no_context(struct pt_regs *regs, unsigned long error_code, sig = 0; /* Executive summary in case the body of the oops scrolled away */ - printk(KERN_EMERG "CR2: %016lx\n", address); + printk(KERN_DEFAULT "CR2: %016lx\n", address); oops_end(flags, regs, sig); } diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 7b65f752c5f8..7c1b765ecc59 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -151,17 +151,18 @@ void bpf_jit_compile(struct sk_filter *fp) cleanup_addr = proglen; /* epilogue address */ for (pass = 0; pass < 10; pass++) { + u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen; /* no prologue/epilogue for trivial filters (RET something) */ proglen = 0; prog = temp; - if (seen) { + if (seen_or_pass0) { EMIT4(0x55, 0x48, 0x89, 0xe5); /* push %rbp; mov %rsp,%rbp */ EMIT4(0x48, 0x83, 0xec, 96); /* subq $96,%rsp */ /* note : must save %rbx in case bpf_error is hit */ - if (seen & (SEEN_XREG | SEEN_DATAREF)) + if (seen_or_pass0 & (SEEN_XREG | SEEN_DATAREF)) EMIT4(0x48, 0x89, 0x5d, 0xf8); /* mov %rbx, -8(%rbp) */ - if (seen & SEEN_XREG) + if (seen_or_pass0 & SEEN_XREG) CLEAR_X(); /* make sure we dont leek kernel memory */ /* @@ -170,7 +171,7 @@ void bpf_jit_compile(struct sk_filter *fp) * r9 = skb->len - skb->data_len * r8 = skb->data */ - if (seen & SEEN_DATAREF) { + if (seen_or_pass0 & SEEN_DATAREF) { if (offsetof(struct sk_buff, len) <= 127) /* mov off8(%rdi),%r9d */ EMIT4(0x44, 0x8b, 0x4f, offsetof(struct sk_buff, len)); @@ -260,9 +261,14 @@ void bpf_jit_compile(struct sk_filter *fp) case BPF_S_ALU_DIV_X: /* A /= X; */ seen |= SEEN_XREG; EMIT2(0x85, 0xdb); /* test %ebx,%ebx */ - if (pc_ret0 != -1) - EMIT_COND_JMP(X86_JE, addrs[pc_ret0] - (addrs[i] - 4)); - else { + if (pc_ret0 > 0) { + /* addrs[pc_ret0 - 1] is start address of target + * (addrs[i] - 4) is the address following this jmp + * ("xor %edx,%edx; div %ebx" being 4 bytes long) + */ + EMIT_COND_JMP(X86_JE, addrs[pc_ret0 - 1] - + (addrs[i] - 4)); + } else { EMIT_COND_JMP(X86_JNE, 2 + 5); CLEAR_A(); EMIT1_off32(0xe9, cleanup_addr - (addrs[i] - 4)); /* jmp .+off32 */ @@ -335,12 +341,12 @@ void bpf_jit_compile(struct sk_filter *fp) } /* fallinto */ case BPF_S_RET_A: - if (seen) { + if (seen_or_pass0) { if (i != flen - 1) { EMIT_JMP(cleanup_addr - addrs[i]); break; } - if (seen & SEEN_XREG) + if (seen_or_pass0 & SEEN_XREG) EMIT4(0x48, 0x8b, 0x5d, 0xf8); /* mov -8(%rbp),%rbx */ EMIT1(0xc9); /* leaveq */ } @@ -483,8 +489,9 @@ common_load: seen |= SEEN_DATAREF; goto common_load; case BPF_S_LDX_B_MSH: if ((int)K < 0) { - if (pc_ret0 != -1) { - EMIT_JMP(addrs[pc_ret0] - addrs[i]); + if (pc_ret0 > 0) { + /* addrs[pc_ret0 - 1] is the start address */ + EMIT_JMP(addrs[pc_ret0 - 1] - addrs[i]); break; } CLEAR_A(); @@ -599,13 +606,14 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; * use it to give the cleanup instruction(s) addr */ cleanup_addr = proglen - 1; /* ret */ - if (seen) + if (seen_or_pass0) cleanup_addr -= 1; /* leaveq */ - if (seen & SEEN_XREG) + if (seen_or_pass0 & SEEN_XREG) cleanup_addr -= 4; /* mov -8(%rbp),%rbx */ if (image) { - WARN_ON(proglen != oldproglen); + if (proglen != oldproglen) + pr_err("bpb_jit_compile proglen=%u != oldproglen=%u\n", proglen, oldproglen); break; } if (proglen == oldproglen) { diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 9be4cff00a2d..3ae0e61abd23 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -1851,6 +1851,8 @@ static void __init init_per_cpu_tunables(void) bcp->cong_reps = congested_reps; bcp->cong_period = congested_period; bcp->clocks_per_100_usec = usec_2_cycles(100); + spin_lock_init(&bcp->queue_lock); + spin_lock_init(&bcp->uvhub_lock); } } diff --git a/arch/x86/platform/uv/uv_irq.c b/arch/x86/platform/uv/uv_irq.c index 374a05d8ad22..f25c2765a5c9 100644 --- a/arch/x86/platform/uv/uv_irq.c +++ b/arch/x86/platform/uv/uv_irq.c @@ -25,7 +25,7 @@ struct uv_irq_2_mmr_pnode{ int irq; }; -static spinlock_t uv_irq_lock; +static DEFINE_SPINLOCK(uv_irq_lock); static struct rb_root uv_irq_root; static int uv_set_irq_affinity(struct irq_data *, const struct cpumask *, bool); diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index cc9b1e182fcf..d69cc6c3f808 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -116,9 +116,26 @@ static inline void spin_time_accum_blocked(u64 start) } #endif /* CONFIG_XEN_DEBUG_FS */ +/* + * Size struct xen_spinlock so it's the same as arch_spinlock_t. + */ +#if NR_CPUS < 256 +typedef u8 xen_spinners_t; +# define inc_spinners(xl) \ + asm(LOCK_PREFIX " incb %0" : "+m" ((xl)->spinners) : : "memory"); +# define dec_spinners(xl) \ + asm(LOCK_PREFIX " decb %0" : "+m" ((xl)->spinners) : : "memory"); +#else +typedef u16 xen_spinners_t; +# define inc_spinners(xl) \ + asm(LOCK_PREFIX " incw %0" : "+m" ((xl)->spinners) : : "memory"); +# define dec_spinners(xl) \ + asm(LOCK_PREFIX " decw %0" : "+m" ((xl)->spinners) : : "memory"); +#endif + struct xen_spinlock { unsigned char lock; /* 0 -> free; 1 -> locked */ - unsigned short spinners; /* count of waiting cpus */ + xen_spinners_t spinners; /* count of waiting cpus */ }; static int xen_spin_is_locked(struct arch_spinlock *lock) @@ -164,8 +181,7 @@ static inline struct xen_spinlock *spinning_lock(struct xen_spinlock *xl) wmb(); /* set lock of interest before count */ - asm(LOCK_PREFIX " incw %0" - : "+m" (xl->spinners) : : "memory"); + inc_spinners(xl); return prev; } @@ -176,8 +192,7 @@ static inline struct xen_spinlock *spinning_lock(struct xen_spinlock *xl) */ static inline void unspinning_lock(struct xen_spinlock *xl, struct xen_spinlock *prev) { - asm(LOCK_PREFIX " decw %0" - : "+m" (xl->spinners) : : "memory"); + dec_spinners(xl); wmb(); /* decrement count before restoring lock */ __this_cpu_write(lock_spinners, prev); } @@ -373,6 +388,8 @@ void xen_uninit_lock_cpu(int cpu) void __init xen_init_spinlocks(void) { + BUILD_BUG_ON(sizeof(struct xen_spinlock) > sizeof(arch_spinlock_t)); + pv_lock_ops.spin_is_locked = xen_spin_is_locked; pv_lock_ops.spin_is_contended = xen_spin_is_contended; pv_lock_ops.spin_lock = xen_spin_lock; diff --git a/arch/xtensa/include/asm/string.h b/arch/xtensa/include/asm/string.h index 5fb8c27cbef5..405a8c49ff2c 100644 --- a/arch/xtensa/include/asm/string.h +++ b/arch/xtensa/include/asm/string.h @@ -118,7 +118,4 @@ extern void *memmove(void *__dest, __const__ void *__src, size_t __n); /* Don't build bcopy at all ... */ #define __HAVE_ARCH_BCOPY -#define __HAVE_ARCH_MEMSCAN -#define memscan memchr - #endif /* _XTENSA_STRING_H */ diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c index 9ed9f60316e5..88f160b77b1f 100644 --- a/crypto/sha512_generic.c +++ b/crypto/sha512_generic.c @@ -21,8 +21,6 @@ #include <linux/percpu.h> #include <asm/byteorder.h> -static DEFINE_PER_CPU(u64[80], msg_schedule); - static inline u64 Ch(u64 x, u64 y, u64 z) { return z ^ (x & (y ^ z)); @@ -80,7 +78,7 @@ static inline void LOAD_OP(int I, u64 *W, const u8 *input) static inline void BLEND_OP(int I, u64 *W) { - W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; + W[I % 16] += s1(W[(I-2) % 16]) + W[(I-7) % 16] + s0(W[(I-15) % 16]); } static void @@ -89,38 +87,48 @@ sha512_transform(u64 *state, const u8 *input) u64 a, b, c, d, e, f, g, h, t1, t2; int i; - u64 *W = get_cpu_var(msg_schedule); + u64 W[16]; /* load the input */ for (i = 0; i < 16; i++) LOAD_OP(i, W, input); - for (i = 16; i < 80; i++) { - BLEND_OP(i, W); - } - /* load the state into our registers */ a=state[0]; b=state[1]; c=state[2]; d=state[3]; e=state[4]; f=state[5]; g=state[6]; h=state[7]; - /* now iterate */ - for (i=0; i<80; i+=8) { - t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[i ]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; +#define SHA512_0_15(i, a, b, c, d, e, f, g, h) \ + t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[i]; \ + t2 = e0(a) + Maj(a, b, c); \ + d += t1; \ + h = t1 + t2 + +#define SHA512_16_79(i, a, b, c, d, e, f, g, h) \ + BLEND_OP(i, W); \ + t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[(i)%16]; \ + t2 = e0(a) + Maj(a, b, c); \ + d += t1; \ + h = t1 + t2 + + for (i = 0; i < 16; i += 8) { + SHA512_0_15(i, a, b, c, d, e, f, g, h); + SHA512_0_15(i + 1, h, a, b, c, d, e, f, g); + SHA512_0_15(i + 2, g, h, a, b, c, d, e, f); + SHA512_0_15(i + 3, f, g, h, a, b, c, d, e); + SHA512_0_15(i + 4, e, f, g, h, a, b, c, d); + SHA512_0_15(i + 5, d, e, f, g, h, a, b, c); + SHA512_0_15(i + 6, c, d, e, f, g, h, a, b); + SHA512_0_15(i + 7, b, c, d, e, f, g, h, a); + } + for (i = 16; i < 80; i += 8) { + SHA512_16_79(i, a, b, c, d, e, f, g, h); + SHA512_16_79(i + 1, h, a, b, c, d, e, f, g); + SHA512_16_79(i + 2, g, h, a, b, c, d, e, f); + SHA512_16_79(i + 3, f, g, h, a, b, c, d, e); + SHA512_16_79(i + 4, e, f, g, h, a, b, c, d); + SHA512_16_79(i + 5, d, e, f, g, h, a, b, c); + SHA512_16_79(i + 6, c, d, e, f, g, h, a, b); + SHA512_16_79(i + 7, b, c, d, e, f, g, h, a); } state[0] += a; state[1] += b; state[2] += c; state[3] += d; @@ -128,8 +136,6 @@ sha512_transform(u64 *state, const u8 *input) /* erase our data */ a = b = c = d = e = f = g = h = t1 = t2 = 0; - memset(W, 0, sizeof(__get_cpu_var(msg_schedule))); - put_cpu_var(msg_schedule); } static int diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index c07f44f05f9d..1567028d2038 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -19,7 +19,6 @@ obj-y += acpi.o \ # All the builtin files are in the "acpi." module_param namespace. acpi-y += osl.o utils.o reboot.o -acpi-y += atomicio.o acpi-y += nvs.o # sleep related files diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index e45350cb6ac8..e5d53b7ddc7e 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -596,33 +596,19 @@ int apei_read(u64 *val, struct acpi_generic_address *reg) { int rc; u64 address; - u32 tmp, width = reg->bit_width; acpi_status status; rc = apei_check_gar(reg, &address); if (rc) return rc; - if (width == 64) - width = 32; /* Break into two 32-bit transfers */ - *val = 0; switch(reg->space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: - status = acpi_os_read_memory((acpi_physical_address) - address, &tmp, width); + status = acpi_os_read_memory64((acpi_physical_address) + address, val, reg->bit_width); if (ACPI_FAILURE(status)) return -EIO; - *val = tmp; - - if (reg->bit_width == 64) { - /* Read the top 32 bits */ - status = acpi_os_read_memory((acpi_physical_address) - (address + 4), &tmp, 32); - if (ACPI_FAILURE(status)) - return -EIO; - *val |= ((u64)tmp << 32); - } break; case ACPI_ADR_SPACE_SYSTEM_IO: status = acpi_os_read_port(address, (u32 *)val, reg->bit_width); @@ -642,31 +628,18 @@ int apei_write(u64 val, struct acpi_generic_address *reg) { int rc; u64 address; - u32 width = reg->bit_width; acpi_status status; rc = apei_check_gar(reg, &address); if (rc) return rc; - if (width == 64) - width = 32; /* Break into two 32-bit transfers */ - switch (reg->space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: - status = acpi_os_write_memory((acpi_physical_address) - address, ACPI_LODWORD(val), - width); + status = acpi_os_write_memory64((acpi_physical_address) + address, val, reg->bit_width); if (ACPI_FAILURE(status)) return -EIO; - - if (reg->bit_width == 64) { - status = acpi_os_write_memory((acpi_physical_address) - (address + 4), - ACPI_HIDWORD(val), 32); - if (ACPI_FAILURE(status)) - return -EIO; - } break; case ACPI_ADR_SPACE_SYSTEM_IO: status = acpi_os_write_port(address, val, reg->bit_width); diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 5b898d4dda99..4ca087dd5f4f 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -141,21 +141,6 @@ static DEFINE_MUTEX(einj_mutex); static void *einj_param; -#ifndef readq -static inline __u64 readq(volatile void __iomem *addr) -{ - return ((__u64)readl(addr+4) << 32) + readl(addr); -} -#endif - -#ifndef writeq -static inline void writeq(__u64 val, volatile void __iomem *addr) -{ - writel(val, addr); - writel(val >> 32, addr+4); -} -#endif - static void einj_exec_ctx_init(struct apei_exec_context *ctx) { apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type), @@ -204,22 +189,21 @@ static int einj_timedout(u64 *t) static void check_vendor_extension(u64 paddr, struct set_error_type_with_address *v5param) { - int offset = readl(&v5param->vendor_extension); + int offset = v5param->vendor_extension; struct vendor_error_type_extension *v; u32 sbdf; if (!offset) return; - v = ioremap(paddr + offset, sizeof(*v)); + v = acpi_os_map_memory(paddr + offset, sizeof(*v)); if (!v) return; - sbdf = readl(&v->pcie_sbdf); + sbdf = v->pcie_sbdf; sprintf(vendor_dev, "%x:%x:%x.%x vendor_id=%x device_id=%x rev_id=%x\n", sbdf >> 24, (sbdf >> 16) & 0xff, (sbdf >> 11) & 0x1f, (sbdf >> 8) & 0x7, - readw(&v->vendor_id), readw(&v->device_id), - readb(&v->rev_id)); - iounmap(v); + v->vendor_id, v->device_id, v->rev_id); + acpi_os_unmap_memory(v, sizeof(*v)); } static void *einj_get_parameter_address(void) @@ -247,7 +231,7 @@ static void *einj_get_parameter_address(void) if (paddrv5) { struct set_error_type_with_address *v5param; - v5param = ioremap(paddrv5, sizeof(*v5param)); + v5param = acpi_os_map_memory(paddrv5, sizeof(*v5param)); if (v5param) { acpi5 = 1; check_vendor_extension(paddrv5, v5param); @@ -257,17 +241,17 @@ static void *einj_get_parameter_address(void) if (paddrv4) { struct einj_parameter *v4param; - v4param = ioremap(paddrv4, sizeof(*v4param)); + v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param)); if (!v4param) - return 0; - if (readq(&v4param->reserved1) || readq(&v4param->reserved2)) { - iounmap(v4param); - return 0; + return NULL; + if (v4param->reserved1 || v4param->reserved2) { + acpi_os_unmap_memory(v4param, sizeof(*v4param)); + return NULL; } return v4param; } - return 0; + return NULL; } /* do sanity check to trigger table */ @@ -276,7 +260,7 @@ static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab) if (trigger_tab->header_size != sizeof(struct acpi_einj_trigger)) return -EINVAL; if (trigger_tab->table_size > PAGE_SIZE || - trigger_tab->table_size <= trigger_tab->header_size) + trigger_tab->table_size < trigger_tab->header_size) return -EINVAL; if (trigger_tab->entry_count != (trigger_tab->table_size - trigger_tab->header_size) / @@ -340,6 +324,11 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type, "The trigger error action table is invalid\n"); goto out_rel_header; } + + /* No action structures in the TRIGGER_ERROR table, nothing to do */ + if (!trigger_tab->entry_count) + goto out_rel_header; + rc = -EIO; table_size = trigger_tab->table_size; r = request_mem_region(trigger_paddr + sizeof(*trigger_tab), @@ -435,41 +424,41 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) if (acpi5) { struct set_error_type_with_address *v5param = einj_param; - writel(type, &v5param->type); + v5param->type = type; if (type & 0x80000000) { switch (vendor_flags) { case SETWA_FLAGS_APICID: - writel(param1, &v5param->apicid); + v5param->apicid = param1; break; case SETWA_FLAGS_MEM: - writeq(param1, &v5param->memory_address); - writeq(param2, &v5param->memory_address_range); + v5param->memory_address = param1; + v5param->memory_address_range = param2; break; case SETWA_FLAGS_PCIE_SBDF: - writel(param1, &v5param->pcie_sbdf); + v5param->pcie_sbdf = param1; break; } - writel(vendor_flags, &v5param->flags); + v5param->flags = vendor_flags; } else { switch (type) { case ACPI_EINJ_PROCESSOR_CORRECTABLE: case ACPI_EINJ_PROCESSOR_UNCORRECTABLE: case ACPI_EINJ_PROCESSOR_FATAL: - writel(param1, &v5param->apicid); - writel(SETWA_FLAGS_APICID, &v5param->flags); + v5param->apicid = param1; + v5param->flags = SETWA_FLAGS_APICID; break; case ACPI_EINJ_MEMORY_CORRECTABLE: case ACPI_EINJ_MEMORY_UNCORRECTABLE: case ACPI_EINJ_MEMORY_FATAL: - writeq(param1, &v5param->memory_address); - writeq(param2, &v5param->memory_address_range); - writel(SETWA_FLAGS_MEM, &v5param->flags); + v5param->memory_address = param1; + v5param->memory_address_range = param2; + v5param->flags = SETWA_FLAGS_MEM; break; case ACPI_EINJ_PCIX_CORRECTABLE: case ACPI_EINJ_PCIX_UNCORRECTABLE: case ACPI_EINJ_PCIX_FATAL: - writel(param1, &v5param->pcie_sbdf); - writel(SETWA_FLAGS_PCIE_SBDF, &v5param->flags); + v5param->pcie_sbdf = param1; + v5param->flags = SETWA_FLAGS_PCIE_SBDF; break; } } @@ -479,8 +468,8 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2) return rc; if (einj_param) { struct einj_parameter *v4param = einj_param; - writeq(param1, &v4param->param1); - writeq(param2, &v4param->param2); + v4param->param1 = param1; + v4param->param2 = param2; } } rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION); @@ -731,8 +720,13 @@ static int __init einj_init(void) return 0; err_unmap: - if (einj_param) - iounmap(einj_param); + if (einj_param) { + acpi_size size = (acpi5) ? + sizeof(struct set_error_type_with_address) : + sizeof(struct einj_parameter); + + acpi_os_unmap_memory(einj_param, size); + } apei_exec_post_unmap_gars(&ctx); err_release: apei_resources_release(&einj_resources); @@ -748,8 +742,13 @@ static void __exit einj_exit(void) { struct apei_exec_context ctx; - if (einj_param) - iounmap(einj_param); + if (einj_param) { + acpi_size size = (acpi5) ? + sizeof(struct set_error_type_with_address) : + sizeof(struct einj_parameter); + + acpi_os_unmap_memory(einj_param, size); + } einj_exec_ctx_init(&ctx); apei_exec_post_unmap_gars(&ctx); apei_resources_release(&einj_resources); diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c deleted file mode 100644 index d4a5b3d3657b..000000000000 --- a/drivers/acpi/atomicio.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * atomicio.c - ACPI IO memory pre-mapping/post-unmapping, then - * accessing in atomic context. - * - * This is used for NMI handler to access IO memory area, because - * ioremap/iounmap can not be used in NMI handler. The IO memory area - * is pre-mapped in process context and accessed in NMI handler. - * - * Copyright (C) 2009-2010, Intel Corp. - * Author: Huang Ying <ying.huang@intel.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/kernel.h> -#include <linux/export.h> -#include <linux/init.h> -#include <linux/acpi.h> -#include <linux/io.h> -#include <linux/kref.h> -#include <linux/rculist.h> -#include <linux/interrupt.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/highmem.h> -#include <acpi/atomicio.h> - -#define ACPI_PFX "ACPI: " - -static LIST_HEAD(acpi_iomaps); -/* - * Used for mutual exclusion between writers of acpi_iomaps list, for - * synchronization between readers and writer, RCU is used. - */ -static DEFINE_SPINLOCK(acpi_iomaps_lock); - -struct acpi_iomap { - struct list_head list; - void __iomem *vaddr; - unsigned long size; - phys_addr_t paddr; - struct kref ref; -}; - -/* acpi_iomaps_lock or RCU read lock must be held before calling */ -static struct acpi_iomap *__acpi_find_iomap(phys_addr_t paddr, - unsigned long size) -{ - struct acpi_iomap *map; - - list_for_each_entry_rcu(map, &acpi_iomaps, list) { - if (map->paddr + map->size >= paddr + size && - map->paddr <= paddr) - return map; - } - return NULL; -} - -/* - * Atomic "ioremap" used by NMI handler, if the specified IO memory - * area is not pre-mapped, NULL will be returned. - * - * acpi_iomaps_lock or RCU read lock must be held before calling - */ -static void __iomem *__acpi_ioremap_fast(phys_addr_t paddr, - unsigned long size) -{ - struct acpi_iomap *map; - - map = __acpi_find_iomap(paddr, size/8); - if (map) - return map->vaddr + (paddr - map->paddr); - else - return NULL; -} - -/* acpi_iomaps_lock must be held before calling */ -static void __iomem *__acpi_try_ioremap(phys_addr_t paddr, - unsigned long size) -{ - struct acpi_iomap *map; - - map = __acpi_find_iomap(paddr, size); - if (map) { - kref_get(&map->ref); - return map->vaddr + (paddr - map->paddr); - } else - return NULL; -} - -#ifndef CONFIG_IA64 -#define should_use_kmap(pfn) page_is_ram(pfn) -#else -/* ioremap will take care of cache attributes */ -#define should_use_kmap(pfn) 0 -#endif - -static void __iomem *acpi_map(phys_addr_t pg_off, unsigned long pg_sz) -{ - unsigned long pfn; - - pfn = pg_off >> PAGE_SHIFT; - if (should_use_kmap(pfn)) { - if (pg_sz > PAGE_SIZE) - return NULL; - return (void __iomem __force *)kmap(pfn_to_page(pfn)); - } else - return ioremap(pg_off, pg_sz); -} - -static void acpi_unmap(phys_addr_t pg_off, void __iomem *vaddr) -{ - unsigned long pfn; - - pfn = pg_off >> PAGE_SHIFT; - if (page_is_ram(pfn)) - kunmap(pfn_to_page(pfn)); - else - iounmap(vaddr); -} - -/* - * Used to pre-map the specified IO memory area. First try to find - * whether the area is already pre-mapped, if it is, increase the - * reference count (in __acpi_try_ioremap) and return; otherwise, do - * the real ioremap, and add the mapping into acpi_iomaps list. - */ -static void __iomem *acpi_pre_map(phys_addr_t paddr, - unsigned long size) -{ - void __iomem *vaddr; - struct acpi_iomap *map; - unsigned long pg_sz, flags; - phys_addr_t pg_off; - - spin_lock_irqsave(&acpi_iomaps_lock, flags); - vaddr = __acpi_try_ioremap(paddr, size); - spin_unlock_irqrestore(&acpi_iomaps_lock, flags); - if (vaddr) - return vaddr; - - pg_off = paddr & PAGE_MASK; - pg_sz = ((paddr + size + PAGE_SIZE - 1) & PAGE_MASK) - pg_off; - vaddr = acpi_map(pg_off, pg_sz); - if (!vaddr) - return NULL; - map = kmalloc(sizeof(*map), GFP_KERNEL); - if (!map) - goto err_unmap; - INIT_LIST_HEAD(&map->list); - map->paddr = pg_off; - map->size = pg_sz; - map->vaddr = vaddr; - kref_init(&map->ref); - - spin_lock_irqsave(&acpi_iomaps_lock, flags); - vaddr = __acpi_try_ioremap(paddr, size); - if (vaddr) { - spin_unlock_irqrestore(&acpi_iomaps_lock, flags); - acpi_unmap(pg_off, map->vaddr); - kfree(map); - return vaddr; - } - list_add_tail_rcu(&map->list, &acpi_iomaps); - spin_unlock_irqrestore(&acpi_iomaps_lock, flags); - - return map->vaddr + (paddr - map->paddr); -err_unmap: - acpi_unmap(pg_off, vaddr); - return NULL; -} - -/* acpi_iomaps_lock must be held before calling */ -static void __acpi_kref_del_iomap(struct kref *ref) -{ - struct acpi_iomap *map; - - map = container_of(ref, struct acpi_iomap, ref); - list_del_rcu(&map->list); -} - -/* - * Used to post-unmap the specified IO memory area. The iounmap is - * done only if the reference count goes zero. - */ -static void acpi_post_unmap(phys_addr_t paddr, unsigned long size) -{ - struct acpi_iomap *map; - unsigned long flags; - int del; - - spin_lock_irqsave(&acpi_iomaps_lock, flags); - map = __acpi_find_iomap(paddr, size); - BUG_ON(!map); - del = kref_put(&map->ref, __acpi_kref_del_iomap); - spin_unlock_irqrestore(&acpi_iomaps_lock, flags); - - if (!del) - return; - - synchronize_rcu(); - acpi_unmap(map->paddr, map->vaddr); - kfree(map); -} - -/* In NMI handler, should set silent = 1 */ -static int acpi_check_gar(struct acpi_generic_address *reg, - u64 *paddr, int silent) -{ - u32 width, space_id; - - width = reg->bit_width; - space_id = reg->space_id; - /* Handle possible alignment issues */ - memcpy(paddr, ®->address, sizeof(*paddr)); - if (!*paddr) { - if (!silent) - pr_warning(FW_BUG ACPI_PFX - "Invalid physical address in GAR [0x%llx/%u/%u]\n", - *paddr, width, space_id); - return -EINVAL; - } - - if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) { - if (!silent) - pr_warning(FW_BUG ACPI_PFX - "Invalid bit width in GAR [0x%llx/%u/%u]\n", - *paddr, width, space_id); - return -EINVAL; - } - - if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY && - space_id != ACPI_ADR_SPACE_SYSTEM_IO) { - if (!silent) - pr_warning(FW_BUG ACPI_PFX - "Invalid address space type in GAR [0x%llx/%u/%u]\n", - *paddr, width, space_id); - return -EINVAL; - } - - return 0; -} - -/* Pre-map, working on GAR */ -int acpi_pre_map_gar(struct acpi_generic_address *reg) -{ - u64 paddr; - void __iomem *vaddr; - int rc; - - if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) - return 0; - - rc = acpi_check_gar(reg, &paddr, 0); - if (rc) - return rc; - - vaddr = acpi_pre_map(paddr, reg->bit_width / 8); - if (!vaddr) - return -EIO; - - return 0; -} -EXPORT_SYMBOL_GPL(acpi_pre_map_gar); - -/* Post-unmap, working on GAR */ -int acpi_post_unmap_gar(struct acpi_generic_address *reg) -{ - u64 paddr; - int rc; - - if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) - return 0; - - rc = acpi_check_gar(reg, &paddr, 0); - if (rc) - return rc; - - acpi_post_unmap(paddr, reg->bit_width / 8); - - return 0; -} -EXPORT_SYMBOL_GPL(acpi_post_unmap_gar); - -#ifdef readq -static inline u64 read64(const volatile void __iomem *addr) -{ - return readq(addr); -} -#else -static inline u64 read64(const volatile void __iomem *addr) -{ - u64 l, h; - l = readl(addr); - h = readl(addr+4); - return l | (h << 32); -} -#endif - -/* - * Can be used in atomic (including NMI) or process context. RCU read - * lock can only be released after the IO memory area accessing. - */ -static int acpi_atomic_read_mem(u64 paddr, u64 *val, u32 width) -{ - void __iomem *addr; - - rcu_read_lock(); - addr = __acpi_ioremap_fast(paddr, width); - switch (width) { - case 8: - *val = readb(addr); - break; - case 16: - *val = readw(addr); - break; - case 32: - *val = readl(addr); - break; - case 64: - *val = read64(addr); - break; - default: - return -EINVAL; - } - rcu_read_unlock(); - - return 0; -} - -#ifdef writeq -static inline void write64(u64 val, volatile void __iomem *addr) -{ - writeq(val, addr); -} -#else -static inline void write64(u64 val, volatile void __iomem *addr) -{ - writel(val, addr); - writel(val>>32, addr+4); -} -#endif - -static int acpi_atomic_write_mem(u64 paddr, u64 val, u32 width) -{ - void __iomem *addr; - - rcu_read_lock(); - addr = __acpi_ioremap_fast(paddr, width); - switch (width) { - case 8: - writeb(val, addr); - break; - case 16: - writew(val, addr); - break; - case 32: - writel(val, addr); - break; - case 64: - write64(val, addr); - break; - default: - return -EINVAL; - } - rcu_read_unlock(); - - return 0; -} - -/* GAR accessing in atomic (including NMI) or process context */ -int acpi_atomic_read(u64 *val, struct acpi_generic_address *reg) -{ - u64 paddr; - int rc; - - rc = acpi_check_gar(reg, &paddr, 1); - if (rc) - return rc; - - *val = 0; - switch (reg->space_id) { - case ACPI_ADR_SPACE_SYSTEM_MEMORY: - return acpi_atomic_read_mem(paddr, val, reg->bit_width); - case ACPI_ADR_SPACE_SYSTEM_IO: - return acpi_os_read_port(paddr, (u32 *)val, reg->bit_width); - default: - return -EINVAL; - } -} -EXPORT_SYMBOL_GPL(acpi_atomic_read); - -int acpi_atomic_write(u64 val, struct acpi_generic_address *reg) -{ - u64 paddr; - int rc; - - rc = acpi_check_gar(reg, &paddr, 1); - if (rc) - return rc; - - switch (reg->space_id) { - case ACPI_ADR_SPACE_SYSTEM_MEMORY: - return acpi_atomic_write_mem(paddr, val, reg->bit_width); - case ACPI_ADR_SPACE_SYSTEM_IO: - return acpi_os_write_port(paddr, val, reg->bit_width); - default: - return -EINVAL; - } -} -EXPORT_SYMBOL_GPL(acpi_atomic_write); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index fcc12d842bcc..412a1e04a922 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -31,6 +31,7 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/mm.h> +#include <linux/highmem.h> #include <linux/pci.h> #include <linux/interrupt.h> #include <linux/kmod.h> @@ -321,6 +322,37 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size) return NULL; } +#ifndef CONFIG_IA64 +#define should_use_kmap(pfn) page_is_ram(pfn) +#else +/* ioremap will take care of cache attributes */ +#define should_use_kmap(pfn) 0 +#endif + +static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz) +{ + unsigned long pfn; + + pfn = pg_off >> PAGE_SHIFT; + if (should_use_kmap(pfn)) { + if (pg_sz > PAGE_SIZE) + return NULL; + return (void __iomem __force *)kmap(pfn_to_page(pfn)); + } else + return acpi_os_ioremap(pg_off, pg_sz); +} + +static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr) +{ + unsigned long pfn; + + pfn = pg_off >> PAGE_SHIFT; + if (page_is_ram(pfn)) + kunmap(pfn_to_page(pfn)); + else + iounmap(vaddr); +} + void __iomem *__init_refok acpi_os_map_memory(acpi_physical_address phys, acpi_size size) { @@ -353,7 +385,7 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size) pg_off = round_down(phys, PAGE_SIZE); pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; - virt = acpi_os_ioremap(pg_off, pg_sz); + virt = acpi_map(pg_off, pg_sz); if (!virt) { mutex_unlock(&acpi_ioremap_lock); kfree(map); @@ -384,7 +416,7 @@ static void acpi_os_map_cleanup(struct acpi_ioremap *map) { if (!map->refcount) { synchronize_rcu(); - iounmap(map->virt); + acpi_unmap(map->phys, map->virt); kfree(map); } } @@ -710,6 +742,67 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) return AE_OK; } +#ifdef readq +static inline u64 read64(const volatile void __iomem *addr) +{ + return readq(addr); +} +#else +static inline u64 read64(const volatile void __iomem *addr) +{ + u64 l, h; + l = readl(addr); + h = readl(addr+4); + return l | (h << 32); +} +#endif + +acpi_status +acpi_os_read_memory64(acpi_physical_address phys_addr, u64 *value, u32 width) +{ + void __iomem *virt_addr; + unsigned int size = width / 8; + bool unmap = false; + u64 dummy; + + rcu_read_lock(); + virt_addr = acpi_map_vaddr_lookup(phys_addr, size); + if (!virt_addr) { + rcu_read_unlock(); + virt_addr = acpi_os_ioremap(phys_addr, size); + if (!virt_addr) + return AE_BAD_ADDRESS; + unmap = true; + } + + if (!value) + value = &dummy; + + switch (width) { + case 8: + *(u8 *) value = readb(virt_addr); + break; + case 16: + *(u16 *) value = readw(virt_addr); + break; + case 32: + *(u32 *) value = readl(virt_addr); + break; + case 64: + *(u64 *) value = read64(virt_addr); + break; + default: + BUG(); + } + + if (unmap) + iounmap(virt_addr); + else + rcu_read_unlock(); + + return AE_OK; +} + acpi_status acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) { @@ -749,6 +842,61 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) return AE_OK; } +#ifdef writeq +static inline void write64(u64 val, volatile void __iomem *addr) +{ + writeq(val, addr); +} +#else +static inline void write64(u64 val, volatile void __iomem *addr) +{ + writel(val, addr); + writel(val>>32, addr+4); +} +#endif + +acpi_status +acpi_os_write_memory64(acpi_physical_address phys_addr, u64 value, u32 width) +{ + void __iomem *virt_addr; + unsigned int size = width / 8; + bool unmap = false; + + rcu_read_lock(); + virt_addr = acpi_map_vaddr_lookup(phys_addr, size); + if (!virt_addr) { + rcu_read_unlock(); + virt_addr = acpi_os_ioremap(phys_addr, size); + if (!virt_addr) + return AE_BAD_ADDRESS; + unmap = true; + } + + switch (width) { + case 8: + writeb(value, virt_addr); + break; + case 16: + writew(value, virt_addr); + break; + case 32: + writel(value, virt_addr); + break; + case 64: + write64(value, virt_addr); + break; + default: + BUG(); + } + + if (unmap) + iounmap(virt_addr); + else + rcu_read_unlock(); + + return AE_OK; +} + acpi_status acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, u64 *value, u32 width) diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 0034ede38710..2b805d7ef317 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -84,7 +84,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type); static void acpi_processor_notify(struct acpi_device *device, u32 event); static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr); static int acpi_processor_handle_eject(struct acpi_processor *pr); - +static int acpi_processor_start(struct acpi_processor *pr); static const struct acpi_device_id processor_device_ids[] = { {ACPI_PROCESSOR_OBJECT_HID, 0}, @@ -423,10 +423,29 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, struct acpi_processor *pr = per_cpu(processors, cpu); if (action == CPU_ONLINE && pr) { - acpi_processor_ppc_has_changed(pr, 0); - acpi_processor_hotplug(pr); - acpi_processor_reevaluate_tstate(pr, action); - acpi_processor_tstate_has_changed(pr); + /* CPU got physically hotplugged and onlined the first time: + * Initialize missing things + */ + if (pr->flags.need_hotplug_init) { + struct cpuidle_driver *idle_driver = + cpuidle_get_driver(); + + printk(KERN_INFO "Will online and init hotplugged " + "CPU: %d\n", pr->id); + WARN(acpi_processor_start(pr), "Failed to start CPU:" + " %d\n", pr->id); + pr->flags.need_hotplug_init = 0; + if (idle_driver && !strcmp(idle_driver->name, + "intel_idle")) { + intel_idle_cpu_init(pr->id); + } + /* Normal CPU soft online event */ + } else { + acpi_processor_ppc_has_changed(pr, 0); + acpi_processor_cst_has_changed(pr); + acpi_processor_reevaluate_tstate(pr, action); + acpi_processor_tstate_has_changed(pr); + } } if (action == CPU_DEAD && pr) { /* invalidate the flag.throttling after one CPU is offline */ @@ -440,6 +459,71 @@ static struct notifier_block acpi_cpu_notifier = .notifier_call = acpi_cpu_soft_notify, }; +/* + * acpi_processor_start() is called by the cpu_hotplug_notifier func: + * acpi_cpu_soft_notify(). Getting it __cpuinit{data} is difficult, the + * root cause seem to be that acpi_processor_uninstall_hotplug_notify() + * is in the module_exit (__exit) func. Allowing acpi_processor_start() + * to not be in __cpuinit section, but being called from __cpuinit funcs + * via __ref looks like the right thing to do here. + */ +static __ref int acpi_processor_start(struct acpi_processor *pr) +{ + struct acpi_device *device = per_cpu(processor_device_array, pr->id); + int result = 0; + +#ifdef CONFIG_CPU_FREQ + acpi_processor_ppc_has_changed(pr, 0); +#endif + acpi_processor_get_throttling_info(pr); + acpi_processor_get_limit_info(pr); + + if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver) + acpi_processor_power_init(pr, device); + + pr->cdev = thermal_cooling_device_register("Processor", device, + &processor_cooling_ops); + if (IS_ERR(pr->cdev)) { + result = PTR_ERR(pr->cdev); + goto err_power_exit; + } + + dev_dbg(&device->dev, "registered as cooling_device%d\n", + pr->cdev->id); + + result = sysfs_create_link(&device->dev.kobj, + &pr->cdev->device.kobj, + "thermal_cooling"); + if (result) { + printk(KERN_ERR PREFIX "Create sysfs link\n"); + goto err_thermal_unregister; + } + result = sysfs_create_link(&pr->cdev->device.kobj, + &device->dev.kobj, + "device"); + if (result) { + printk(KERN_ERR PREFIX "Create sysfs link\n"); + goto err_remove_sysfs_thermal; + } + + return 0; + +err_remove_sysfs_thermal: + sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); +err_thermal_unregister: + thermal_cooling_device_unregister(pr->cdev); +err_power_exit: + acpi_processor_power_exit(pr, device); + + return result; +} + +/* + * Do not put anything in here which needs the core to be online. + * For example MSR access or setting up things which check for cpuinfo_x86 + * (cpu_data(cpu)) values, like CPU feature flags, family, model, etc. + * Such things have to be put in and set up above in acpi_processor_start() + */ static int __cpuinit acpi_processor_add(struct acpi_device *device) { struct acpi_processor *pr = NULL; @@ -495,48 +579,27 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) goto err_free_cpumask; } -#ifdef CONFIG_CPU_FREQ - acpi_processor_ppc_has_changed(pr, 0); -#endif - acpi_processor_get_throttling_info(pr); - acpi_processor_get_limit_info(pr); - - if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver) - acpi_processor_power_init(pr, device); - - pr->cdev = thermal_cooling_device_register("Processor", device, - &processor_cooling_ops); - if (IS_ERR(pr->cdev)) { - result = PTR_ERR(pr->cdev); - goto err_power_exit; - } + /* + * Do not start hotplugged CPUs now, but when they + * are onlined the first time + */ + if (pr->flags.need_hotplug_init) + return 0; - dev_dbg(&device->dev, "registered as cooling_device%d\n", - pr->cdev->id); + /* + * Do not start hotplugged CPUs now, but when they + * are onlined the first time + */ + if (pr->flags.need_hotplug_init) + return 0; - result = sysfs_create_link(&device->dev.kobj, - &pr->cdev->device.kobj, - "thermal_cooling"); - if (result) { - printk(KERN_ERR PREFIX "Create sysfs link\n"); - goto err_thermal_unregister; - } - result = sysfs_create_link(&pr->cdev->device.kobj, - &device->dev.kobj, - "device"); - if (result) { - printk(KERN_ERR PREFIX "Create sysfs link\n"); + result = acpi_processor_start(pr); + if (result) goto err_remove_sysfs; - } return 0; err_remove_sysfs: - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); -err_thermal_unregister: - thermal_cooling_device_unregister(pr->cdev); -err_power_exit: - acpi_processor_power_exit(pr, device); sysfs_remove_link(&device->dev.kobj, "sysdev"); err_free_cpumask: free_cpumask_var(pr->throttling.shared_cpu_map); @@ -735,6 +798,17 @@ static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr) return AE_ERROR; } + /* CPU got hot-plugged, but cpu_data is not initialized yet + * Set flag to delay cpu_idle/throttling initialization + * in: + * acpi_processor_add() + * acpi_processor_get_info() + * and do it when the CPU gets online the first time + * TBD: Cleanup above functions and try to do this more elegant. + */ + printk(KERN_INFO "CPU %d got hotplugged\n", pr->id); + pr->flags.need_hotplug_init = 1; + return AE_OK; } diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 0a7ed69546ba..ca191ff97844 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -438,6 +438,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { }, { .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCCW29FX", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"), + }, + }, + { + .callback = init_nvs_nosave, .ident = "Averatec AV1020-ED2", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"), diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 2c8272dd93c4..610f9997a403 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -1,6 +1,6 @@ # Makefile for the Linux device tree -obj-y := core.o sys.o bus.o dd.o syscore.o \ +obj-y := core.o bus.o dd.o syscore.o \ driver.o class.o platform.o \ cpu.o firmware.o init.o map.o devres.o \ attribute_container.o transport_class.o \ diff --git a/drivers/base/core.c b/drivers/base/core.c index 4a67cc0c8b37..74dda4f697f9 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -632,6 +632,11 @@ static void klist_children_put(struct klist_node *n) * may be used for reference counting of @dev after calling this * function. * + * All fields in @dev must be initialized by the caller to 0, except + * for those explicitly set to some other value. The simplest + * approach is to use kzalloc() to allocate the structure containing + * @dev. + * * NOTE: Use put_device() to give up your reference instead of freeing * @dev directly once you have called this function. */ @@ -930,6 +935,13 @@ int device_private_init(struct device *dev) * to the global and sibling lists for the device, then * adds it to the other relevant subsystems of the driver model. * + * Do not call this routine or device_register() more than once for + * any device structure. The driver model core is not designed to work + * with devices that get unregistered and then spring back to life. + * (Among other things, it's very hard to guarantee that all references + * to the previous incarnation of @dev have been dropped.) Allocate + * and register a fresh new struct device instead. + * * NOTE: _Never_ directly free @dev after calling this function, even * if it returned an error! Always use put_device() to give up your * reference instead. @@ -1022,7 +1034,7 @@ int device_add(struct device *dev) device_pm_add(dev); /* Notify clients of device addition. This call must come - * after dpm_sysf_add() and before kobject_uevent(). + * after dpm_sysfs_add() and before kobject_uevent(). */ if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, @@ -1090,6 +1102,9 @@ name_error: * have a clearly defined need to use and refcount the device * before it is added to the hierarchy. * + * For more information, see the kerneldoc for device_initialize() + * and device_add(). + * * NOTE: _Never_ directly free @dev after calling this function, even * if it returned an error! Always use put_device() to give up the * reference initialized in this function instead. diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index be10a4ff6609..65558034318f 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -284,6 +284,9 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) map->precious_reg = config->precious_reg; map->cache_type = config->cache_type; + map->cache_bypass = false; + map->cache_only = false; + ret = regcache_init(map, config); mutex_unlock(&map->lock); diff --git a/drivers/base/sys.c b/drivers/base/sys.c deleted file mode 100644 index 409f5ce78829..000000000000 --- a/drivers/base/sys.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * sys.c - pseudo-bus for system 'devices' (cpus, PICs, timers, etc) - * - * Copyright (c) 2002-3 Patrick Mochel - * 2002-3 Open Source Development Lab - * - * This file is released under the GPLv2 - * - * This exports a 'system' bus type. - * By default, a 'sys' bus gets added to the root of the system. There will - * always be core system devices. Devices can use sysdev_register() to - * add themselves as children of the system bus. - */ - -#include <linux/sysdev.h> -#include <linux/err.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/string.h> -#include <linux/pm.h> -#include <linux/device.h> -#include <linux/mutex.h> -#include <linux/interrupt.h> - -#include "base.h" - -#define to_sysdev(k) container_of(k, struct sys_device, kobj) -#define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr) - - -static ssize_t -sysdev_show(struct kobject *kobj, struct attribute *attr, char *buffer) -{ - struct sys_device *sysdev = to_sysdev(kobj); - struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr); - - if (sysdev_attr->show) - return sysdev_attr->show(sysdev, sysdev_attr, buffer); - return -EIO; -} - - -static ssize_t -sysdev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) -{ - struct sys_device *sysdev = to_sysdev(kobj); - struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr); - - if (sysdev_attr->store) - return sysdev_attr->store(sysdev, sysdev_attr, buffer, count); - return -EIO; -} - -static const struct sysfs_ops sysfs_ops = { - .show = sysdev_show, - .store = sysdev_store, -}; - -static struct kobj_type ktype_sysdev = { - .sysfs_ops = &sysfs_ops, -}; - - -int sysdev_create_file(struct sys_device *s, struct sysdev_attribute *a) -{ - return sysfs_create_file(&s->kobj, &a->attr); -} - - -void sysdev_remove_file(struct sys_device *s, struct sysdev_attribute *a) -{ - sysfs_remove_file(&s->kobj, &a->attr); -} - -EXPORT_SYMBOL_GPL(sysdev_create_file); -EXPORT_SYMBOL_GPL(sysdev_remove_file); - -#define to_sysdev_class(k) container_of(k, struct sysdev_class, kset.kobj) -#define to_sysdev_class_attr(a) container_of(a, \ - struct sysdev_class_attribute, attr) - -static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr, - char *buffer) -{ - struct sysdev_class *class = to_sysdev_class(kobj); - struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); - - if (class_attr->show) - return class_attr->show(class, class_attr, buffer); - return -EIO; -} - -static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) -{ - struct sysdev_class *class = to_sysdev_class(kobj); - struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); - - if (class_attr->store) - return class_attr->store(class, class_attr, buffer, count); - return -EIO; -} - -static const struct sysfs_ops sysfs_class_ops = { - .show = sysdev_class_show, - .store = sysdev_class_store, -}; - -static struct kobj_type ktype_sysdev_class = { - .sysfs_ops = &sysfs_class_ops, -}; - -int sysdev_class_create_file(struct sysdev_class *c, - struct sysdev_class_attribute *a) -{ - return sysfs_create_file(&c->kset.kobj, &a->attr); -} -EXPORT_SYMBOL_GPL(sysdev_class_create_file); - -void sysdev_class_remove_file(struct sysdev_class *c, - struct sysdev_class_attribute *a) -{ - sysfs_remove_file(&c->kset.kobj, &a->attr); -} -EXPORT_SYMBOL_GPL(sysdev_class_remove_file); - -extern struct kset *system_kset; - -int sysdev_class_register(struct sysdev_class *cls) -{ - int retval; - - pr_debug("Registering sysdev class '%s'\n", cls->name); - - INIT_LIST_HEAD(&cls->drivers); - memset(&cls->kset.kobj, 0x00, sizeof(struct kobject)); - cls->kset.kobj.parent = &system_kset->kobj; - cls->kset.kobj.ktype = &ktype_sysdev_class; - cls->kset.kobj.kset = system_kset; - - retval = kobject_set_name(&cls->kset.kobj, "%s", cls->name); - if (retval) - return retval; - - retval = kset_register(&cls->kset); - if (!retval && cls->attrs) - retval = sysfs_create_files(&cls->kset.kobj, - (const struct attribute **)cls->attrs); - return retval; -} - -void sysdev_class_unregister(struct sysdev_class *cls) -{ - pr_debug("Unregistering sysdev class '%s'\n", - kobject_name(&cls->kset.kobj)); - if (cls->attrs) - sysfs_remove_files(&cls->kset.kobj, - (const struct attribute **)cls->attrs); - kset_unregister(&cls->kset); -} - -EXPORT_SYMBOL_GPL(sysdev_class_register); -EXPORT_SYMBOL_GPL(sysdev_class_unregister); - -static DEFINE_MUTEX(sysdev_drivers_lock); - -/* - * @dev != NULL means that we're unwinding because some drv->add() - * failed for some reason. You need to grab sysdev_drivers_lock before - * calling this. - */ -static void __sysdev_driver_remove(struct sysdev_class *cls, - struct sysdev_driver *drv, - struct sys_device *from_dev) -{ - struct sys_device *dev = from_dev; - - list_del_init(&drv->entry); - if (!cls) - return; - - if (!drv->remove) - goto kset_put; - - if (dev) - list_for_each_entry_continue_reverse(dev, &cls->kset.list, - kobj.entry) - drv->remove(dev); - else - list_for_each_entry(dev, &cls->kset.list, kobj.entry) - drv->remove(dev); - -kset_put: - kset_put(&cls->kset); -} - -/** - * sysdev_driver_register - Register auxiliary driver - * @cls: Device class driver belongs to. - * @drv: Driver. - * - * @drv is inserted into @cls->drivers to be - * called on each operation on devices of that class. The refcount - * of @cls is incremented. - */ -int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv) -{ - struct sys_device *dev = NULL; - int err = 0; - - if (!cls) { - WARN(1, KERN_WARNING "sysdev: invalid class passed to %s!\n", - __func__); - return -EINVAL; - } - - /* Check whether this driver has already been added to a class. */ - if (drv->entry.next && !list_empty(&drv->entry)) - WARN(1, KERN_WARNING "sysdev: class %s: driver (%p) has already" - " been registered to a class, something is wrong, but " - "will forge on!\n", cls->name, drv); - - mutex_lock(&sysdev_drivers_lock); - if (cls && kset_get(&cls->kset)) { - list_add_tail(&drv->entry, &cls->drivers); - - /* If devices of this class already exist, tell the driver */ - if (drv->add) { - list_for_each_entry(dev, &cls->kset.list, kobj.entry) { - err = drv->add(dev); - if (err) - goto unwind; - } - } - } else { - err = -EINVAL; - WARN(1, KERN_ERR "%s: invalid device class\n", __func__); - } - - goto unlock; - -unwind: - __sysdev_driver_remove(cls, drv, dev); - -unlock: - mutex_unlock(&sysdev_drivers_lock); - return err; -} - -/** - * sysdev_driver_unregister - Remove an auxiliary driver. - * @cls: Class driver belongs to. - * @drv: Driver. - */ -void sysdev_driver_unregister(struct sysdev_class *cls, - struct sysdev_driver *drv) -{ - mutex_lock(&sysdev_drivers_lock); - __sysdev_driver_remove(cls, drv, NULL); - mutex_unlock(&sysdev_drivers_lock); -} -EXPORT_SYMBOL_GPL(sysdev_driver_register); -EXPORT_SYMBOL_GPL(sysdev_driver_unregister); - -/** - * sysdev_register - add a system device to the tree - * @sysdev: device in question - * - */ -int sysdev_register(struct sys_device *sysdev) -{ - int error; - struct sysdev_class *cls = sysdev->cls; - - if (!cls) - return -EINVAL; - - pr_debug("Registering sys device of class '%s'\n", - kobject_name(&cls->kset.kobj)); - - /* initialize the kobject to 0, in case it had previously been used */ - memset(&sysdev->kobj, 0x00, sizeof(struct kobject)); - - /* Make sure the kset is set */ - sysdev->kobj.kset = &cls->kset; - - /* Register the object */ - error = kobject_init_and_add(&sysdev->kobj, &ktype_sysdev, NULL, - "%s%d", kobject_name(&cls->kset.kobj), - sysdev->id); - - if (!error) { - struct sysdev_driver *drv; - - pr_debug("Registering sys device '%s'\n", - kobject_name(&sysdev->kobj)); - - mutex_lock(&sysdev_drivers_lock); - /* Generic notification is implicit, because it's that - * code that should have called us. - */ - - /* Notify class auxiliary drivers */ - list_for_each_entry(drv, &cls->drivers, entry) { - if (drv->add) - drv->add(sysdev); - } - mutex_unlock(&sysdev_drivers_lock); - kobject_uevent(&sysdev->kobj, KOBJ_ADD); - } - - return error; -} - -void sysdev_unregister(struct sys_device *sysdev) -{ - struct sysdev_driver *drv; - - mutex_lock(&sysdev_drivers_lock); - list_for_each_entry(drv, &sysdev->cls->drivers, entry) { - if (drv->remove) - drv->remove(sysdev); - } - mutex_unlock(&sysdev_drivers_lock); - - kobject_put(&sysdev->kobj); -} - -EXPORT_SYMBOL_GPL(sysdev_register); -EXPORT_SYMBOL_GPL(sysdev_unregister); - -#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr) - -ssize_t sysdev_store_ulong(struct sys_device *sysdev, - struct sysdev_attribute *attr, - const char *buf, size_t size) -{ - struct sysdev_ext_attribute *ea = to_ext_attr(attr); - char *end; - unsigned long new = simple_strtoul(buf, &end, 0); - if (end == buf) - return -EINVAL; - *(unsigned long *)(ea->var) = new; - /* Always return full write size even if we didn't consume all */ - return size; -} -EXPORT_SYMBOL_GPL(sysdev_store_ulong); - -ssize_t sysdev_show_ulong(struct sys_device *sysdev, - struct sysdev_attribute *attr, - char *buf) -{ - struct sysdev_ext_attribute *ea = to_ext_attr(attr); - return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var)); -} -EXPORT_SYMBOL_GPL(sysdev_show_ulong); - -ssize_t sysdev_store_int(struct sys_device *sysdev, - struct sysdev_attribute *attr, - const char *buf, size_t size) -{ - struct sysdev_ext_attribute *ea = to_ext_attr(attr); - char *end; - long new = simple_strtol(buf, &end, 0); - if (end == buf || new > INT_MAX || new < INT_MIN) - return -EINVAL; - *(int *)(ea->var) = new; - /* Always return full write size even if we didn't consume all */ - return size; -} -EXPORT_SYMBOL_GPL(sysdev_store_int); - -ssize_t sysdev_show_int(struct sys_device *sysdev, - struct sysdev_attribute *attr, - char *buf) -{ - struct sysdev_ext_attribute *ea = to_ext_attr(attr); - return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var)); -} -EXPORT_SYMBOL_GPL(sysdev_show_int); - diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 3fd31dec8c9c..a6278e7e61a0 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -380,6 +380,7 @@ static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr, rbdc = __rbd_client_find(opt); if (rbdc) { ceph_destroy_options(opt); + kfree(rbd_opts); /* using an existing client */ kref_get(&rbdc->kref); @@ -406,15 +407,15 @@ done_err: /* * Destroy ceph client + * + * Caller must hold node_lock. */ static void rbd_client_release(struct kref *kref) { struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref); dout("rbd_release_client %p\n", rbdc); - spin_lock(&node_lock); list_del(&rbdc->node); - spin_unlock(&node_lock); ceph_destroy_client(rbdc->client); kfree(rbdc->rbd_opts); @@ -427,7 +428,9 @@ static void rbd_client_release(struct kref *kref) */ static void rbd_put_client(struct rbd_device *rbd_dev) { + spin_lock(&node_lock); kref_put(&rbd_dev->rbd_client->kref, rbd_client_release); + spin_unlock(&node_lock); rbd_dev->rbd_client = NULL; rbd_dev->client = NULL; } diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 4b71647782d0..317c28ce8328 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -194,10 +194,10 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) err_out: if (bridge->driver->needs_scratch_page) { - void *va = page_address(bridge->scratch_page_page); + struct page *page = bridge->scratch_page_page; - bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); - bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); + bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP); + bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE); } if (got_gatt) bridge->driver->free_gatt_table(bridge); @@ -221,10 +221,10 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) if (bridge->driver->agp_destroy_page && bridge->driver->needs_scratch_page) { - void *va = page_address(bridge->scratch_page_page); + struct page *page = bridge->scratch_page_page; - bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); - bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); + bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP); + bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE); } } diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 97f87b29b9f3..f4aed5fc2cb6 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1343,7 +1343,7 @@ static int __init at_dma_probe(struct platform_device *pdev) tasklet_init(&atchan->tasklet, atc_tasklet, (unsigned long)atchan); - atc_enable_irq(atchan); + atc_enable_chan_irq(atdma, i); } /* set base routines */ @@ -1410,7 +1410,7 @@ static int __exit at_dma_remove(struct platform_device *pdev) struct at_dma_chan *atchan = to_at_dma_chan(chan); /* Disable interrupts */ - atc_disable_irq(atchan); + atc_disable_chan_irq(atdma, chan->chan_id); tasklet_disable(&atchan->tasklet); tasklet_kill(&atchan->tasklet); diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index dcaedfc181cf..a8d3277d60b5 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -327,28 +327,27 @@ static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli) } -static void atc_setup_irq(struct at_dma_chan *atchan, int on) +static void atc_setup_irq(struct at_dma *atdma, int chan_id, int on) { - struct at_dma *atdma = to_at_dma(atchan->chan_common.device); - u32 ebci; + u32 ebci; /* enable interrupts on buffer transfer completion & error */ - ebci = AT_DMA_BTC(atchan->chan_common.chan_id) - | AT_DMA_ERR(atchan->chan_common.chan_id); + ebci = AT_DMA_BTC(chan_id) + | AT_DMA_ERR(chan_id); if (on) dma_writel(atdma, EBCIER, ebci); else dma_writel(atdma, EBCIDR, ebci); } -static inline void atc_enable_irq(struct at_dma_chan *atchan) +static void atc_enable_chan_irq(struct at_dma *atdma, int chan_id) { - atc_setup_irq(atchan, 1); + atc_setup_irq(atdma, chan_id, 1); } -static inline void atc_disable_irq(struct at_dma_chan *atchan) +static void atc_disable_chan_irq(struct at_dma *atdma, int chan_id) { - atc_setup_irq(atchan, 0); + atc_setup_irq(atdma, chan_id, 0); } diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 2b8661b54eaf..24225f0fdcd8 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -599,7 +599,7 @@ static int dmatest_add_channel(struct dma_chan *chan) } if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) { cnt = dmatest_add_threads(dtc, DMA_PQ); - thread_count += cnt > 0 ?: 0; + thread_count += cnt > 0 ? cnt : 0; } pr_info("dmatest: Started %u threads using %s\n", diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index a8af379680c1..8bc5acf36ee5 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1102,11 +1102,13 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, case DMA_SLAVE_CONFIG: if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { sdmac->per_address = dmaengine_cfg->src_addr; - sdmac->watermark_level = dmaengine_cfg->src_maxburst; + sdmac->watermark_level = dmaengine_cfg->src_maxburst * + dmaengine_cfg->src_addr_width; sdmac->word_size = dmaengine_cfg->src_addr_width; } else { sdmac->per_address = dmaengine_cfg->dst_addr; - sdmac->watermark_level = dmaengine_cfg->dst_maxburst; + sdmac->watermark_level = dmaengine_cfg->dst_maxburst * + dmaengine_cfg->dst_addr_width; sdmac->word_size = dmaengine_cfg->dst_addr_width; } sdmac->direction = dmaengine_cfg->direction; diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 54043cd831c8..812fd76e9c18 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -1262,7 +1262,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev) INIT_LIST_HEAD(&shdev->common.channels); - dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask); + if (!pdata->slave_only) + dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask); if (pdata->slave && pdata->slave_num) dma_cap_set(DMA_SLAVE, shdev->common.cap_mask); diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 6628feaa7622..7f5f0da726da 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -263,6 +263,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card) static char ohci_driver_name[] = KBUILD_MODNAME; #define PCI_DEVICE_ID_AGERE_FW643 0x5901 +#define PCI_DEVICE_ID_CREATIVE_SB1394 0x4001 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380 #define PCI_DEVICE_ID_TI_TSB12LV22 0x8009 #define PCI_DEVICE_ID_TI_TSB12LV26 0x8020 @@ -289,6 +290,9 @@ static const struct { {PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6, QUIRK_NO_MSI}, + {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID, + QUIRK_RESET_PACKET}, + {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID, QUIRK_NO_MSI}, @@ -299,7 +303,7 @@ static const struct { QUIRK_NO_MSI}, {PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID, - QUIRK_CYCLE_TIMER}, + QUIRK_CYCLE_TIMER | QUIRK_NO_MSI}, {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID, QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A}, diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 5b6948081f8f..ddfacc5ce56d 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -96,7 +96,7 @@ static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = { }; static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = { - "gpi000", "gpio01", "gpio02", "gpio03", + "gpio00", "gpio01", "gpio02", "gpio03", "gpio04", "gpio05" }; diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 03d6dd5dcb77..f0febe5b8221 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -448,6 +448,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev, chip->reg = chip->base; chip->ch = i; mutex_init(&chip->lock); + spin_lock_init(&chip->spinlock); ioh_gpio_setup(chip, num_ports[i]); ret = gpiochip_add(&chip->gpio); if (ret) { diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 68fa55e86eb1..e8729cc2ba2b 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -392,6 +392,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev, chip->reg = chip->base; pci_set_drvdata(pdev, chip); mutex_init(&chip->lock); + spin_lock_init(&chip->spinlock); pch_gpio_setup(chip); ret = gpiochip_add(&chip->gpio); if (ret) { diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index a7661773c052..0a79a1167a25 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -2387,27 +2387,30 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = { }; #if defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF) -static int exynos4_gpio_xlate(struct gpio_chip *gc, struct device_node *np, - const void *gpio_spec, u32 *flags) +static int exynos4_gpio_xlate(struct gpio_chip *gc, + const struct of_phandle_args *gpiospec, u32 *flags) { - const __be32 *gpio = gpio_spec; - const u32 n = be32_to_cpup(gpio); - unsigned int pin = gc->base + be32_to_cpu(gpio[0]); + unsigned int pin; if (WARN_ON(gc->of_gpio_n_cells < 4)) return -EINVAL; - if (n > gc->ngpio) + if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) return -EINVAL; - if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(be32_to_cpu(gpio[1])))) + if (gpiospec->args[0] > gc->ngpio) + return -EINVAL; + + pin = gc->base + gpiospec->args[0]; + + if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1]))) pr_warn("gpio_xlate: failed to set pin function\n"); - if (s3c_gpio_setpull(pin, be32_to_cpu(gpio[2]))) + if (s3c_gpio_setpull(pin, gpiospec->args[2])) pr_warn("gpio_xlate: failed to set pin pull up/down\n"); - if (s5p_gpio_set_drvstr(pin, be32_to_cpu(gpio[3]))) + if (s5p_gpio_set_drvstr(pin, gpiospec->args[3])) pr_warn("gpio_xlate: failed to set pin drive strength\n"); - return n; + return gpiospec->args[0]; } static const struct of_device_id exynos4_gpio_dt_match[] __initdata = { diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index 3f46772f0cb2..ba23790450e9 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -101,7 +101,7 @@ static int drm_add_magic(struct drm_master *master, struct drm_file *priv, * Searches and unlinks the entry in drm_device::magiclist with the magic * number hash key, while holding the drm_device::struct_mutex lock. */ -static int drm_remove_magic(struct drm_master *master, drm_magic_t magic) +int drm_remove_magic(struct drm_master *master, drm_magic_t magic) { struct drm_magic_entry *pt; struct drm_hash_item *hash; @@ -136,6 +136,8 @@ static int drm_remove_magic(struct drm_master *master, drm_magic_t magic) * If there is a magic number in drm_file::magic then use it, otherwise * searches an unique non-zero magic number and add it associating it with \p * file_priv. + * This ioctl needs protection by the drm_global_mutex, which protects + * struct drm_file::magic and struct drm_magic_entry::priv. */ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -173,6 +175,8 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) * \return zero if authentication successed, or a negative number otherwise. * * Checks if \p file_priv is associated with the magic number passed in \arg. + * This ioctl needs protection by the drm_global_mutex, which protects + * struct drm_file::magic and struct drm_magic_entry::priv. */ int drm_authmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index c00cf154cc0b..6263b0147598 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -487,6 +487,11 @@ int drm_release(struct inode *inode, struct file *filp) (long)old_encode_dev(file_priv->minor->device), dev->open_count); + /* Release any auth tokens that might point to this file_priv, + (do that under the drm_global_mutex) */ + if (file_priv->magic) + (void) drm_remove_magic(file_priv->master, file_priv->magic); + /* if the master has gone away we can't do anything with the lock */ if (file_priv->minor->master) drm_master_release(dev, filp); diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 396e60ce8114..f8625e290728 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -140,7 +140,7 @@ int drm_gem_object_init(struct drm_device *dev, obj->dev = dev; obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE); if (IS_ERR(obj->filp)) - return -ENOMEM; + return PTR_ERR(obj->filp); kref_init(&obj->refcount); atomic_set(&obj->handle_count, 0); diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index f9aaa56eae07..b9e5266c341b 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -13,7 +13,7 @@ config DRM_EXYNOS config DRM_EXYNOS_FIMD tristate "Exynos DRM FIMD" - depends on DRM_EXYNOS + depends on DRM_EXYNOS && !FB_S3C default n help Choose this option if you want to use Exynos FIMD for DRM. @@ -21,7 +21,7 @@ config DRM_EXYNOS_FIMD config DRM_EXYNOS_HDMI tristate "Exynos DRM HDMI" - depends on DRM_EXYNOS + depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV help Choose this option if you want to use Exynos HDMI for DRM. If M is selected, the module will be called exynos_drm_hdmi diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index ca83139cd309..b6a737d196ae 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -158,7 +158,8 @@ static void fimd_dpms(struct device *subdrv_dev, int mode) case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - pm_runtime_put_sync(subdrv_dev); + if (!ctx->suspended) + pm_runtime_put_sync(subdrv_dev); break; default: DRM_DEBUG_KMS("unspecified mode %d\n", mode); @@ -734,6 +735,46 @@ static void fimd_clear_win(struct fimd_context *ctx, int win) writel(val, ctx->regs + SHADOWCON); } +static int fimd_power_on(struct fimd_context *ctx, bool enable) +{ + struct exynos_drm_subdrv *subdrv = &ctx->subdrv; + struct device *dev = subdrv->manager.dev; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + if (enable != false && enable != true) + return -EINVAL; + + if (enable) { + int ret; + + ret = clk_enable(ctx->bus_clk); + if (ret < 0) + return ret; + + ret = clk_enable(ctx->lcd_clk); + if (ret < 0) { + clk_disable(ctx->bus_clk); + return ret; + } + + ctx->suspended = false; + + /* if vblank was enabled status, enable it again. */ + if (test_and_clear_bit(0, &ctx->irq_flags)) + fimd_enable_vblank(dev); + + fimd_apply(dev); + } else { + clk_disable(ctx->lcd_clk); + clk_disable(ctx->bus_clk); + + ctx->suspended = true; + } + + return 0; +} + static int __devinit fimd_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -911,39 +952,30 @@ out: #ifdef CONFIG_PM_SLEEP static int fimd_suspend(struct device *dev) { - int ret; + struct fimd_context *ctx = get_fimd_context(dev); if (pm_runtime_suspended(dev)) return 0; - ret = pm_runtime_suspend(dev); - if (ret < 0) - return ret; - - return 0; + /* + * do not use pm_runtime_suspend(). if pm_runtime_suspend() is + * called here, an error would be returned by that interface + * because the usage_count of pm runtime is more than 1. + */ + return fimd_power_on(ctx, false); } static int fimd_resume(struct device *dev) { - int ret; - - ret = pm_runtime_resume(dev); - if (ret < 0) { - DRM_ERROR("failed to resume runtime pm.\n"); - return ret; - } - - pm_runtime_disable(dev); - - ret = pm_runtime_set_active(dev); - if (ret < 0) { - DRM_ERROR("failed to active runtime pm.\n"); - pm_runtime_enable(dev); - pm_runtime_suspend(dev); - return ret; - } + struct fimd_context *ctx = get_fimd_context(dev); - pm_runtime_enable(dev); + /* + * if entered to sleep when lcd panel was on, the usage_count + * of pm runtime would still be 1 so in this case, fimd driver + * should be on directly not drawing on pm runtime interface. + */ + if (!pm_runtime_suspended(dev)) + return fimd_power_on(ctx, true); return 0; } @@ -956,39 +988,16 @@ static int fimd_runtime_suspend(struct device *dev) DRM_DEBUG_KMS("%s\n", __FILE__); - clk_disable(ctx->lcd_clk); - clk_disable(ctx->bus_clk); - - ctx->suspended = true; - return 0; + return fimd_power_on(ctx, false); } static int fimd_runtime_resume(struct device *dev) { struct fimd_context *ctx = get_fimd_context(dev); - int ret; DRM_DEBUG_KMS("%s\n", __FILE__); - ret = clk_enable(ctx->bus_clk); - if (ret < 0) - return ret; - - ret = clk_enable(ctx->lcd_clk); - if (ret < 0) { - clk_disable(ctx->bus_clk); - return ret; - } - - ctx->suspended = false; - - /* if vblank was enabled status, enable it again. */ - if (test_and_clear_bit(0, &ctx->irq_flags)) - fimd_enable_vblank(dev); - - fimd_apply(dev); - - return 0; + return fimd_power_on(ctx, true); } #endif diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index f48f7ce92f5f..3429d3fd93f3 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1116,8 +1116,8 @@ err_ddc: err_iomap: iounmap(hdata->regs); err_req_region: - release_resource(hdata->regs_res); - kfree(hdata->regs_res); + release_mem_region(hdata->regs_res->start, + resource_size(hdata->regs_res)); err_resource: hdmi_resources_cleanup(hdata); err_data: @@ -1145,8 +1145,8 @@ static int __devexit hdmi_remove(struct platform_device *pdev) iounmap(hdata->regs); - release_resource(hdata->regs_res); - kfree(hdata->regs_res); + release_mem_region(hdata->regs_res->start, + resource_size(hdata->regs_res)); /* hdmiphy i2c driver */ i2c_del_driver(&hdmiphy_driver); diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 791c0ef1a65b..830dfdd6bf15 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -113,12 +113,12 @@ static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info) void psbfb_suspend(struct drm_device *dev) { - struct drm_framebuffer *fb = 0; - struct psb_framebuffer *psbfb = to_psb_fb(fb); + struct drm_framebuffer *fb; console_lock(); mutex_lock(&dev->mode_config.mutex); list_for_each_entry(fb, &dev->mode_config.fb_list, head) { + struct psb_framebuffer *psbfb = to_psb_fb(fb); struct fb_info *info = psbfb->fbdev; fb_set_suspend(info, 1); drm_fb_helper_blank(FB_BLANK_POWERDOWN, info); @@ -129,12 +129,12 @@ void psbfb_suspend(struct drm_device *dev) void psbfb_resume(struct drm_device *dev) { - struct drm_framebuffer *fb = 0; - struct psb_framebuffer *psbfb = to_psb_fb(fb); + struct drm_framebuffer *fb; console_lock(); mutex_lock(&dev->mode_config.mutex); list_for_each_entry(fb, &dev->mode_config.fb_list, head) { + struct psb_framebuffer *psbfb = to_psb_fb(fb); struct fb_info *info = psbfb->fbdev; fb_set_suspend(info, 0); drm_fb_helper_blank(FB_BLANK_UNBLANK, info); diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index e770bd190a5c..5d5330f667f1 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -20,6 +20,7 @@ */ #include <drm/drmP.h> +#include <linux/shmem_fs.h> #include "psb_drv.h" @@ -203,9 +204,7 @@ static int psb_gtt_attach_pages(struct gtt_range *gt) gt->npage = pages; for (i = 0; i < pages; i++) { - /* FIXME: needs updating as per mail from Hugh Dickins */ - p = read_cache_page_gfp(mapping, i, - __GFP_COLD | GFP_KERNEL); + p = shmem_read_mapping_page(mapping, i); if (IS_ERR(p)) goto err; gt->pages[i] = p; diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index f7c17b239833..7f4b4e10246e 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -886,7 +886,7 @@ static int i810_flush_queue(struct drm_device *dev) } /* Must be called with the lock held */ -void i810_driver_reclaim_buffers(struct drm_device *dev, +static void i810_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) { struct drm_device_dma *dma = dev->dma; @@ -1223,17 +1223,12 @@ void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) if (dev_priv->page_flipping) i810_do_cleanup_pageflip(dev); } +} - if (file_priv->master && file_priv->master->lock.hw_lock) { - drm_idlelock_take(&file_priv->master->lock); - i810_driver_reclaim_buffers(dev, file_priv); - drm_idlelock_release(&file_priv->master->lock); - } else { - /* master disappeared, clean up stuff anyway and hope nothing - * goes wrong */ - i810_driver_reclaim_buffers(dev, file_priv); - } - +void i810_driver_reclaim_buffers_locked(struct drm_device *dev, + struct drm_file *file_priv) +{ + i810_reclaim_buffers(dev, file_priv); } int i810_driver_dma_quiescent(struct drm_device *dev) diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index 053f1ee58393..ec12f7dc717a 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -63,6 +63,7 @@ static struct drm_driver driver = { .lastclose = i810_driver_lastclose, .preclose = i810_driver_preclose, .device_is_agp = i810_driver_device_is_agp, + .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked, .dma_quiescent = i810_driver_dma_quiescent, .ioctls = i810_ioctls, .fops = &i810_driver_fops, diff --git a/drivers/gpu/drm/i810/i810_drv.h b/drivers/gpu/drm/i810/i810_drv.h index 6e0acad9e0f5..c9339f481795 100644 --- a/drivers/gpu/drm/i810/i810_drv.h +++ b/drivers/gpu/drm/i810/i810_drv.h @@ -116,12 +116,14 @@ typedef struct drm_i810_private { /* i810_dma.c */ extern int i810_driver_dma_quiescent(struct drm_device *dev); -void i810_driver_reclaim_buffers(struct drm_device *dev, - struct drm_file *file_priv); +extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev, + struct drm_file *file_priv); extern int i810_driver_load(struct drm_device *, unsigned long flags); extern void i810_driver_lastclose(struct drm_device *dev); extern void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv); +extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev, + struct drm_file *file_priv); extern int i810_driver_device_is_agp(struct drm_device *dev); extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 11807989f918..deaa657292b4 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -121,11 +121,11 @@ static const char *cache_level_str(int type) static void describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) { - seq_printf(m, "%p: %s%s %8zd %04x %04x %d %d%s%s%s", + seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d%s%s%s", &obj->base, get_pin_flag(obj), get_tiling_flag(obj), - obj->base.size, + obj->base.size / 1024, obj->base.read_domains, obj->base.write_domain, obj->last_rendering_seqno, @@ -653,7 +653,7 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data) seq_printf(m, " Size : %08x\n", ring->size); seq_printf(m, " Active : %08x\n", intel_ring_get_active_head(ring)); seq_printf(m, " NOPID : %08x\n", I915_READ_NOPID(ring)); - if (IS_GEN6(dev)) { + if (IS_GEN6(dev) || IS_GEN7(dev)) { seq_printf(m, " Sync 0 : %08x\n", I915_READ_SYNC_0(ring)); seq_printf(m, " Sync 1 : %08x\n", I915_READ_SYNC_1(ring)); } @@ -1075,6 +1075,7 @@ static int gen6_drpc_info(struct seq_file *m) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 rpmodectl1, gt_core_status, rcctl1; + unsigned forcewake_count; int count=0, ret; @@ -1082,9 +1083,13 @@ static int gen6_drpc_info(struct seq_file *m) if (ret) return ret; - if (atomic_read(&dev_priv->forcewake_count)) { - seq_printf(m, "RC information inaccurate because userspace " - "holds a reference \n"); + spin_lock_irq(&dev_priv->gt_lock); + forcewake_count = dev_priv->forcewake_count; + spin_unlock_irq(&dev_priv->gt_lock); + + if (forcewake_count) { + seq_printf(m, "RC information inaccurate because somebody " + "holds a forcewake reference \n"); } else { /* NB: we cannot use forcewake, else we read the wrong values */ while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1)) @@ -1106,7 +1111,7 @@ static int gen6_drpc_info(struct seq_file *m) seq_printf(m, "SW control enabled: %s\n", yesno((rpmodectl1 & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE)); - seq_printf(m, "RC6 Enabled: %s\n", + seq_printf(m, "RC1e Enabled: %s\n", yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE)); seq_printf(m, "RC6 Enabled: %s\n", yesno(rcctl1 & GEN6_RC_CTL_RC6_ENABLE)); @@ -1398,9 +1403,13 @@ static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data) struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; + unsigned forcewake_count; + + spin_lock_irq(&dev_priv->gt_lock); + forcewake_count = dev_priv->forcewake_count; + spin_unlock_irq(&dev_priv->gt_lock); - seq_printf(m, "forcewake count = %d\n", - atomic_read(&dev_priv->forcewake_count)); + seq_printf(m, "forcewake count = %u\n", forcewake_count); return 0; } @@ -1665,7 +1674,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file) struct drm_i915_private *dev_priv = dev->dev_private; int ret; - if (!IS_GEN6(dev)) + if (INTEL_INFO(dev)->gen < 6) return 0; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -1682,7 +1691,7 @@ int i915_forcewake_release(struct inode *inode, struct file *file) struct drm_device *dev = inode->i_private; struct drm_i915_private *dev_priv = dev->dev_private; - if (!IS_GEN6(dev)) + if (INTEL_INFO(dev)->gen < 6) return 0; /* diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 5f4d5893e983..ddfe3d902b2a 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -2045,6 +2045,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (!IS_I945G(dev) && !IS_I945GM(dev)) pci_enable_msi(dev->pdev); + spin_lock_init(&dev_priv->gt_lock); spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->error_lock); spin_lock_init(&dev_priv->rps_lock); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8f7187915b0d..308f81913562 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -368,11 +368,12 @@ void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) */ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) { - WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); + unsigned long irqflags; - /* Forcewake is atomic in case we get in here without the lock */ - if (atomic_add_return(1, &dev_priv->forcewake_count) == 1) + spin_lock_irqsave(&dev_priv->gt_lock, irqflags); + if (dev_priv->forcewake_count++ == 0) dev_priv->display.force_wake_get(dev_priv); + spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); } void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) @@ -392,10 +393,12 @@ void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) */ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { - WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); + unsigned long irqflags; - if (atomic_dec_and_test(&dev_priv->forcewake_count)) + spin_lock_irqsave(&dev_priv->gt_lock, irqflags); + if (--dev_priv->forcewake_count == 0) dev_priv->display.force_wake_put(dev_priv); + spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); } void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) @@ -597,9 +600,36 @@ static int ironlake_do_reset(struct drm_device *dev, u8 flags) static int gen6_do_reset(struct drm_device *dev, u8 flags) { struct drm_i915_private *dev_priv = dev->dev_private; + int ret; + unsigned long irqflags; - I915_WRITE(GEN6_GDRST, GEN6_GRDOM_FULL); - return wait_for((I915_READ(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500); + /* Hold gt_lock across reset to prevent any register access + * with forcewake not set correctly + */ + spin_lock_irqsave(&dev_priv->gt_lock, irqflags); + + /* Reset the chip */ + + /* GEN6_GDRST is not in the gt power well, no need to check + * for fifo space for the write or forcewake the chip for + * the read + */ + I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL); + + /* Spin waiting for the device to ack the reset request */ + ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500); + + /* If reset with a user forcewake, try to restore, otherwise turn it off */ + if (dev_priv->forcewake_count) + dev_priv->display.force_wake_get(dev_priv); + else + dev_priv->display.force_wake_put(dev_priv); + + /* Restore fifo count */ + dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); + + spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); + return ret; } /** @@ -643,9 +673,6 @@ int i915_reset(struct drm_device *dev, u8 flags) case 7: case 6: ret = gen6_do_reset(dev, flags); - /* If reset with a user forcewake, try to restore */ - if (atomic_read(&dev_priv->forcewake_count)) - __gen6_gt_force_wake_get(dev_priv); break; case 5: ret = ironlake_do_reset(dev, flags); @@ -927,9 +954,14 @@ MODULE_LICENSE("GPL and additional rights"); u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ u##x val = 0; \ if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ - gen6_gt_force_wake_get(dev_priv); \ + unsigned long irqflags; \ + spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \ + if (dev_priv->forcewake_count == 0) \ + dev_priv->display.force_wake_get(dev_priv); \ val = read##y(dev_priv->regs + reg); \ - gen6_gt_force_wake_put(dev_priv); \ + if (dev_priv->forcewake_count == 0) \ + dev_priv->display.force_wake_put(dev_priv); \ + spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \ } else { \ val = read##y(dev_priv->regs + reg); \ } \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 602bc80baabb..9689ca38b2b3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -288,7 +288,13 @@ typedef struct drm_i915_private { int relative_constants_mode; void __iomem *regs; - u32 gt_fifo_count; + /** gt_fifo_count and the subsequent register write are synchronized + * with dev->struct_mutex. */ + unsigned gt_fifo_count; + /** forcewake_count is protected by gt_lock */ + unsigned forcewake_count; + /** gt_lock is also taken in irq contexts. */ + struct spinlock gt_lock; struct intel_gmbus { struct i2c_adapter adapter; @@ -741,8 +747,6 @@ typedef struct drm_i915_private { struct drm_property *broadcast_rgb_property; struct drm_property *force_audio_property; - - atomic_t forcewake_count; } drm_i915_private_t; enum i915_cache_level { diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5d433fc11ace..5bd4361ea84d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1751,7 +1751,8 @@ static void ironlake_irq_preinstall(struct drm_device *dev) INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); I915_WRITE(HWSTAM, 0xeffe); - if (IS_GEN6(dev) || IS_GEN7(dev)) { + + if (IS_GEN6(dev)) { /* Workaround stalls observed on Sandy Bridge GPUs by * making the blitter command streamer generate a * write to the Hardware Status Page for diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 7886e4fb60e3..2b5eb229ff2c 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -28,14 +28,19 @@ #include "drm.h" #include "i915_drm.h" #include "intel_drv.h" +#include "i915_reg.h" static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; u32 dpll_reg; + /* On IVB, 3rd pipe shares PLL with another one */ + if (pipe > 1) + return false; + if (HAS_PCH_SPLIT(dev)) - dpll_reg = (pipe == PIPE_A) ? _PCH_DPLL_A : _PCH_DPLL_B; + dpll_reg = PCH_DPLL(pipe); else dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B; @@ -822,7 +827,7 @@ int i915_save_state(struct drm_device *dev) if (IS_IRONLAKE_M(dev)) ironlake_disable_drps(dev); - if (IS_GEN6(dev)) + if (INTEL_INFO(dev)->gen >= 6) gen6_disable_rps(dev); /* Cache mode state */ @@ -881,7 +886,7 @@ int i915_restore_state(struct drm_device *dev) intel_init_emon(dev); } - if (IS_GEN6(dev)) { + if (INTEL_INFO(dev)->gen >= 6) { gen6_enable_rps(dev_priv); gen6_update_ring_freq(dev_priv); } diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 8af3735e27c6..dbda6e3bdf07 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -467,8 +467,12 @@ struct edp_link_params { struct bdb_edp { struct edp_power_seq power_seqs[16]; u32 color_depth; - u32 sdrrs_msa_timing_delay; struct edp_link_params link_params[16]; + u32 sdrrs_msa_timing_delay; + + /* ith bit indicates enabled/disabled for (i+1)th panel */ + u16 edp_s3d_feature; + u16 edp_t3_optimization; } __attribute__ ((packed)); void intel_setup_bios(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index fee0ad02c6d0..dd729d46a61f 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -24,6 +24,7 @@ * Eric Anholt <eric@anholt.net> */ +#include <linux/dmi.h> #include <linux/i2c.h> #include <linux/slab.h> #include "drmP.h" @@ -540,6 +541,24 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = { .destroy = intel_encoder_destroy, }; +static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id) +{ + DRM_DEBUG_KMS("Skipping CRT initialization for %s\n", id->ident); + return 1; +} + +static const struct dmi_system_id intel_no_crt[] = { + { + .callback = intel_no_crt_dmi_callback, + .ident = "ACER ZGB", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ACER"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), + }, + }, + { } +}; + void intel_crt_init(struct drm_device *dev) { struct drm_connector *connector; @@ -547,6 +566,10 @@ void intel_crt_init(struct drm_device *dev) struct intel_connector *intel_connector; struct drm_i915_private *dev_priv = dev->dev_private; + /* Skip machines without VGA that falsely report hotplug events */ + if (dmi_check_system(intel_no_crt)) + return; + crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL); if (!crt) return; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2a3f707caab8..b3b51c43dad0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5808,12 +5808,15 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, if (is_lvds) { temp = I915_READ(PCH_LVDS); temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; - if (HAS_PCH_CPT(dev)) + if (HAS_PCH_CPT(dev)) { + temp &= ~PORT_TRANS_SEL_MASK; temp |= PORT_TRANS_SEL_CPT(pipe); - else if (pipe == 1) - temp |= LVDS_PIPEB_SELECT; - else - temp &= ~LVDS_PIPEB_SELECT; + } else { + if (pipe == 1) + temp |= LVDS_PIPEB_SELECT; + else + temp &= ~LVDS_PIPEB_SELECT; + } /* set the corresponsding LVDS_BORDER bit */ temp |= dev_priv->lvds_border_bits; @@ -9025,12 +9028,9 @@ void intel_modeset_init(struct drm_device *dev) for (i = 0; i < dev_priv->num_pipe; i++) { intel_crtc_init(dev, i); - if (HAS_PCH_SPLIT(dev)) { - ret = intel_plane_init(dev, i); - if (ret) - DRM_ERROR("plane %d init failed: %d\n", - i, ret); - } + ret = intel_plane_init(dev, i); + if (ret) + DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret); } /* Just disable it once at startup */ diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index e44191132ac4..798f6e1aa544 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -708,6 +708,14 @@ static const struct dmi_system_id intel_no_lvds[] = { }, }, { + .callback = intel_no_lvds_dmi_callback, + .ident = "Clientron E830", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Clientron"), + DMI_MATCH(DMI_PRODUCT_NAME, "E830"), + }, + }, + { .callback = intel_no_lvds_dmi_callback, .ident = "Asus EeeBox PC EB1007", .matches = { diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 77e729d4e4f0..1ab842c6032e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -636,6 +636,19 @@ render_ring_add_request(struct intel_ring_buffer *ring, } static u32 +gen6_ring_get_seqno(struct intel_ring_buffer *ring) +{ + struct drm_device *dev = ring->dev; + + /* Workaround to force correct ordering between irq and seqno writes on + * ivb (and maybe also on snb) by reading from a CS register (like + * ACTHD) before reading the status page. */ + if (IS_GEN7(dev)) + intel_ring_get_active_head(ring); + return intel_read_status_page(ring, I915_GEM_HWS_INDEX); +} + +static u32 ring_get_seqno(struct intel_ring_buffer *ring) { return intel_read_status_page(ring, I915_GEM_HWS_INDEX); @@ -792,17 +805,6 @@ ring_add_request(struct intel_ring_buffer *ring, } static bool -gen7_blt_ring_get_irq(struct intel_ring_buffer *ring) -{ - /* The BLT ring on IVB appears to have broken synchronization - * between the seqno write and the interrupt, so that the - * interrupt appears first. Returning false here makes - * i915_wait_request() do a polling loop, instead. - */ - return false; -} - -static bool gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag) { struct drm_device *dev = ring->dev; @@ -811,6 +813,12 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag) if (!dev->irq_enabled) return false; + /* It looks like we need to prevent the gt from suspending while waiting + * for an notifiy irq, otherwise irqs seem to get lost on at least the + * blt/bsd rings on ivb. */ + if (IS_GEN7(dev)) + gen6_gt_force_wake_get(dev_priv); + spin_lock(&ring->irq_lock); if (ring->irq_refcount++ == 0) { ring->irq_mask &= ~rflag; @@ -835,6 +843,9 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag) ironlake_disable_irq(dev_priv, gflag); } spin_unlock(&ring->irq_lock); + + if (IS_GEN7(dev)) + gen6_gt_force_wake_put(dev_priv); } static bool @@ -1341,7 +1352,7 @@ static const struct intel_ring_buffer gen6_bsd_ring = { .write_tail = gen6_bsd_ring_write_tail, .flush = gen6_ring_flush, .add_request = gen6_add_request, - .get_seqno = ring_get_seqno, + .get_seqno = gen6_ring_get_seqno, .irq_get = gen6_bsd_ring_get_irq, .irq_put = gen6_bsd_ring_put_irq, .dispatch_execbuffer = gen6_ring_dispatch_execbuffer, @@ -1476,7 +1487,7 @@ static const struct intel_ring_buffer gen6_blt_ring = { .write_tail = ring_write_tail, .flush = blt_ring_flush, .add_request = gen6_add_request, - .get_seqno = ring_get_seqno, + .get_seqno = gen6_ring_get_seqno, .irq_get = blt_ring_get_irq, .irq_put = blt_ring_put_irq, .dispatch_execbuffer = gen6_ring_dispatch_execbuffer, @@ -1499,6 +1510,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->flush = gen6_render_ring_flush; ring->irq_get = gen6_render_ring_get_irq; ring->irq_put = gen6_render_ring_put_irq; + ring->get_seqno = gen6_ring_get_seqno; } else if (IS_GEN5(dev)) { ring->add_request = pc_render_add_request; ring->get_seqno = pc_render_get_seqno; @@ -1577,8 +1589,5 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) *ring = gen6_blt_ring; - if (IS_GEN7(dev)) - ring->irq_get = gen7_blt_ring_get_irq; - return intel_init_ring_buffer(dev, ring); } diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f7b9268df266..e334ec33a47d 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1066,15 +1066,13 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, /* Set the SDVO control regs. */ if (INTEL_INFO(dev)->gen >= 4) { - sdvox = 0; + /* The real mode polarity is set by the SDVO commands, using + * struct intel_sdvo_dtd. */ + sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH; if (intel_sdvo->is_hdmi) sdvox |= intel_sdvo->color_range; if (INTEL_INFO(dev)->gen < 5) sdvox |= SDVO_BORDER_ENABLE; - if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) - sdvox |= SDVO_VSYNC_ACTIVE_HIGH; - if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) - sdvox |= SDVO_HSYNC_ACTIVE_HIGH; } else { sdvox = I915_READ(intel_sdvo->sdvo_reg); switch (intel_sdvo->sdvo_reg) { diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index d13989fda501..2288abf88cce 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -466,10 +466,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, mutex_lock(&dev->struct_mutex); ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); - if (ret) { - DRM_ERROR("failed to pin object\n"); + if (ret) goto out_unlock; - } intel_plane->obj = obj; @@ -632,10 +630,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) unsigned long possible_crtcs; int ret; - if (!(IS_GEN6(dev) || IS_GEN7(dev))) { - DRM_ERROR("new plane code only for SNB+\n"); + if (!(IS_GEN6(dev) || IS_GEN7(dev))) return -ENODEV; - } intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL); if (!intel_plane) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index f3c6a9a8b081..1571be37ce3e 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -417,7 +417,7 @@ static const struct tv_mode tv_modes[] = { { .name = "NTSC-M", .clock = 108000, - .refresh = 29970, + .refresh = 59940, .oversample = TV_OVERSAMPLE_8X, .component_only = 0, /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */ @@ -460,7 +460,7 @@ static const struct tv_mode tv_modes[] = { { .name = "NTSC-443", .clock = 108000, - .refresh = 29970, + .refresh = 59940, .oversample = TV_OVERSAMPLE_8X, .component_only = 0, /* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */ @@ -502,7 +502,7 @@ static const struct tv_mode tv_modes[] = { { .name = "NTSC-J", .clock = 108000, - .refresh = 29970, + .refresh = 59940, .oversample = TV_OVERSAMPLE_8X, .component_only = 0, @@ -545,7 +545,7 @@ static const struct tv_mode tv_modes[] = { { .name = "PAL-M", .clock = 108000, - .refresh = 29970, + .refresh = 59940, .oversample = TV_OVERSAMPLE_8X, .component_only = 0, @@ -589,7 +589,7 @@ static const struct tv_mode tv_modes[] = { /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */ .name = "PAL-N", .clock = 108000, - .refresh = 25000, + .refresh = 50000, .oversample = TV_OVERSAMPLE_8X, .component_only = 0, @@ -634,7 +634,7 @@ static const struct tv_mode tv_modes[] = { /* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */ .name = "PAL", .clock = 108000, - .refresh = 25000, + .refresh = 50000, .oversample = TV_OVERSAMPLE_8X, .component_only = 0, @@ -674,78 +674,6 @@ static const struct tv_mode tv_modes[] = { .filter_table = filter_table, }, { - .name = "480p@59.94Hz", - .clock = 107520, - .refresh = 59940, - .oversample = TV_OVERSAMPLE_4X, - .component_only = 1, - - .hsync_end = 64, .hblank_end = 122, - .hblank_start = 842, .htotal = 857, - - .progressive = true, .trilevel_sync = false, - - .vsync_start_f1 = 12, .vsync_start_f2 = 12, - .vsync_len = 12, - - .veq_ena = false, - - .vi_end_f1 = 44, .vi_end_f2 = 44, - .nbr_end = 479, - - .burst_ena = false, - - .filter_table = filter_table, - }, - { - .name = "480p@60Hz", - .clock = 107520, - .refresh = 60000, - .oversample = TV_OVERSAMPLE_4X, - .component_only = 1, - - .hsync_end = 64, .hblank_end = 122, - .hblank_start = 842, .htotal = 856, - - .progressive = true, .trilevel_sync = false, - - .vsync_start_f1 = 12, .vsync_start_f2 = 12, - .vsync_len = 12, - - .veq_ena = false, - - .vi_end_f1 = 44, .vi_end_f2 = 44, - .nbr_end = 479, - - .burst_ena = false, - - .filter_table = filter_table, - }, - { - .name = "576p", - .clock = 107520, - .refresh = 50000, - .oversample = TV_OVERSAMPLE_4X, - .component_only = 1, - - .hsync_end = 64, .hblank_end = 139, - .hblank_start = 859, .htotal = 863, - - .progressive = true, .trilevel_sync = false, - - .vsync_start_f1 = 10, .vsync_start_f2 = 10, - .vsync_len = 10, - - .veq_ena = false, - - .vi_end_f1 = 48, .vi_end_f2 = 48, - .nbr_end = 575, - - .burst_ena = false, - - .filter_table = filter_table, - }, - { .name = "720p@60Hz", .clock = 148800, .refresh = 60000, @@ -770,30 +698,6 @@ static const struct tv_mode tv_modes[] = { .filter_table = filter_table, }, { - .name = "720p@59.94Hz", - .clock = 148800, - .refresh = 59940, - .oversample = TV_OVERSAMPLE_2X, - .component_only = 1, - - .hsync_end = 80, .hblank_end = 300, - .hblank_start = 1580, .htotal = 1651, - - .progressive = true, .trilevel_sync = true, - - .vsync_start_f1 = 10, .vsync_start_f2 = 10, - .vsync_len = 10, - - .veq_ena = false, - - .vi_end_f1 = 29, .vi_end_f2 = 29, - .nbr_end = 719, - - .burst_ena = false, - - .filter_table = filter_table, - }, - { .name = "720p@50Hz", .clock = 148800, .refresh = 50000, @@ -821,7 +725,7 @@ static const struct tv_mode tv_modes[] = { { .name = "1080i@50Hz", .clock = 148800, - .refresh = 25000, + .refresh = 50000, .oversample = TV_OVERSAMPLE_2X, .component_only = 1, @@ -847,7 +751,7 @@ static const struct tv_mode tv_modes[] = { { .name = "1080i@60Hz", .clock = 148800, - .refresh = 30000, + .refresh = 60000, .oversample = TV_OVERSAMPLE_2X, .component_only = 1, @@ -870,32 +774,6 @@ static const struct tv_mode tv_modes[] = { .filter_table = filter_table, }, - { - .name = "1080i@59.94Hz", - .clock = 148800, - .refresh = 29970, - .oversample = TV_OVERSAMPLE_2X, - .component_only = 1, - - .hsync_end = 88, .hblank_end = 235, - .hblank_start = 2155, .htotal = 2201, - - .progressive = false, .trilevel_sync = true, - - .vsync_start_f1 = 4, .vsync_start_f2 = 5, - .vsync_len = 10, - - .veq_ena = true, .veq_start_f1 = 4, - .veq_start_f2 = 4, .veq_len = 10, - - - .vi_end_f1 = 21, .vi_end_f2 = 22, - .nbr_end = 539, - - .burst_ena = false, - - .filter_table = filter_table, - }, }; static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 1e382ad5a2b8..a37c31e358aa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -54,9 +54,10 @@ struct bit_entry { int bit_table(struct drm_device *, u8 id, struct bit_entry *); enum dcb_gpio_tag { - DCB_GPIO_TVDAC0 = 0xc, + DCB_GPIO_PANEL_POWER = 0x01, + DCB_GPIO_TVDAC0 = 0x0c, DCB_GPIO_TVDAC1 = 0x2d, - DCB_GPIO_PWM_FAN = 0x9, + DCB_GPIO_PWM_FAN = 0x09, DCB_GPIO_FAN_SENSE = 0x3d, DCB_GPIO_UNUSED = 0xff }; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 724b41a2b9e9..ec54364ac828 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -812,6 +812,10 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_vma *vma; + /* ttm can now (stupidly) pass the driver bos it didn't create... */ + if (bo->destroy != nouveau_bo_del_ttm) + return; + list_for_each_entry(vma, &nvbo->vma_list, head) { if (new_mem && new_mem->mem_type == TTM_PL_VRAM) { nouveau_vm_map(vma, new_mem->mm_node); diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 3cb52bc52b21..795a9e3c990a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -219,6 +219,16 @@ nouveau_display_init(struct drm_device *dev) if (ret) return ret; + /* power on internal panel if it's not already. the init tables of + * some vbios default this to off for some reason, causing the + * panel to not work after resume + */ + if (nouveau_gpio_func_get(dev, DCB_GPIO_PANEL_POWER) == 0) { + nouveau_gpio_func_set(dev, DCB_GPIO_PANEL_POWER, true); + msleep(300); + } + + /* enable polling for external displays */ drm_kms_helper_poll_enable(dev); /* enable hotplug interrupts */ diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index e4a7cfe7898d..81d7962e7252 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -124,7 +124,7 @@ MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n"); int nouveau_ctxfw; module_param_named(ctxfw, nouveau_ctxfw, int, 0400); -MODULE_PARM_DESC(ctxfw, "Santise DCB table according to MXM-SIS\n"); +MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS\n"); int nouveau_mxmdcb = 1; module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 5f0bc57fdaab..7ce3fde40743 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -380,6 +380,25 @@ retry: } static int +validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo) +{ + struct nouveau_fence *fence = NULL; + int ret = 0; + + spin_lock(&nvbo->bo.bdev->fence_lock); + if (nvbo->bo.sync_obj) + fence = nouveau_fence_ref(nvbo->bo.sync_obj); + spin_unlock(&nvbo->bo.bdev->fence_lock); + + if (fence) { + ret = nouveau_fence_sync(fence, chan); + nouveau_fence_unref(&fence); + } + + return ret; +} + +static int validate_list(struct nouveau_channel *chan, struct list_head *list, struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr) { @@ -393,7 +412,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, list_for_each_entry(nvbo, list, entry) { struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; - ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan); + ret = validate_sync(chan, nvbo); if (unlikely(ret)) { NV_ERROR(dev, "fail pre-validate sync\n"); return ret; @@ -416,7 +435,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, return ret; } - ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan); + ret = validate_sync(chan, nvbo); if (unlikely(ret)) { NV_ERROR(dev, "fail post-validate sync\n"); return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_mxm.c b/drivers/gpu/drm/nouveau/nouveau_mxm.c index 8bccddf4eff0..e5a64f0f4cb7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mxm.c +++ b/drivers/gpu/drm/nouveau/nouveau_mxm.c @@ -656,7 +656,16 @@ nouveau_mxm_init(struct drm_device *dev) if (mxm_shadow(dev, mxm[0])) { MXM_MSG(dev, "failed to locate valid SIS\n"); +#if 0 + /* we should, perhaps, fall back to some kind of limited + * mode here if the x86 vbios hasn't already done the + * work for us (so we prevent loading with completely + * whacked vbios tables). + */ return -EINVAL; +#else + return 0; +#endif } MXM_MSG(dev, "MXMS Version %d.%d\n", diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index 03937212e9d8..ec5481dfcd82 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c @@ -495,9 +495,9 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_pm_state *info; struct pll_lims pll; - int ret = -EINVAL; + int clk, ret = -EINVAL; int N, M, P1, P2; - u32 clk, out; + u32 out; if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 0fda830ef806..742f17f009a9 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -355,15 +355,12 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } -static void atombios_disable_ss(struct drm_crtc *crtc) +static void atombios_disable_ss(struct radeon_device *rdev, int pll_id) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct radeon_device *rdev = dev->dev_private; u32 ss_cntl; if (ASIC_IS_DCE4(rdev)) { - switch (radeon_crtc->pll_id) { + switch (pll_id) { case ATOM_PPLL1: ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL); ss_cntl &= ~EVERGREEN_PxPLL_SS_EN; @@ -379,7 +376,7 @@ static void atombios_disable_ss(struct drm_crtc *crtc) return; } } else if (ASIC_IS_AVIVO(rdev)) { - switch (radeon_crtc->pll_id) { + switch (pll_id) { case ATOM_PPLL1: ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL); ss_cntl &= ~1; @@ -406,13 +403,11 @@ union atom_enable_ss { ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 v3; }; -static void atombios_crtc_program_ss(struct drm_crtc *crtc, +static void atombios_crtc_program_ss(struct radeon_device *rdev, int enable, int pll_id, struct radeon_atom_ss *ss) { - struct drm_device *dev = crtc->dev; - struct radeon_device *rdev = dev->dev_private; int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); union atom_enable_ss args; @@ -479,7 +474,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc, } else if (ASIC_IS_AVIVO(rdev)) { if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK)) { - atombios_disable_ss(crtc); + atombios_disable_ss(rdev, pll_id); return; } args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); @@ -491,7 +486,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc, } else { if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK)) { - atombios_disable_ss(crtc); + atombios_disable_ss(rdev, pll_id); return; } args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); @@ -523,6 +518,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, int encoder_mode = 0; u32 dp_clock = mode->clock; int bpc = 8; + bool is_duallink = false; /* reset the pll flags */ pll->flags = 0; @@ -557,6 +553,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, if (connector && connector->display_info.bpc) bpc = connector->display_info.bpc; encoder_mode = atombios_get_encoder_mode(encoder); + is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock); if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) { if (connector) { @@ -652,7 +649,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, if (dig->coherent_mode) args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_COHERENT_MODE; - if (mode->clock > 165000) + if (is_duallink) args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK; } @@ -702,11 +699,9 @@ union set_pixel_clock { /* on DCE5, make sure the voltage is high enough to support the * required disp clk. */ -static void atombios_crtc_set_dcpll(struct drm_crtc *crtc, +static void atombios_crtc_set_dcpll(struct radeon_device *rdev, u32 dispclk) { - struct drm_device *dev = crtc->dev; - struct radeon_device *rdev = dev->dev_private; u8 frev, crev; int index; union set_pixel_clock args; @@ -996,7 +991,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, &ref_div, &post_div); - atombios_crtc_program_ss(crtc, ATOM_DISABLE, radeon_crtc->pll_id, &ss); + atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss); atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, encoder_mode, radeon_encoder->encoder_id, mode->clock, @@ -1019,7 +1014,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ss.step = step_size; } - atombios_crtc_program_ss(crtc, ATOM_ENABLE, radeon_crtc->pll_id, &ss); + atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss); } } @@ -1189,7 +1184,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1); WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, - crtc->mode.vdisplay); + target_fb->height); x &= ~3; y &= ~1; WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, @@ -1358,7 +1353,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, - crtc->mode.vdisplay); + target_fb->height); x &= ~3; y &= ~1; WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, @@ -1494,6 +1489,24 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) } +void radeon_atom_dcpll_init(struct radeon_device *rdev) +{ + /* always set DCPLL */ + if (ASIC_IS_DCE4(rdev)) { + struct radeon_atom_ss ss; + bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss, + ASIC_INTERNAL_SS_ON_DCPLL, + rdev->clock.default_dispclk); + if (ss_enabled) + atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss); + /* XXX: DCE5, make sure voltage, dispclk is high enough */ + atombios_crtc_set_dcpll(rdev, rdev->clock.default_dispclk); + if (ss_enabled) + atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss); + } + +} + int atombios_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -1515,19 +1528,6 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, } } - /* always set DCPLL */ - if (ASIC_IS_DCE4(rdev)) { - struct radeon_atom_ss ss; - bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss, - ASIC_INTERNAL_SS_ON_DCPLL, - rdev->clock.default_dispclk); - if (ss_enabled) - atombios_crtc_program_ss(crtc, ATOM_DISABLE, ATOM_DCPLL, &ss); - /* XXX: DCE5, make sure voltage, dispclk is high enough */ - atombios_crtc_set_dcpll(crtc, rdev->clock.default_dispclk); - if (ss_enabled) - atombios_crtc_program_ss(crtc, ATOM_ENABLE, ATOM_DCPLL, &ss); - } atombios_crtc_set_pll(crtc, adjusted_mode); if (ASIC_IS_DCE4(rdev)) diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 6fb335a4fdda..552b436451fd 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -549,8 +549,8 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) return false; } -static void radeon_dp_set_panel_mode(struct drm_encoder *encoder, - struct drm_connector *connector) +int radeon_dp_get_panel_mode(struct drm_encoder *encoder, + struct drm_connector *connector) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -558,28 +558,33 @@ static void radeon_dp_set_panel_mode(struct drm_encoder *encoder, int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; if (!ASIC_IS_DCE4(rdev)) - return; + return panel_mode; if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == ENCODER_OBJECT_ID_NUTMEG) panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == - ENCODER_OBJECT_ID_TRAVIS) - panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; - else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + ENCODER_OBJECT_ID_TRAVIS) { + u8 id[6]; + int i; + for (i = 0; i < 6; i++) + id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i); + if (id[0] == 0x73 && + id[1] == 0x69 && + id[2] == 0x76 && + id[3] == 0x61 && + id[4] == 0x72 && + id[5] == 0x54) + panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; + else + panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; + } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); if (tmp & 1) panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; } - atombios_dig_encoder_setup(encoder, - ATOM_ENCODER_CMD_SETUP_PANEL_MODE, - panel_mode); - - if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) && - (panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) { - radeon_write_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_SET, 1); - } + return panel_mode; } void radeon_dp_set_link_config(struct drm_connector *connector, @@ -717,6 +722,8 @@ static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp) static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(dp_info->encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; u8 tmp; /* power up the sink */ @@ -732,7 +739,10 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) radeon_write_dpcd_reg(dp_info->radeon_connector, DP_DOWNSPREAD_CTRL, 0); - radeon_dp_set_panel_mode(dp_info->encoder, dp_info->connector); + if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) && + (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) { + radeon_write_dpcd_reg(dp_info->radeon_connector, DP_EDP_CONFIGURATION_SET, 1); + } /* set the lane count on the sink */ tmp = dp_info->dp_lane_count; diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index f1f06ca9f1f5..b88c4608731b 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -57,22 +57,6 @@ static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) } } -static struct drm_connector * -radeon_get_connector_for_encoder_init(struct drm_encoder *encoder) -{ - struct drm_device *dev = encoder->dev; - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct drm_connector *connector; - struct radeon_connector *radeon_connector; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - radeon_connector = to_radeon_connector(connector); - if (radeon_encoder->devices & radeon_connector->devices) - return connector; - } - return NULL; -} - static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -253,7 +237,7 @@ atombios_dvo_setup(struct drm_encoder *encoder, int action) /* R4xx, R5xx */ args.ext_tmds.sXTmdsEncoder.ucEnable = action; - if (radeon_encoder->pixel_clock > 165000) + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL; args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB; @@ -265,7 +249,7 @@ atombios_dvo_setup(struct drm_encoder *encoder, int action) /* DFP1, CRT1, TV1 depending on the type of port */ args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX; - if (radeon_encoder->pixel_clock > 165000) + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL; break; case 3: @@ -349,7 +333,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) } else { if (dig->linkb) args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; - if (radeon_encoder->pixel_clock > 165000) + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; /*if (pScrn->rgbBits == 8) */ args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; @@ -388,7 +372,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) } else { if (dig->linkb) args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; - if (radeon_encoder->pixel_clock > 165000) + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; } break; @@ -432,7 +416,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ - if (drm_detect_monitor_audio(radeon_connector->edid) && + if (drm_detect_hdmi_monitor(radeon_connector->edid) && radeon_audio) return ATOM_ENCODER_MODE_HDMI; else if (radeon_connector->use_digital) @@ -443,7 +427,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_HDMIA: default: - if (drm_detect_monitor_audio(radeon_connector->edid) && + if (drm_detect_hdmi_monitor(radeon_connector->edid) && radeon_audio) return ATOM_ENCODER_MODE_HDMI; else @@ -457,7 +441,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) return ATOM_ENCODER_MODE_DP; - else if (drm_detect_monitor_audio(radeon_connector->edid) && + else if (drm_detect_hdmi_monitor(radeon_connector->edid) && radeon_audio) return ATOM_ENCODER_MODE_HDMI; else @@ -587,7 +571,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)) args.v1.ucLaneNum = dp_lane_count; - else if (radeon_encoder->pixel_clock > 165000) + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v1.ucLaneNum = 8; else args.v1.ucLaneNum = 4; @@ -622,7 +606,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)) args.v3.ucLaneNum = dp_lane_count; - else if (radeon_encoder->pixel_clock > 165000) + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v3.ucLaneNum = 8; else args.v3.ucLaneNum = 4; @@ -662,7 +646,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode)) args.v4.ucLaneNum = dp_lane_count; - else if (radeon_encoder->pixel_clock > 165000) + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v4.ucLaneNum = 8; else args.v4.ucLaneNum = 4; @@ -806,7 +790,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t if (is_dp) args.v1.usPixelClock = cpu_to_le16(dp_clock / 10); - else if (radeon_encoder->pixel_clock > 165000) + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); else args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); @@ -821,7 +805,8 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t if ((rdev->flags & RADEON_IS_IGP) && (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { - if (is_dp || (radeon_encoder->pixel_clock <= 165000)) { + if (is_dp || + !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) { if (igp_lane_info & 0x1) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; else if (igp_lane_info & 0x2) @@ -848,7 +833,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { if (dig->coherent_mode) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; - if (radeon_encoder->pixel_clock > 165000) + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; } break; @@ -863,7 +848,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t if (is_dp) args.v2.usPixelClock = cpu_to_le16(dp_clock / 10); - else if (radeon_encoder->pixel_clock > 165000) + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); else args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); @@ -891,7 +876,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { if (dig->coherent_mode) args.v2.acConfig.fCoherentMode = 1; - if (radeon_encoder->pixel_clock > 165000) + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v2.acConfig.fDualLinkConnector = 1; } break; @@ -906,7 +891,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t if (is_dp) args.v3.usPixelClock = cpu_to_le16(dp_clock / 10); - else if (radeon_encoder->pixel_clock > 165000) + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); else args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); @@ -914,7 +899,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t if (is_dp) args.v3.ucLaneNum = dp_lane_count; - else if (radeon_encoder->pixel_clock > 165000) + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v3.ucLaneNum = 8; else args.v3.ucLaneNum = 4; @@ -951,7 +936,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { if (dig->coherent_mode) args.v3.acConfig.fCoherentMode = 1; - if (radeon_encoder->pixel_clock > 165000) + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v3.acConfig.fDualLinkConnector = 1; } break; @@ -966,7 +951,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t if (is_dp) args.v4.usPixelClock = cpu_to_le16(dp_clock / 10); - else if (radeon_encoder->pixel_clock > 165000) + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); else args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); @@ -974,7 +959,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t if (is_dp) args.v4.ucLaneNum = dp_lane_count; - else if (radeon_encoder->pixel_clock > 165000) + else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v4.ucLaneNum = 8; else args.v4.ucLaneNum = 4; @@ -1014,7 +999,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { if (dig->coherent_mode) args.v4.acConfig.fCoherentMode = 1; - if (radeon_encoder->pixel_clock > 165000) + if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v4.acConfig.fDualLinkConnector = 1; } break; @@ -1137,7 +1122,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder, if (dp_clock == 270000) args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; args.v1.sDigEncoder.ucLaneNum = dp_lane_count; - } else if (radeon_encoder->pixel_clock > 165000) + } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v1.sDigEncoder.ucLaneNum = 8; else args.v1.sDigEncoder.ucLaneNum = 4; @@ -1156,7 +1141,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder, else if (dp_clock == 540000) args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; args.v3.sExtEncoder.ucLaneNum = dp_lane_count; - } else if (radeon_encoder->pixel_clock > 165000) + } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) args.v3.sExtEncoder.ucLaneNum = 8; else args.v3.sExtEncoder.ucLaneNum = 4; @@ -1341,7 +1326,8 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) switch (mode) { case DRM_MODE_DPMS_ON: /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730)) + if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || + ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); else atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); @@ -1351,8 +1337,6 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) ATOM_TRANSMITTER_ACTION_POWER_ON); radeon_dig_connector->edp_on = true; } - if (ASIC_IS_DCE4(rdev)) - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); radeon_dp_link_train(encoder, connector); if (ASIC_IS_DCE4(rdev)) atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0); @@ -1363,7 +1347,10 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + else + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (ASIC_IS_DCE4(rdev)) atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); @@ -1810,7 +1797,21 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - if (ASIC_IS_DCE4(rdev)) { + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + + if (!connector) + dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + else + dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); + + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + atombios_dig_encoder_setup(encoder, + ATOM_ENCODER_CMD_SETUP_PANEL_MODE, + dig->panel_mode); + } else if (ASIC_IS_DCE4(rdev)) { /* disable the transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); /* setup and enable the encoder */ diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 636660fca8c2..ae09fe82afbc 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1455,6 +1455,7 @@ int evergreen_cp_resume(struct radeon_device *rdev) #endif WREG32(CP_RB_CNTL, tmp); WREG32(CP_SEM_WAIT_TIMER, 0x0); + WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); /* Set the write pointer delay */ WREG32(CP_RB_WPTR_DELAY, 0); diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index b502216d42af..74713d42df29 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -108,6 +108,7 @@ #define CP_RB_WPTR_ADDR_HI 0xC11C #define CP_RB_WPTR_DELAY 0x8704 #define CP_SEM_WAIT_TIMER 0x85BC +#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 #define CP_DEBUG 0xC1FC diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 321137295400..db09065e68fd 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1219,6 +1219,7 @@ int cayman_cp_resume(struct radeon_device *rdev) RREG32(GRBM_SOFT_RESET); WREG32(CP_SEM_WAIT_TIMER, 0x0); + WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); /* Set the write pointer delay */ WREG32(CP_RB_WPTR_DELAY, 0); diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index f9df2a645e79..9a7f3b6e02de 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -222,6 +222,7 @@ #define SCRATCH_UMSK 0x8540 #define SCRATCH_ADDR 0x8544 #define CP_SEM_WAIT_TIMER 0x85BC +#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 #define CP_COHER_CNTL2 0x85E8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index d996f4381130..accc032c103f 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -468,27 +468,42 @@ set_default_state(struct radeon_device *rdev) radeon_ring_write(ring, sq_stack_resource_mgmt_2); } +#define I2F_MAX_BITS 15 +#define I2F_MAX_INPUT ((1 << I2F_MAX_BITS) - 1) +#define I2F_SHIFT (24 - I2F_MAX_BITS) + +/* + * Converts unsigned integer into 32-bit IEEE floating point representation. + * Conversion is not universal and only works for the range from 0 + * to 2^I2F_MAX_BITS-1. Currently we only use it with inputs between + * 0 and 16384 (inclusive), so I2F_MAX_BITS=15 is enough. If necessary, + * I2F_MAX_BITS can be increased, but that will add to the loop iterations + * and slow us down. Conversion is done by shifting the input and counting + * down until the first 1 reaches bit position 23. The resulting counter + * and the shifted input are, respectively, the exponent and the fraction. + * The sign is always zero. + */ static uint32_t i2f(uint32_t input) { u32 result, i, exponent, fraction; - if ((input & 0x3fff) == 0) - result = 0; /* 0 is a special case */ + WARN_ON_ONCE(input > I2F_MAX_INPUT); + + if ((input & I2F_MAX_INPUT) == 0) + result = 0; else { - exponent = 140; /* exponent biased by 127; */ - fraction = (input & 0x3fff) << 10; /* cheat and only - handle numbers below 2^^15 */ - for (i = 0; i < 14; i++) { + exponent = 126 + I2F_MAX_BITS; + fraction = (input & I2F_MAX_INPUT) << I2F_SHIFT; + + for (i = 0; i < I2F_MAX_BITS; i++) { if (fraction & 0x800000) break; else { - fraction = fraction << 1; /* keep - shifting left until top bit = 1 */ + fraction = fraction << 1; exponent = exponent - 1; } } - result = exponent << 23 | (fraction & 0x7fffff); /* mask - off top bit; assumed 1 */ + result = exponent << 23 | (fraction & 0x7fffff); } return result; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 73e05cb85eca..1668ec1ee770 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -157,6 +157,47 @@ bool radeon_get_bios(struct radeon_device *rdev); /* + * Mutex which allows recursive locking from the same process. + */ +struct radeon_mutex { + struct mutex mutex; + struct task_struct *owner; + int level; +}; + +static inline void radeon_mutex_init(struct radeon_mutex *mutex) +{ + mutex_init(&mutex->mutex); + mutex->owner = NULL; + mutex->level = 0; +} + +static inline void radeon_mutex_lock(struct radeon_mutex *mutex) +{ + if (mutex_trylock(&mutex->mutex)) { + /* The mutex was unlocked before, so it's ours now */ + mutex->owner = current; + } else if (mutex->owner != current) { + /* Another process locked the mutex, take it */ + mutex_lock(&mutex->mutex); + mutex->owner = current; + } + /* Otherwise the mutex was already locked by this process */ + + mutex->level++; +} + +static inline void radeon_mutex_unlock(struct radeon_mutex *mutex) +{ + if (--mutex->level > 0) + return; + + mutex->owner = NULL; + mutex_unlock(&mutex->mutex); +} + + +/* * Dummy page */ struct radeon_dummy_page { @@ -598,7 +639,7 @@ struct radeon_ib { * mutex protects scheduled_ibs, ready, alloc_bm */ struct radeon_ib_pool { - struct mutex mutex; + struct radeon_mutex mutex; struct radeon_sa_manager sa_manager; struct radeon_ib ibs[RADEON_IB_POOL_SIZE]; bool ready; @@ -1355,47 +1396,6 @@ struct r600_vram_scratch { /* - * Mutex which allows recursive locking from the same process. - */ -struct radeon_mutex { - struct mutex mutex; - struct task_struct *owner; - int level; -}; - -static inline void radeon_mutex_init(struct radeon_mutex *mutex) -{ - mutex_init(&mutex->mutex); - mutex->owner = NULL; - mutex->level = 0; -} - -static inline void radeon_mutex_lock(struct radeon_mutex *mutex) -{ - if (mutex_trylock(&mutex->mutex)) { - /* The mutex was unlocked before, so it's ours now */ - mutex->owner = current; - } else if (mutex->owner != current) { - /* Another process locked the mutex, take it */ - mutex_lock(&mutex->mutex); - mutex->owner = current; - } - /* Otherwise the mutex was already locked by this process */ - - mutex->level++; -} - -static inline void radeon_mutex_unlock(struct radeon_mutex *mutex) -{ - if (--mutex->level > 0) - return; - - mutex->owner = NULL; - mutex_unlock(&mutex->mutex); -} - - -/* * Core structure, functions and helpers. */ typedef uint32_t (*radeon_rreg_t)(struct radeon_device*, uint32_t); diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 9d95792bea3e..98724fcb0088 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -58,7 +58,8 @@ static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, } obj = (union acpi_object *)buffer.pointer; - memcpy(bios+offset, obj->buffer.pointer, len); + memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); + len = obj->buffer.length; kfree(buffer.pointer); return len; } diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 229a20f10e2b..501f4881e5aa 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -120,7 +120,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) ret = radeon_atrm_get_bios_chunk(rdev->bios, (i * ATRM_BIOS_PAGE), ATRM_BIOS_PAGE); - if (ret <= 0) + if (ret < ATRM_BIOS_PAGE) break; } diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 0afb13bd8dca..49f7cb7e226b 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -720,7 +720,7 @@ int radeon_device_init(struct radeon_device *rdev, /* mutex initialization are all done here so we * can recall function without having locking issues */ radeon_mutex_init(&rdev->cs_mutex); - mutex_init(&rdev->ib_pool.mutex); + radeon_mutex_init(&rdev->ib_pool.mutex); for (i = 0; i < RADEON_NUM_RINGS; ++i) mutex_init(&rdev->ring[i].mutex); mutex_init(&rdev->dc_hw_i2c_mutex); @@ -883,6 +883,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; + drm_kms_helper_poll_disable(dev); + /* turn off display hw */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); @@ -959,9 +961,11 @@ int radeon_resume_kms(struct drm_device *dev) radeon_fbdev_set_suspend(rdev, 0); console_unlock(); - /* init dig PHYs */ - if (rdev->is_atom_bios) + /* init dig PHYs, disp eng pll */ + if (rdev->is_atom_bios) { radeon_atom_encoder_init(rdev); + radeon_atom_dcpll_init(rdev); + } /* reset hpd state */ radeon_hpd_init(rdev); /* blat the mode back in */ @@ -970,6 +974,8 @@ int radeon_resume_kms(struct drm_device *dev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); } + + drm_kms_helper_poll_enable(dev); return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index d3ffc18774a6..8c49fef1ce78 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1305,9 +1305,11 @@ int radeon_modeset_init(struct radeon_device *rdev) return ret; } - /* init dig PHYs */ - if (rdev->is_atom_bios) + /* init dig PHYs, disp eng pll */ + if (rdev->is_atom_bios) { radeon_atom_encoder_init(rdev); + radeon_atom_dcpll_init(rdev); + } /* initialize hpd */ radeon_hpd_init(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 4b27efa4405b..9419c51bcf50 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -202,6 +202,22 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder) return NULL; } +struct drm_connector * +radeon_get_connector_for_encoder_init(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + radeon_connector = to_radeon_connector(connector); + if (radeon_encoder->devices & radeon_connector->devices) + return connector; + } + return NULL; +} + struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; @@ -288,3 +304,64 @@ void radeon_panel_mode_fixup(struct drm_encoder *encoder, } +bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder, + u32 pixel_clock) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct drm_connector *connector; + struct radeon_connector *radeon_connector; + struct radeon_connector_atom_dig *dig_connector; + + connector = radeon_get_connector_for_encoder(encoder); + /* if we don't have an active device yet, just use one of + * the connectors tied to the encoder. + */ + if (!connector) + connector = radeon_get_connector_for_encoder_init(encoder); + radeon_connector = to_radeon_connector(connector); + + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_HDMIB: + if (radeon_connector->use_digital) { + /* HDMI 1.3 supports up to 340 Mhz over single link */ + if (ASIC_IS_DCE3(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) { + if (pixel_clock > 340000) + return true; + else + return false; + } else { + if (pixel_clock > 165000) + return true; + else + return false; + } + } else + return false; + case DRM_MODE_CONNECTOR_DVID: + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_DisplayPort: + dig_connector = radeon_connector->con_priv; + if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) + return false; + else { + /* HDMI 1.3 supports up to 340 Mhz over single link */ + if (ASIC_IS_DCE3(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) { + if (pixel_clock > 340000) + return true; + else + return false; + } else { + if (pixel_clock > 165000) + return true; + else + return false; + } + } + default: + return false; + } +} + diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 7bb1b079f480..98a8ad680109 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -897,6 +897,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, i2c->rec = *rec; i2c->adapter.owner = THIS_MODULE; i2c->adapter.class = I2C_CLASS_DDC; + i2c->adapter.dev.parent = &dev->pdev->dev; i2c->dev = dev; i2c_set_adapdata(&i2c->adapter, i2c); if (rec->mm_i2c || @@ -957,6 +958,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, i2c->rec = *rec; i2c->adapter.owner = THIS_MODULE; i2c->adapter.class = I2C_CLASS_DDC; + i2c->adapter.dev.parent = &dev->pdev->dev; i2c->dev = dev; snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), "Radeon aux bus %s", name); diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index be38921bf761..66d5fe1c8174 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -138,6 +138,12 @@ static bool radeon_msi_ok(struct radeon_device *rdev) /* Dell RS690 only seems to work with MSIs. */ if ((rdev->pdev->device == 0x791f) && (rdev->pdev->subsystem_vendor == 0x1028) && + (rdev->pdev->subsystem_device == 0x01fc)) + return true; + + /* Dell RS690 only seems to work with MSIs. */ + if ((rdev->pdev->device == 0x791f) && + (rdev->pdev->subsystem_vendor == 0x1028) && (rdev->pdev->subsystem_device == 0x01fd)) return true; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 08ff857c8fd6..4330e3253573 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -362,6 +362,7 @@ struct radeon_encoder_atom_dig { struct backlight_device *bl_dev; int dpms_mode; uint8_t backlight_level; + int panel_mode; }; struct radeon_encoder_atom_dac { @@ -466,6 +467,10 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev); extern struct drm_connector * radeon_get_connector_for_encoder(struct drm_encoder *encoder); +extern struct drm_connector * +radeon_get_connector_for_encoder_init(struct drm_encoder *encoder); +extern bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder, + u32 pixel_clock); extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder); extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector); @@ -482,8 +487,11 @@ extern void radeon_dp_link_train(struct drm_encoder *encoder, extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector); extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector); +extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder, + struct drm_connector *connector); extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode); extern void radeon_atom_encoder_init(struct radeon_device *rdev); +extern void radeon_atom_dcpll_init(struct radeon_device *rdev); extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set); diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index e8bc70933d1b..30a4c5014c8b 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -109,12 +109,12 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, return r; } - mutex_lock(&rdev->ib_pool.mutex); + radeon_mutex_lock(&rdev->ib_pool.mutex); idx = rdev->ib_pool.head_id; retry: if (cretry > 5) { dev_err(rdev->dev, "failed to get an ib after 5 retry\n"); - mutex_unlock(&rdev->ib_pool.mutex); + radeon_mutex_unlock(&rdev->ib_pool.mutex); radeon_fence_unref(&fence); return -ENOMEM; } @@ -139,7 +139,7 @@ retry: */ rdev->ib_pool.head_id = (1 + idx); rdev->ib_pool.head_id &= (RADEON_IB_POOL_SIZE - 1); - mutex_unlock(&rdev->ib_pool.mutex); + radeon_mutex_unlock(&rdev->ib_pool.mutex); return 0; } } @@ -158,7 +158,7 @@ retry: } idx = (idx + 1) & (RADEON_IB_POOL_SIZE - 1); } - mutex_unlock(&rdev->ib_pool.mutex); + radeon_mutex_unlock(&rdev->ib_pool.mutex); radeon_fence_unref(&fence); return r; } @@ -171,12 +171,12 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib) if (tmp == NULL) { return; } - mutex_lock(&rdev->ib_pool.mutex); + radeon_mutex_lock(&rdev->ib_pool.mutex); if (tmp->fence && !tmp->fence->emitted) { radeon_sa_bo_free(rdev, &tmp->sa_bo); radeon_fence_unref(&tmp->fence); } - mutex_unlock(&rdev->ib_pool.mutex); + radeon_mutex_unlock(&rdev->ib_pool.mutex); } int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) @@ -204,22 +204,25 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) int radeon_ib_pool_init(struct radeon_device *rdev) { + struct radeon_sa_manager tmp; int i, r; - mutex_lock(&rdev->ib_pool.mutex); - if (rdev->ib_pool.ready) { - mutex_unlock(&rdev->ib_pool.mutex); - return 0; - } - - r = radeon_sa_bo_manager_init(rdev, &rdev->ib_pool.sa_manager, + r = radeon_sa_bo_manager_init(rdev, &tmp, RADEON_IB_POOL_SIZE*64*1024, RADEON_GEM_DOMAIN_GTT); if (r) { - mutex_unlock(&rdev->ib_pool.mutex); return r; } + radeon_mutex_lock(&rdev->ib_pool.mutex); + if (rdev->ib_pool.ready) { + radeon_mutex_unlock(&rdev->ib_pool.mutex); + radeon_sa_bo_manager_fini(rdev, &tmp); + return 0; + } + + rdev->ib_pool.sa_manager = tmp; + INIT_LIST_HEAD(&rdev->ib_pool.sa_manager.sa_bo); for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { rdev->ib_pool.ibs[i].fence = NULL; rdev->ib_pool.ibs[i].idx = i; @@ -236,7 +239,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev) if (radeon_debugfs_ring_init(rdev)) { DRM_ERROR("Failed to register debugfs file for rings !\n"); } - mutex_unlock(&rdev->ib_pool.mutex); + radeon_mutex_unlock(&rdev->ib_pool.mutex); return 0; } @@ -244,7 +247,7 @@ void radeon_ib_pool_fini(struct radeon_device *rdev) { unsigned i; - mutex_lock(&rdev->ib_pool.mutex); + radeon_mutex_lock(&rdev->ib_pool.mutex); if (rdev->ib_pool.ready) { for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { radeon_sa_bo_free(rdev, &rdev->ib_pool.ibs[i].sa_bo); @@ -253,7 +256,7 @@ void radeon_ib_pool_fini(struct radeon_device *rdev) radeon_sa_bo_manager_fini(rdev, &rdev->ib_pool.sa_manager); rdev->ib_pool.ready = false; } - mutex_unlock(&rdev->ib_pool.mutex); + radeon_mutex_unlock(&rdev->ib_pool.mutex); } int radeon_ib_pool_start(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 06da063ece2e..573220cc5269 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -40,7 +40,6 @@ static struct pci_device_id pciidlist[] = { static int sis_driver_load(struct drm_device *dev, unsigned long chipset) { drm_sis_private_t *dev_priv; - int ret; dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL); if (dev_priv == NULL) @@ -50,7 +49,7 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->chipset = chipset; idr_init(&dev->object_name_idr); - return ret; + return 0; } static int sis_driver_unload(struct drm_device *dev) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 2f0eab66ece6..7c3a57de8187 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -404,6 +404,9 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, } } + if (bdev->driver->move_notify) + bdev->driver->move_notify(bo, mem); + if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) && !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, mem); @@ -413,11 +416,17 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, else ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, mem); - if (ret) - goto out_err; + if (ret) { + if (bdev->driver->move_notify) { + struct ttm_mem_reg tmp_mem = *mem; + *mem = bo->mem; + bo->mem = tmp_mem; + bdev->driver->move_notify(bo, mem); + bo->mem = *mem; + } - if (bdev->driver->move_notify) - bdev->driver->move_notify(bo, mem); + goto out_err; + } moved: if (bo->evicted) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 0af6ebdf205d..b66ef0e3cde1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -378,7 +378,7 @@ int vmw_framebuffer_create_handle(struct drm_framebuffer *fb, unsigned int *handle) { if (handle) - handle = 0; + *handle = 0; return 0; } diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c index 0c33ae9cf0f0..406632472c1b 100644 --- a/drivers/hid/hid-hyperv.c +++ b/drivers/hid/hid-hyperv.c @@ -548,6 +548,7 @@ static int mousevsc_remove(struct hv_device *dev) struct mousevsc_dev *input_dev = hv_get_drvdata(dev); vmbus_close(dev->channel); + hid_hw_stop(input_dev->hid_device); hid_destroy_device(input_dev->hid_device); mousevsc_free_device(input_dev); diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index b47e58b52d9f..acab74cde727 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -531,7 +531,6 @@ static int wacom_probe(struct hid_device *hdev, wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; wdata->battery.use_for_apm = 0; - power_supply_powers(&wdata->battery, &hdev->dev); ret = power_supply_register(&hdev->dev, &wdata->battery); if (ret) { @@ -540,6 +539,8 @@ static int wacom_probe(struct hid_device *hdev, goto err_battery; } + power_supply_powers(&wdata->battery, &hdev->dev); + wdata->ac.properties = wacom_ac_props; wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props); wdata->ac.get_property = wacom_ac_get_property; @@ -547,14 +548,14 @@ static int wacom_probe(struct hid_device *hdev, wdata->ac.type = POWER_SUPPLY_TYPE_MAINS; wdata->ac.use_for_apm = 0; - power_supply_powers(&wdata->battery, &hdev->dev); - ret = power_supply_register(&hdev->dev, &wdata->ac); if (ret) { hid_warn(hdev, "can't create ac battery attribute, err: %d\n", ret); goto err_ac; } + + power_supply_powers(&wdata->ac, &hdev->dev); #endif return 0; diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index fc253b472f9d..cac3589b1ed5 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c @@ -1226,14 +1226,14 @@ static int wiimote_hid_probe(struct hid_device *hdev, wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; wdata->battery.use_for_apm = 0; - power_supply_powers(&wdata->battery, &hdev->dev); - ret = power_supply_register(&wdata->hdev->dev, &wdata->battery); if (ret) { hid_err(hdev, "Cannot register battery device\n"); goto err_battery; } + power_supply_powers(&wdata->battery, &hdev->dev); + ret = wiimote_leds_create(wdata); if (ret) goto err_free; diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 7c297d305d5d..b1ec0e2aeb57 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -922,11 +922,11 @@ void hiddev_disconnect(struct hid_device *hid) struct hiddev *hiddev = hid->hiddev; struct usbhid_device *usbhid = hid->driver_data; + usb_deregister_dev(usbhid->intf, &hiddev_class); + mutex_lock(&hiddev->existancelock); hiddev->exist = 0; - usb_deregister_dev(usbhid->intf, &hiddev_class); - if (hiddev->open) { mutex_unlock(&hiddev->existancelock); usbhid_close(hiddev->hid); diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 92f949767ece..6dbfd3e516e4 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -283,11 +283,11 @@ static inline long temp_from_reg(u8 reg) static inline u8 temp_to_reg(long val) { - if (val < 0) - val = 0; - else if (val > 1000 * 0xff) - val = 0xff; - return ((val + 500) / 1000); + if (val <= 0) + return 0; + if (val >= 1000 * 0xff) + return 0xff; + return (val + 500) / 1000; } /* diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index 6ddeae049058..91fdd1fe18b0 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c @@ -883,7 +883,7 @@ static int sht15_invalidate_voltage(struct notifier_block *nb, static int __devinit sht15_probe(struct platform_device *pdev) { - int ret = 0; + int ret; struct sht15_data *data = kzalloc(sizeof(*data), GFP_KERNEL); u8 status = 0; @@ -901,6 +901,7 @@ static int __devinit sht15_probe(struct platform_device *pdev) init_waitqueue_head(&data->wait_queue); if (pdev->dev.platform_data == NULL) { + ret = -EINVAL; dev_err(&pdev->dev, "no platform data supplied\n"); goto err_free_data; } diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 0e0af0445222..4d383e7e051d 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -1319,6 +1319,7 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, { struct w83627ehf_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + struct w83627ehf_sio_data *sio_data = dev->platform_data; int nr = sensor_attr->index; unsigned long val; int err; @@ -1330,6 +1331,11 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, if (val > 1) return -EINVAL; + + /* On NCT67766F, DC mode is only supported for pwm1 */ + if (sio_data->kind == nct6776 && nr && val != 1) + return -EINVAL; + mutex_lock(&data->update_lock); reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]); data->pwm_mode[nr] = val; @@ -1914,9 +1920,26 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data, fan4min = 0; fan5pin = 0; } else if (sio_data->kind == nct6776) { - fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40); - fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01); - fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02); + bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80; + + superio_select(sio_data->sioreg, W83627EHF_LD_HWM); + regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE); + + if (regval & 0x80) + fan3pin = gpok; + else + fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40); + + if (regval & 0x40) + fan4pin = gpok; + else + fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01); + + if (regval & 0x20) + fan5pin = gpok; + else + fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02); + fan4min = fan4pin; } else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) { fan3pin = 1; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index f713eac55047..801df6000e9b 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1018,7 +1018,7 @@ omap_i2c_probe(struct platform_device *pdev) goto err_release_region; } - match = of_match_device(omap_i2c_of_match, &pdev->dev); + match = of_match_device(of_match_ptr(omap_i2c_of_match), &pdev->dev); if (match) { u32 freq = 100000; /* default to 100000 Hz */ diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 20bce51c2e82..54ab97bae042 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -527,7 +527,7 @@ int intel_idle_cpu_init(int cpu) return 0; } - +EXPORT_SYMBOL_GPL(intel_idle_cpu_init); static int __init intel_idle_init(void) { diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index b37b0c02a7b9..5034a87cc72d 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -808,9 +808,12 @@ static ssize_t ucma_accept(struct ucma_file *file, const char __user *inbuf, return PTR_ERR(ctx); if (cmd.conn_param.valid) { - ctx->uid = cmd.uid; ucma_copy_conn_param(&conn_param, &cmd.conn_param); + mutex_lock(&file->mut); ret = rdma_accept(ctx->cm_id, &conn_param); + if (!ret) + ctx->uid = cmd.uid; + mutex_unlock(&file->mut); } else ret = rdma_accept(ctx->cm_id, NULL); diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index b930da4c0c63..4d27e4c3fe34 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1485,6 +1485,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, qp->event_handler = attr.event_handler; qp->qp_context = attr.qp_context; qp->qp_type = attr.qp_type; + atomic_set(&qp->usecnt, 0); atomic_inc(&pd->usecnt); atomic_inc(&attr.send_cq->usecnt); if (attr.recv_cq) diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 602b1bd723a9..575b78045aaf 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -421,6 +421,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd, qp->uobject = NULL; qp->qp_type = qp_init_attr->qp_type; + atomic_set(&qp->usecnt, 0); if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) { qp->event_handler = __ib_shared_qp_event_handler; qp->qp_context = qp; @@ -430,7 +431,6 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd, qp->xrcd = qp_init_attr->xrcd; atomic_inc(&qp_init_attr->xrcd->usecnt); INIT_LIST_HEAD(&qp->open_list); - atomic_set(&qp->usecnt, 0); real_qp = qp; qp = __ib_open_qp(real_qp, qp_init_attr->event_handler, diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index b7d4216db3c3..a4de9d58e9b4 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -89,7 +89,7 @@ static int create_file(const char *name, umode_t mode, error = ipathfs_mknod(parent->d_inode, *dentry, mode, fops, data); else - error = PTR_ERR(dentry); + error = PTR_ERR(*dentry); mutex_unlock(&parent->d_inode->i_mutex); return error; diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 95c94d8f0254..259b0670b51c 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -257,12 +257,9 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, return IB_MAD_RESULT_SUCCESS; /* - * Don't process SMInfo queries or vendor-specific - * MADs -- the SMA can't handle them. + * Don't process SMInfo queries -- the SMA can't handle them. */ - if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO || - ((in_mad->mad_hdr.attr_id & IB_SMP_ATTR_VENDOR_MASK) == - IB_SMP_ATTR_VENDOR_MASK)) + if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO) return IB_MAD_RESULT_SUCCESS; } else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT || in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS1 || diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 7013da5e9eda..7140199f562e 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. * * This software is available to you under a choice of one of two diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index 568b4f11380a..c438e4691b3c 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. * * This software is available to you under a choice of one of two diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 425065b36b8c..a4972abedef1 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -233,6 +233,7 @@ static int send_mpa_reject(struct nes_cm_node *cm_node) u8 *start_ptr = &start_addr; u8 **start_buff = &start_ptr; u16 buff_len = 0; + struct ietf_mpa_v1 *mpa_frame; skb = dev_alloc_skb(MAX_CM_BUFFER); if (!skb) { @@ -242,6 +243,8 @@ static int send_mpa_reject(struct nes_cm_node *cm_node) /* send an MPA reject frame */ cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY); + mpa_frame = (struct ietf_mpa_v1 *)*start_buff; + mpa_frame->flags |= IETF_MPA_FLAGS_REJECT; form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN); cm_node->state = NES_CM_STATE_FIN_WAIT1; @@ -1360,8 +1363,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi if (!memcmp(nesadapter->arp_table[arpindex].mac_addr, neigh->ha, ETH_ALEN)) { /* Mac address same as in nes_arp_table */ - ip_rt_put(rt); - return rc; + goto out; } nes_manage_arp_cache(nesvnic->netdev, @@ -1377,6 +1379,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi neigh_event_send(neigh, NULL); } } + +out: rcu_read_unlock(); ip_rt_put(rt); return rc; diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index bdfa1fbb35fc..4646e6666087 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_context.h b/drivers/infiniband/hw/nes/nes_context.h index b4393a16099d..a69eef16d72d 100644 --- a/drivers/infiniband/hw/nes/nes_context.h +++ b/drivers/infiniband/hw/nes/nes_context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 055f4b545df0..d42c9f435b1b 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index 0b590e152c6a..d748e4b31b8d 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. +* Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c index b3b2a240c6e9..3ba7be369452 100644 --- a/drivers/infiniband/hw/nes/nes_mgt.c +++ b/drivers/infiniband/hw/nes/nes_mgt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel-NE, Inc. All rights reserved. + * Copyright (c) 2006 - 2011 Intel-NE, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_mgt.h b/drivers/infiniband/hw/nes/nes_mgt.h index 8c8af254555a..4f7f701c4a81 100644 --- a/drivers/infiniband/hw/nes/nes_mgt.h +++ b/drivers/infiniband/hw/nes/nes_mgt.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2010 Intel-NE, Inc. All rights reserved. +* Copyright (c) 2006 - 2011 Intel-NE, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 4b3fa711a247..f3a3ecf8d09e 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_user.h b/drivers/infiniband/hw/nes/nes_user.h index 71e133ab209b..4926de744488 100644 --- a/drivers/infiniband/hw/nes/nes_user.h +++ b/drivers/infiniband/hw/nes/nes_user.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * Copyright (c) 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005 Cisco Systems. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c index 8b4c2ff54888..e98f4fc0b768 100644 --- a/drivers/infiniband/hw/nes/nes_utils.c +++ b/drivers/infiniband/hw/nes/nes_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 5095bc41c6cc..0927b5cc65d3 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -3428,6 +3428,8 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX, ib_wr->wr.fast_reg.length); set_wqe_32bit_value(wqe->wqe_words, + NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0); + set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX, ib_wr->wr.fast_reg.rkey); /* Set page size: */ @@ -3724,7 +3726,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) entry->opcode = IB_WC_SEND; break; case NES_IWARP_SQ_OP_LOCINV: - entry->opcode = IB_WR_LOCAL_INV; + entry->opcode = IB_WC_LOCAL_INV; break; case NES_IWARP_SQ_OP_FAST_REG: entry->opcode = IB_WC_FAST_REG_MR; diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h index fe6b6e92fa90..0eff7c44d76b 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.h +++ b/drivers/infiniband/hw/nes/nes_verbs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. * * This software is available to you under a choice of one of two diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 4f18e2d332df..d0c64d514813 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -2105,7 +2105,7 @@ static void alloc_dummy_hdrq(struct qib_devdata *dd) dd->cspec->dummy_hdrq = dma_alloc_coherent(&dd->pcidev->dev, dd->rcd[0]->rcvhdrq_size, &dd->cspec->dummy_hdrq_phys, - GFP_KERNEL | __GFP_COMP); + GFP_ATOMIC | __GFP_COMP); if (!dd->cspec->dummy_hdrq) { qib_devinfo(dd->pcidev, "Couldn't allocate dummy hdrq\n"); /* fallback to just 0'ing */ diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index f695061d688e..0fde788e1100 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -560,7 +560,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd) * BIOS may not set PCIe bus-utilization parameters for best performance. * Check and optionally adjust them to maximize our throughput. */ -static int qib_pcie_caps = 0x51; +static int qib_pcie_caps; module_param_named(pcie_caps, qib_pcie_caps, int, S_IRUGO); MODULE_PARM_DESC(pcie_caps, "Max PCIe tuning: Payload (0..3), ReadReq (4..7)"); diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 76457d50bc34..afc166fcc3d9 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -386,7 +386,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, struct evdev_client *client = file->private_data; struct evdev *evdev = client->evdev; struct input_event event; - int retval; + int retval = 0; if (count < input_event_size()) return -EINVAL; diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index a588578037eb..67bec14e8b96 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -34,7 +34,6 @@ #include <linux/i2c/twl.h> #include <linux/slab.h> - /* * The TWL4030 family chips include a keypad controller that supports * up to an 8x8 switch matrix. The controller can issue system wakeup @@ -302,7 +301,7 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp) if (twl4030_kpwrite_u8(kp, i, KEYP_DEB) < 0) return -EIO; - /* Set timeout period to 100 ms */ + /* Set timeout period to 200 ms */ i = KEYP_PERIOD_US(200000, PTV_PRESCALER); if (twl4030_kpwrite_u8(kp, (i & 0xFF), KEYP_TIMEOUT_L) < 0) return -EIO; @@ -466,4 +465,3 @@ MODULE_AUTHOR("Texas Instruments"); MODULE_DESCRIPTION("TWL4030 Keypad Driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:twl4030_keypad"); - diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index b4cfc6c8be89..5ec774d6c82b 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -512,6 +512,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"), }, }, + { + /* Lenovo Ideapad U455 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "20046"), + }, + }, { } }; diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 8250299fd64f..4494233d331a 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -164,7 +164,8 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, struct serio_raw_client *client = file->private_data; struct serio_raw *serio_raw = client->serio_raw; char uninitialized_var(c); - ssize_t retval = 0; + ssize_t read = 0; + int retval; if (serio_raw->dead) return -ENODEV; @@ -180,13 +181,15 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, if (serio_raw->dead) return -ENODEV; - while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) { - if (put_user(c, buffer++)) - return -EFAULT; - retval++; + while (read < count && serio_raw_fetch_byte(serio_raw, &c)) { + if (put_user(c, buffer++)) { + retval = -EFAULT; + break; + } + read++; } - return retval; + return read ?: retval; } static ssize_t serio_raw_write(struct file *file, const char __user *buffer, diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 1455e2644ab5..cf0c318d6989 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -887,8 +887,7 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) /* attach demod */ adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach, - &anysee_cxd2820r_config, &adap->dev->i2c_adap, - NULL); + &anysee_cxd2820r_config, &adap->dev->i2c_adap); state->has_ci = true; @@ -1189,6 +1188,14 @@ static int anysee_ci_init(struct dvb_usb_device *d) if (ret) return ret; + ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 2)|(0 << 1)|(0 << 0), 0x07); + if (ret) + return ret; + + ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 2)|(1 << 1)|(1 << 0), 0x07); + if (ret) + return ret; + ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1); if (ret) return ret; diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c index 8a57ed8272de..1efc028a76c9 100644 --- a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c +++ b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c @@ -276,14 +276,15 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe) param.flags = 0; switch (fep->bandwidth_hz) { + default: case 8000000: - param.bandwidth = 0; + param.bandwidth = 8; break; case 7000000: - param.bandwidth = 1; + param.bandwidth = 7; break; case 6000000: - param.bandwidth = 2; + param.bandwidth = 6; break; } diff --git a/drivers/media/dvb/frontends/cxd2820r.h b/drivers/media/dvb/frontends/cxd2820r.h index cf0f546aa1d1..5aa306ebb7ef 100644 --- a/drivers/media/dvb/frontends/cxd2820r.h +++ b/drivers/media/dvb/frontends/cxd2820r.h @@ -77,14 +77,12 @@ struct cxd2820r_config { (defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE)) extern struct dvb_frontend *cxd2820r_attach( const struct cxd2820r_config *config, - struct i2c_adapter *i2c, - struct dvb_frontend *fe + struct i2c_adapter *i2c ); #else static inline struct dvb_frontend *cxd2820r_attach( const struct cxd2820r_config *config, - struct i2c_adapter *i2c, - struct dvb_frontend *fe + struct i2c_adapter *i2c ) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); diff --git a/drivers/media/dvb/frontends/cxd2820r_core.c b/drivers/media/dvb/frontends/cxd2820r_core.c index caae7f79c837..5c7c2aaf9bf5 100644 --- a/drivers/media/dvb/frontends/cxd2820r_core.c +++ b/drivers/media/dvb/frontends/cxd2820r_core.c @@ -482,10 +482,19 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe) /* switch between DVB-T and DVB-T2 when tune fails */ if (priv->last_tune_failed) { - if (priv->delivery_system == SYS_DVBT) + if (priv->delivery_system == SYS_DVBT) { + ret = cxd2820r_sleep_t(fe); + if (ret) + goto error; + c->delivery_system = SYS_DVBT2; - else if (priv->delivery_system == SYS_DVBT2) + } else if (priv->delivery_system == SYS_DVBT2) { + ret = cxd2820r_sleep_t2(fe); + if (ret) + goto error; + c->delivery_system = SYS_DVBT; + } } /* set frontend */ @@ -562,7 +571,7 @@ static const struct dvb_frontend_ops cxd2820r_ops = { .delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A }, /* default: DVB-T/T2 */ .info = { - .name = "Sony CXD2820R (DVB-T/T2)", + .name = "Sony CXD2820R", .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | @@ -572,7 +581,9 @@ static const struct dvb_frontend_ops cxd2820r_ops = { FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_QAM_16 | + FE_CAN_QAM_32 | FE_CAN_QAM_64 | + FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | @@ -602,8 +613,7 @@ static const struct dvb_frontend_ops cxd2820r_ops = { }; struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg, - struct i2c_adapter *i2c, - struct dvb_frontend *fe) + struct i2c_adapter *i2c) { struct cxd2820r_priv *priv = NULL; int ret; diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c index 9fe4519176a4..ec3f6a06f9c3 100644 --- a/drivers/media/video/atmel-isi.c +++ b/drivers/media/video/atmel-isi.c @@ -922,7 +922,9 @@ static int __devexit atmel_isi_remove(struct platform_device *pdev) isi->fb_descriptors_phys); iounmap(isi->regs); + clk_unprepare(isi->mck); clk_put(isi->mck); + clk_unprepare(isi->pclk); clk_put(isi->pclk); kfree(isi); @@ -955,6 +957,10 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev) if (IS_ERR(pclk)) return PTR_ERR(pclk); + ret = clk_prepare(pclk); + if (ret) + goto err_clk_prepare_pclk; + isi = kzalloc(sizeof(struct atmel_isi), GFP_KERNEL); if (!isi) { ret = -ENOMEM; @@ -978,6 +984,10 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev) goto err_clk_get; } + ret = clk_prepare(isi->mck); + if (ret) + goto err_clk_prepare_mck; + /* Set ISI_MCK's frequency, it should be faster than pixel clock */ ret = clk_set_rate(isi->mck, pdata->mck_hz); if (ret < 0) @@ -1059,10 +1069,14 @@ err_alloc_ctx: isi->fb_descriptors_phys); err_alloc_descriptors: err_set_mck_rate: + clk_unprepare(isi->mck); +err_clk_prepare_mck: clk_put(isi->mck); err_clk_get: kfree(isi); err_alloc_isi: + clk_unprepare(pclk); +err_clk_prepare_pclk: clk_put(pclk); return ret; diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 9449423098e0..aabbf4854f66 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -853,8 +853,7 @@ static int em28xx_dvb_init(struct em28xx *dev) case EM28174_BOARD_PCTV_290E: dvb->fe[0] = dvb_attach(cxd2820r_attach, &em28xx_cxd2820r_config, - &dev->i2c_adap, - NULL); + &dev->i2c_adap); if (dvb->fe[0]) { /* FE 0 attach tuner */ if (!dvb_attach(tda18271_attach, diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index 63be60bc3455..86cc3f7841cd 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c @@ -26,35 +26,9 @@ #define to_mcp(d) container_of(d, struct mcp, attached_device) #define to_mcp_driver(d) container_of(d, struct mcp_driver, drv) -static const struct mcp_device_id *mcp_match_id(const struct mcp_device_id *id, - const char *codec) -{ - while (id->name[0]) { - if (strcmp(codec, id->name) == 0) - return id; - id++; - } - return NULL; -} - -const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp) -{ - const struct mcp_driver *driver = - to_mcp_driver(mcp->attached_device.driver); - - return mcp_match_id(driver->id_table, mcp->codec); -} -EXPORT_SYMBOL(mcp_get_device_id); - static int mcp_bus_match(struct device *dev, struct device_driver *drv) { - const struct mcp *mcp = to_mcp(dev); - const struct mcp_driver *driver = to_mcp_driver(drv); - - if (driver->id_table) - return !!mcp_match_id(driver->id_table, mcp->codec); - - return 0; + return 1; } static int mcp_bus_probe(struct device *dev) @@ -100,18 +74,9 @@ static int mcp_bus_resume(struct device *dev) return ret; } -static int mcp_bus_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct mcp *mcp = to_mcp(dev); - - add_uevent_var(env, "MODALIAS=%s%s", MCP_MODULE_PREFIX, mcp->codec); - return 0; -} - static struct bus_type mcp_bus_type = { .name = "mcp", .match = mcp_bus_match, - .uevent = mcp_bus_uevent, .probe = mcp_bus_probe, .remove = mcp_bus_remove, .suspend = mcp_bus_suspend, @@ -128,9 +93,11 @@ static struct bus_type mcp_bus_type = { */ void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div) { - spin_lock_irq(&mcp->lock); + unsigned long flags; + + spin_lock_irqsave(&mcp->lock, flags); mcp->ops->set_telecom_divisor(mcp, div); - spin_unlock_irq(&mcp->lock); + spin_unlock_irqrestore(&mcp->lock, flags); } EXPORT_SYMBOL(mcp_set_telecom_divisor); @@ -143,9 +110,11 @@ EXPORT_SYMBOL(mcp_set_telecom_divisor); */ void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div) { - spin_lock_irq(&mcp->lock); + unsigned long flags; + + spin_lock_irqsave(&mcp->lock, flags); mcp->ops->set_audio_divisor(mcp, div); - spin_unlock_irq(&mcp->lock); + spin_unlock_irqrestore(&mcp->lock, flags); } EXPORT_SYMBOL(mcp_set_audio_divisor); @@ -198,10 +167,11 @@ EXPORT_SYMBOL(mcp_reg_read); */ void mcp_enable(struct mcp *mcp) { - spin_lock_irq(&mcp->lock); + unsigned long flags; + spin_lock_irqsave(&mcp->lock, flags); if (mcp->use_count++ == 0) mcp->ops->enable(mcp); - spin_unlock_irq(&mcp->lock); + spin_unlock_irqrestore(&mcp->lock, flags); } EXPORT_SYMBOL(mcp_enable); @@ -247,14 +217,9 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size) } EXPORT_SYMBOL(mcp_host_alloc); -int mcp_host_register(struct mcp *mcp, void *pdata) +int mcp_host_register(struct mcp *mcp) { - if (!mcp->codec) - return -EINVAL; - - mcp->attached_device.platform_data = pdata; dev_set_name(&mcp->attached_device, "mcp0"); - request_module("%s%s", MCP_MODULE_PREFIX, mcp->codec); return device_register(&mcp->attached_device); } EXPORT_SYMBOL(mcp_host_register); diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c index 9adc2eb69492..02c53a0766c4 100644 --- a/drivers/mfd/mcp-sa11x0.c +++ b/drivers/mfd/mcp-sa11x0.c @@ -19,7 +19,6 @@ #include <linux/spinlock.h> #include <linux/platform_device.h> #include <linux/mfd/mcp.h> -#include <linux/io.h> #include <mach/dma.h> #include <mach/hardware.h> @@ -27,19 +26,12 @@ #include <asm/system.h> #include <mach/mcp.h> -/* Register offsets */ -#define MCCR0 0x00 -#define MCDR0 0x08 -#define MCDR1 0x0C -#define MCDR2 0x10 -#define MCSR 0x18 -#define MCCR1 0x00 +#include <mach/assabet.h> + struct mcp_sa11x0 { - u32 mccr0; - u32 mccr1; - unsigned char *mccr0_base; - unsigned char *mccr1_base; + u32 mccr0; + u32 mccr1; }; #define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp)) @@ -47,25 +39,25 @@ struct mcp_sa11x0 { static void mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor) { - struct mcp_sa11x0 *priv = priv(mcp); + unsigned int mccr0; divisor /= 32; - priv->mccr0 &= ~0x00007f00; - priv->mccr0 |= divisor << 8; - __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0); + mccr0 = Ser4MCCR0 & ~0x00007f00; + mccr0 |= divisor << 8; + Ser4MCCR0 = mccr0; } static void mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor) { - struct mcp_sa11x0 *priv = priv(mcp); + unsigned int mccr0; divisor /= 32; - priv->mccr0 &= ~0x0000007f; - priv->mccr0 |= divisor; - __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0); + mccr0 = Ser4MCCR0 & ~0x0000007f; + mccr0 |= divisor; + Ser4MCCR0 = mccr0; } /* @@ -79,16 +71,12 @@ mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val) { int ret = -ETIME; int i; - u32 mcpreg; - struct mcp_sa11x0 *priv = priv(mcp); - mcpreg = reg << 17 | MCDR2_Wr | (val & 0xffff); - __raw_writel(mcpreg, priv->mccr0_base + MCDR2); + Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff); for (i = 0; i < 2; i++) { udelay(mcp->rw_timeout); - mcpreg = __raw_readl(priv->mccr0_base + MCSR); - if (mcpreg & MCSR_CWC) { + if (Ser4MCSR & MCSR_CWC) { ret = 0; break; } @@ -109,18 +97,13 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) { int ret = -ETIME; int i; - u32 mcpreg; - struct mcp_sa11x0 *priv = priv(mcp); - mcpreg = reg << 17 | MCDR2_Rd; - __raw_writel(mcpreg, priv->mccr0_base + MCDR2); + Ser4MCDR2 = reg << 17 | MCDR2_Rd; for (i = 0; i < 2; i++) { udelay(mcp->rw_timeout); - mcpreg = __raw_readl(priv->mccr0_base + MCSR); - if (mcpreg & MCSR_CRC) { - ret = __raw_readl(priv->mccr0_base + MCDR2) - & 0xffff; + if (Ser4MCSR & MCSR_CRC) { + ret = Ser4MCDR2 & 0xffff; break; } } @@ -133,19 +116,13 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) static void mcp_sa11x0_enable(struct mcp *mcp) { - struct mcp_sa11x0 *priv = priv(mcp); - - __raw_writel(-1, priv->mccr0_base + MCSR); - priv->mccr0 |= MCCR0_MCE; - __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0); + Ser4MCSR = -1; + Ser4MCCR0 |= MCCR0_MCE; } static void mcp_sa11x0_disable(struct mcp *mcp) { - struct mcp_sa11x0 *priv = priv(mcp); - - priv->mccr0 &= ~MCCR0_MCE; - __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0); + Ser4MCCR0 &= ~MCCR0_MCE; } /* @@ -165,69 +142,50 @@ static int mcp_sa11x0_probe(struct platform_device *pdev) struct mcp_plat_data *data = pdev->dev.platform_data; struct mcp *mcp; int ret; - struct mcp_sa11x0 *priv; - struct resource *res_mem0, *res_mem1; - u32 size0, size1; if (!data) return -ENODEV; - if (!data->codec) - return -ENODEV; - - res_mem0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res_mem0) - return -ENODEV; - size0 = res_mem0->end - res_mem0->start + 1; - - res_mem1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res_mem1) - return -ENODEV; - size1 = res_mem1->end - res_mem1->start + 1; - - if (!request_mem_region(res_mem0->start, size0, "sa11x0-mcp")) + if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp")) return -EBUSY; - if (!request_mem_region(res_mem1->start, size1, "sa11x0-mcp")) { - ret = -EBUSY; - goto release; - } - mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0)); if (!mcp) { ret = -ENOMEM; - goto release2; + goto release; } - priv = priv(mcp); - mcp->owner = THIS_MODULE; mcp->ops = &mcp_sa11x0; mcp->sclk_rate = data->sclk_rate; - mcp->dma_audio_rd = DDAR_DevAdd(res_mem0->start + MCDR0) - + DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev; - mcp->dma_audio_wr = DDAR_DevAdd(res_mem0->start + MCDR0) - + DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev; - mcp->dma_telco_rd = DDAR_DevAdd(res_mem0->start + MCDR1) - + DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev; - mcp->dma_telco_wr = DDAR_DevAdd(res_mem0->start + MCDR1) - + DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev; - mcp->codec = data->codec; + mcp->dma_audio_rd = DMA_Ser4MCP0Rd; + mcp->dma_audio_wr = DMA_Ser4MCP0Wr; + mcp->dma_telco_rd = DMA_Ser4MCP1Rd; + mcp->dma_telco_wr = DMA_Ser4MCP1Wr; + mcp->gpio_base = data->gpio_base; platform_set_drvdata(pdev, mcp); + if (machine_is_assabet()) { + ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); + } + + /* + * Setup the PPC unit correctly. + */ + PPDR &= ~PPC_RXD4; + PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; + PSDR |= PPC_RXD4; + PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); + PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); + /* * Initialise device. Note that we initially * set the sampling rate to minimum. */ - priv->mccr0_base = ioremap(res_mem0->start, size0); - priv->mccr1_base = ioremap(res_mem1->start, size1); - - __raw_writel(-1, priv->mccr0_base + MCSR); - priv->mccr1 = data->mccr1; - priv->mccr0 = data->mccr0 | 0x7f7f; - __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0); - __raw_writel(priv->mccr1, priv->mccr1_base + MCCR1); + Ser4MCSR = -1; + Ser4MCCR1 = data->mccr1; + Ser4MCCR0 = data->mccr0 | 0x7f7f; /* * Calculate the read/write timeout (us) from the bit clock @@ -237,53 +195,36 @@ static int mcp_sa11x0_probe(struct platform_device *pdev) mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) / mcp->sclk_rate; - ret = mcp_host_register(mcp, data->codec_pdata); + ret = mcp_host_register(mcp); if (ret == 0) goto out; - release2: - release_mem_region(res_mem1->start, size1); release: - release_mem_region(res_mem0->start, size0); + release_mem_region(0x80060000, 0x60); platform_set_drvdata(pdev, NULL); out: return ret; } -static int mcp_sa11x0_remove(struct platform_device *pdev) +static int mcp_sa11x0_remove(struct platform_device *dev) { - struct mcp *mcp = platform_get_drvdata(pdev); - struct mcp_sa11x0 *priv = priv(mcp); - struct resource *res_mem; - u32 size; + struct mcp *mcp = platform_get_drvdata(dev); - platform_set_drvdata(pdev, NULL); + platform_set_drvdata(dev, NULL); mcp_host_unregister(mcp); + release_mem_region(0x80060000, 0x60); - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res_mem) { - size = res_mem->end - res_mem->start + 1; - release_mem_region(res_mem->start, size); - } - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (res_mem) { - size = res_mem->end - res_mem->start + 1; - release_mem_region(res_mem->start, size); - } - iounmap(priv->mccr0_base); - iounmap(priv->mccr1_base); return 0; } static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state) { struct mcp *mcp = platform_get_drvdata(dev); - struct mcp_sa11x0 *priv = priv(mcp); - u32 mccr0; - mccr0 = priv->mccr0 & ~MCCR0_MCE; - __raw_writel(mccr0, priv->mccr0_base + MCCR0); + priv(mcp)->mccr0 = Ser4MCCR0; + priv(mcp)->mccr1 = Ser4MCCR1; + Ser4MCCR0 &= ~MCCR0_MCE; return 0; } @@ -291,10 +232,9 @@ static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state) static int mcp_sa11x0_resume(struct platform_device *dev) { struct mcp *mcp = platform_get_drvdata(dev); - struct mcp_sa11x0 *priv = priv(mcp); - __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0); - __raw_writel(priv->mccr1, priv->mccr1_base + MCCR1); + Ser4MCCR1 = priv(mcp)->mccr1; + Ser4MCCR0 = priv(mcp)->mccr0; return 0; } @@ -311,7 +251,6 @@ static struct platform_driver mcp_sa11x0_driver = { .resume = mcp_sa11x0_resume, .driver = { .name = "sa11x0-mcp", - .owner = THIS_MODULE, }, }; diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index dda86293dc9f..b2d8e512d3cb 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c @@ -282,6 +282,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) /* Default PLL configuration after power up */ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; twl6040->sysclk = 19200000; + twl6040->mclk = 32768; } else { /* already powered-down */ if (!twl6040->power_count) { @@ -305,6 +306,7 @@ int twl6040_power(struct twl6040 *twl6040, int on) twl6040_power_down(twl6040); } twl6040->sysclk = 0; + twl6040->mclk = 0; } out: @@ -324,23 +326,38 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL); lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL); + /* Force full reconfiguration when switching between PLL */ + if (pll_id != twl6040->pll) { + twl6040->sysclk = 0; + twl6040->mclk = 0; + } + switch (pll_id) { case TWL6040_SYSCLK_SEL_LPPLL: /* low-power PLL divider */ - switch (freq_out) { - case 17640000: - lppllctl |= TWL6040_LPLLFIN; - break; - case 19200000: - lppllctl &= ~TWL6040_LPLLFIN; - break; - default: - dev_err(twl6040->dev, - "freq_out %d not supported\n", freq_out); - ret = -EINVAL; - goto pll_out; + /* Change the sysclk configuration only if it has been canged */ + if (twl6040->sysclk != freq_out) { + switch (freq_out) { + case 17640000: + lppllctl |= TWL6040_LPLLFIN; + break; + case 19200000: + lppllctl &= ~TWL6040_LPLLFIN; + break; + default: + dev_err(twl6040->dev, + "freq_out %d not supported\n", + freq_out); + ret = -EINVAL; + goto pll_out; + } + twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, + lppllctl); } - twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); + + /* The PLL in use has not been change, we can exit */ + if (twl6040->pll == pll_id) + break; switch (freq_in) { case 32768: @@ -371,48 +388,56 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, goto pll_out; } - hppllctl &= ~TWL6040_MCLK_MSK; + if (twl6040->mclk != freq_in) { + hppllctl &= ~TWL6040_MCLK_MSK; + + switch (freq_in) { + case 12000000: + /* PLL enabled, active mode */ + hppllctl |= TWL6040_MCLK_12000KHZ | + TWL6040_HPLLENA; + break; + case 19200000: + /* + * PLL disabled + * (enable PLL if MCLK jitter quality + * doesn't meet specification) + */ + hppllctl |= TWL6040_MCLK_19200KHZ; + break; + case 26000000: + /* PLL enabled, active mode */ + hppllctl |= TWL6040_MCLK_26000KHZ | + TWL6040_HPLLENA; + break; + case 38400000: + /* PLL enabled, active mode */ + hppllctl |= TWL6040_MCLK_38400KHZ | + TWL6040_HPLLENA; + break; + default: + dev_err(twl6040->dev, + "freq_in %d not supported\n", freq_in); + ret = -EINVAL; + goto pll_out; + } - switch (freq_in) { - case 12000000: - /* PLL enabled, active mode */ - hppllctl |= TWL6040_MCLK_12000KHZ | - TWL6040_HPLLENA; - break; - case 19200000: /* - * PLL disabled - * (enable PLL if MCLK jitter quality - * doesn't meet specification) + * enable clock slicer to ensure input waveform is + * square */ - hppllctl |= TWL6040_MCLK_19200KHZ; - break; - case 26000000: - /* PLL enabled, active mode */ - hppllctl |= TWL6040_MCLK_26000KHZ | - TWL6040_HPLLENA; - break; - case 38400000: - /* PLL enabled, active mode */ - hppllctl |= TWL6040_MCLK_38400KHZ | - TWL6040_HPLLENA; - break; - default: - dev_err(twl6040->dev, - "freq_in %d not supported\n", freq_in); - ret = -EINVAL; - goto pll_out; - } + hppllctl |= TWL6040_HPLLSQRENA; - /* enable clock slicer to ensure input waveform is square */ - hppllctl |= TWL6040_HPLLSQRENA; - - twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl); - usleep_range(500, 700); - lppllctl |= TWL6040_HPLLSEL; - twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); - lppllctl &= ~TWL6040_LPLLENA; - twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); + twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, + hppllctl); + usleep_range(500, 700); + lppllctl |= TWL6040_HPLLSEL; + twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, + lppllctl); + lppllctl &= ~TWL6040_LPLLENA; + twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, + lppllctl); + } break; default: dev_err(twl6040->dev, "unknown pll id %d\n", pll_id); @@ -421,6 +446,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id, } twl6040->sysclk = freq_out; + twl6040->mclk = freq_in; twl6040->pll = pll_id; pll_out: diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index 91c4f25e0e55..febc90cdef7e 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -36,15 +36,6 @@ static DEFINE_MUTEX(ucb1x00_mutex); static LIST_HEAD(ucb1x00_drivers); static LIST_HEAD(ucb1x00_devices); -static struct mcp_device_id ucb1x00_id[] = { - { "ucb1x00", 0 }, /* auto-detection */ - { "ucb1200", UCB_ID_1200 }, - { "ucb1300", UCB_ID_1300 }, - { "tc35143", UCB_ID_TC35143 }, - { } -}; -MODULE_DEVICE_TABLE(mcp, ucb1x00_id); - /** * ucb1x00_io_set_dir - set IO direction * @ucb: UCB1x00 structure describing chip @@ -157,16 +148,22 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset { struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); unsigned long flags; + unsigned old, mask = 1 << offset; spin_lock_irqsave(&ucb->io_lock, flags); - ucb->io_dir |= (1 << offset); - ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); - + old = ucb->io_out; if (value) - ucb->io_out |= 1 << offset; + ucb->io_out |= mask; else - ucb->io_out &= ~(1 << offset); - ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); + ucb->io_out &= ~mask; + + if (old != ucb->io_out) + ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); + + if (!(ucb->io_dir & mask)) { + ucb->io_dir |= mask; + ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); + } spin_unlock_irqrestore(&ucb->io_lock, flags); return 0; @@ -536,33 +533,17 @@ static struct class ucb1x00_class = { static int ucb1x00_probe(struct mcp *mcp) { - const struct mcp_device_id *mid; struct ucb1x00 *ucb; struct ucb1x00_driver *drv; - struct ucb1x00_plat_data *pdata; unsigned int id; int ret = -ENODEV; int temp; mcp_enable(mcp); id = mcp_reg_read(mcp, UCB_ID); - mid = mcp_get_device_id(mcp); - if (mid && mid->driver_data) { - if (id != mid->driver_data) { - printk(KERN_WARNING "%s wrong ID %04x found: %04x\n", - mid->name, (unsigned int) mid->driver_data, id); - goto err_disable; - } - } else { - mid = &ucb1x00_id[1]; - while (mid->driver_data) { - if (id == mid->driver_data) - break; - mid++; - } - printk(KERN_WARNING "%s ID not found: %04x\n", - ucb1x00_id[0].name, id); + if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) { + printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); goto err_disable; } @@ -571,28 +552,28 @@ static int ucb1x00_probe(struct mcp *mcp) if (!ucb) goto err_disable; - pdata = mcp->attached_device.platform_data; + ucb->dev.class = &ucb1x00_class; ucb->dev.parent = &mcp->attached_device; - dev_set_name(&ucb->dev, mid->name); + dev_set_name(&ucb->dev, "ucb1x00"); spin_lock_init(&ucb->lock); spin_lock_init(&ucb->io_lock); sema_init(&ucb->adc_sem, 1); - ucb->id = mid; + ucb->id = id; ucb->mcp = mcp; ucb->irq = ucb1x00_detect_irq(ucb); if (ucb->irq == NO_IRQ) { - printk(KERN_ERR "%s: IRQ probe failed\n", mid->name); + printk(KERN_ERR "UCB1x00: IRQ probe failed\n"); ret = -ENODEV; goto err_free; } ucb->gpio.base = -1; - if (pdata && (pdata->gpio_base >= 0)) { + if (mcp->gpio_base != 0) { ucb->gpio.label = dev_name(&ucb->dev); - ucb->gpio.base = pdata->gpio_base; + ucb->gpio.base = mcp->gpio_base; ucb->gpio.ngpio = 10; ucb->gpio.set = ucb1x00_gpio_set; ucb->gpio.get = ucb1x00_gpio_get; @@ -605,10 +586,10 @@ static int ucb1x00_probe(struct mcp *mcp) dev_info(&ucb->dev, "gpio_base not set so no gpiolib support"); ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING, - mid->name, ucb); + "UCB1x00", ucb); if (ret) { - printk(KERN_ERR "%s: unable to grab irq%d: %d\n", - mid->name, ucb->irq, ret); + printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", + ucb->irq, ret); goto err_gpio; } @@ -712,6 +693,7 @@ static int ucb1x00_resume(struct mcp *mcp) struct ucb1x00 *ucb = mcp_get_drvdata(mcp); struct ucb1x00_dev *dev; + ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); mutex_lock(&ucb1x00_mutex); list_for_each_entry(dev, &ucb->devs, dev_node) { @@ -730,7 +712,6 @@ static struct mcp_driver ucb1x00_driver = { .remove = ucb1x00_remove, .suspend = ucb1x00_suspend, .resume = ucb1x00_resume, - .id_table = ucb1x00_id, }; static int __init ucb1x00_init(void) diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 40ec3c118868..63a3cbdfa3f3 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c @@ -47,7 +47,6 @@ struct ucb1x00_ts { u16 x_res; u16 y_res; - unsigned int restart:1; unsigned int adcsync:1; }; @@ -207,15 +206,17 @@ static int ucb1x00_thread(void *_ts) { struct ucb1x00_ts *ts = _ts; DECLARE_WAITQUEUE(wait, current); + bool frozen, ignore = false; int valid = 0; set_freezable(); add_wait_queue(&ts->irq_wait, &wait); - while (!kthread_should_stop()) { + while (!kthread_freezable_should_stop(&frozen)) { unsigned int x, y, p; signed long timeout; - ts->restart = 0; + if (frozen) + ignore = true; ucb1x00_adc_enable(ts->ucb); @@ -258,7 +259,7 @@ static int ucb1x00_thread(void *_ts) * space. We therefore leave it to user space * to do any filtering they please. */ - if (!ts->restart) { + if (!ignore) { ucb1x00_ts_evt_add(ts, p, x, y); valid = 1; } @@ -267,8 +268,6 @@ static int ucb1x00_thread(void *_ts) timeout = HZ / 100; } - try_to_freeze(); - schedule_timeout(timeout); } @@ -340,26 +339,6 @@ static void ucb1x00_ts_close(struct input_dev *idev) ucb1x00_disable(ts->ucb); } -#ifdef CONFIG_PM -static int ucb1x00_ts_resume(struct ucb1x00_dev *dev) -{ - struct ucb1x00_ts *ts = dev->priv; - - if (ts->rtask != NULL) { - /* - * Restart the TS thread to ensure the - * TS interrupt mode is set up again - * after sleep. - */ - ts->restart = 1; - wake_up(&ts->irq_wait); - } - return 0; -} -#else -#define ucb1x00_ts_resume NULL -#endif - /* * Initialisation. @@ -382,7 +361,7 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev) ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; idev->name = "Touchscreen panel"; - idev->id.product = ts->ucb->id->driver_data; + idev->id.product = ts->ucb->id; idev->open = ucb1x00_ts_open; idev->close = ucb1x00_ts_close; @@ -425,7 +404,6 @@ static void ucb1x00_ts_remove(struct ucb1x00_dev *dev) static struct ucb1x00_driver ucb1x00_ts_driver = { .add = ucb1x00_ts_add, .remove = ucb1x00_ts_remove, - .resume = ucb1x00_ts_resume, }; static int __init ucb1x00_ts_init(void) diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 150cd7061b80..28adefe70f96 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -354,6 +354,7 @@ static void lkdtm_do_action(enum ctype which) static void lkdtm_handler(void) { unsigned long flags; + bool do_it = false; spin_lock_irqsave(&count_lock, flags); count--; @@ -361,10 +362,13 @@ static void lkdtm_handler(void) cp_name_to_str(cpoint), cp_type_to_str(cptype), count); if (count == 0) { - lkdtm_do_action(cptype); + do_it = true; count = cpoint_count; } spin_unlock_irqrestore(&count_lock, flags); + + if (do_it) + lkdtm_do_action(cptype); } static int lkdtm_register_cpoint(enum cname which) diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 6ae9ca01388b..9a9ce71a71fc 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -119,7 +119,7 @@ static int mtd_cls_suspend(struct device *dev, pm_message_t state) { struct mtd_info *mtd = dev_get_drvdata(dev); - return mtd_suspend(mtd); + return mtd ? mtd_suspend(mtd) : 0; } static int mtd_cls_resume(struct device *dev) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 4dd056e2e16a..35b4fb55dbd6 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -161,6 +161,37 @@ static int atmel_nand_device_ready(struct mtd_info *mtd) !!host->board->rdy_pin_active_low; } +/* + * Minimal-overhead PIO for data access. + */ +static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + + __raw_readsb(nand_chip->IO_ADDR_R, buf, len); +} + +static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + + __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); +} + +static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + + __raw_writesb(nand_chip->IO_ADDR_W, buf, len); +} + +static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len) +{ + struct nand_chip *nand_chip = mtd->priv; + + __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2); +} + static void dma_complete_func(void *completion) { complete(completion); @@ -235,27 +266,33 @@ err_buf: static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) { struct nand_chip *chip = mtd->priv; + struct atmel_nand_host *host = chip->priv; if (use_dma && len > mtd->oobsize) /* only use DMA for bigger than oob size: better performances */ if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) return; - /* if no DMA operation possible, use PIO */ - memcpy_fromio(buf, chip->IO_ADDR_R, len); + if (host->board->bus_width_16) + atmel_read_buf16(mtd, buf, len); + else + atmel_read_buf8(mtd, buf, len); } static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) { struct nand_chip *chip = mtd->priv; + struct atmel_nand_host *host = chip->priv; if (use_dma && len > mtd->oobsize) /* only use DMA for bigger than oob size: better performances */ if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) return; - /* if no DMA operation possible, use PIO */ - memcpy_toio(chip->IO_ADDR_W, buf, len); + if (host->board->bus_width_16) + atmel_write_buf16(mtd, buf, len); + else + atmel_write_buf8(mtd, buf, len); } /* diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index 7f680420bfab..7db6555ed3ba 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -69,17 +69,19 @@ static int clear_poll_bit(void __iomem *addr, u32 mask) * [1] enable the module. * [2] reset the module. * - * In most of the cases, it's ok. But there is a hardware bug in the BCH block. + * In most of the cases, it's ok. + * But in MX23, there is a hardware bug in the BCH block (see erratum #2847). * If you try to soft reset the BCH block, it becomes unusable until * the next hard reset. This case occurs in the NAND boot mode. When the board * boots by NAND, the ROM of the chip will initialize the BCH blocks itself. * So If the driver tries to reset the BCH again, the BCH will not work anymore. - * You will see a DMA timeout in this case. + * You will see a DMA timeout in this case. The bug has been fixed + * in the following chips, such as MX28. * * To avoid this bug, just add a new parameter `just_enable` for * the mxs_reset_block(), and rewrite it here. */ -int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) +static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) { int ret; int timeout = 0x400; @@ -206,7 +208,15 @@ int bch_set_geometry(struct gpmi_nand_data *this) if (ret) goto err_out; - ret = gpmi_reset_block(r->bch_regs, true); + /* + * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this + * chip, otherwise it will lock up. So we skip resetting BCH on the MX23. + * On the other hand, the MX28 needs the reset, because one case has been + * seen where the BCH produced ECC errors constantly after 10000 + * consecutive reboots. The latter case has not been seen on the MX23 yet, + * still we don't know if it could happen there as well. + */ + ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); if (ret) goto err_out; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 35b4565050f1..8a393f9e6027 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2588,7 +2588,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, instr->state = MTD_ERASING; while (len) { - /* Heck if we have a bad block, we do not erase bad blocks! */ + /* Check if we have a bad block, we do not erase bad blocks! */ if (nand_block_checkbad(mtd, ((loff_t) page) << chip->page_shift, 0, allowbbt)) { pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 342626f4bc46..f820b26b9db3 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -909,16 +909,12 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]) } } -/* hw is a boolean parameter that determines whether we should try and - * set the hw address of the device as well as the hw address of the - * net_device - */ -static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw) +static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[]) { struct net_device *dev = slave->dev; struct sockaddr s_addr; - if (!hw) { + if (slave->bond->params.mode == BOND_MODE_TLB) { memcpy(dev->dev_addr, addr, dev->addr_len); return 0; } @@ -948,8 +944,8 @@ static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct u8 tmp_mac_addr[ETH_ALEN]; memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN); - alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled); - alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled); + alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr); + alb_set_slave_mac_addr(slave2, tmp_mac_addr); } @@ -1096,8 +1092,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav /* Try setting slave mac to bond address and fall-through to code handling that situation below... */ - alb_set_slave_mac_addr(slave, bond->dev->dev_addr, - bond->alb_info.rlb_enabled); + alb_set_slave_mac_addr(slave, bond->dev->dev_addr); } /* The slave's address is equal to the address of the bond. @@ -1133,8 +1128,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav } if (free_mac_slave) { - alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr, - bond->alb_info.rlb_enabled); + alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr); pr_warning("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n", bond->dev->name, slave->dev->name, @@ -1491,8 +1485,7 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave) { int res; - res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr, - bond->alb_info.rlb_enabled); + res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr); if (res) { return res; } @@ -1643,8 +1636,7 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave alb_swap_mac_addr(bond, swap_slave, new_slave); } else { /* set the new_slave to the bond mac address */ - alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr, - bond->alb_info.rlb_enabled); + alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr); } if (swap_slave) { @@ -1704,8 +1696,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave); alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave); } else { - alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr, - bond->alb_info.rlb_enabled); + alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr); read_lock(&bond->lock); alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr); diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 7fc4e81d4d43..325391d19bad 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -9,6 +9,7 @@ */ #include <linux/list.h> +#include <linux/module.h> #include <linux/netdevice.h> #include <linux/phy.h> #include <net/dsa.h> diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c index c0a458fc698f..c17c75b9f531 100644 --- a/drivers/net/dsa/mv88e6123_61_65.c +++ b/drivers/net/dsa/mv88e6123_61_65.c @@ -9,6 +9,7 @@ */ #include <linux/list.h> +#include <linux/module.h> #include <linux/netdevice.h> #include <linux/phy.h> #include <net/dsa.h> @@ -20,12 +21,25 @@ static char *mv88e6123_61_65_probe(struct mii_bus *bus, int sw_addr) ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); if (ret >= 0) { - ret &= 0xfff0; - if (ret == 0x1210) + if (ret == 0x1212) + return "Marvell 88E6123 (A1)"; + if (ret == 0x1213) + return "Marvell 88E6123 (A2)"; + if ((ret & 0xfff0) == 0x1210) return "Marvell 88E6123"; - if (ret == 0x1610) + + if (ret == 0x1612) + return "Marvell 88E6161 (A1)"; + if (ret == 0x1613) + return "Marvell 88E6161 (A2)"; + if ((ret & 0xfff0) == 0x1610) return "Marvell 88E6161"; - if (ret == 0x1650) + + if (ret == 0x1652) + return "Marvell 88E6165 (A1)"; + if (ret == 0x1653) + return "Marvell 88e6165 (A2)"; + if ((ret & 0xfff0) == 0x1650) return "Marvell 88E6165"; } diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index e0eb68243834..55888b06d8b4 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -9,6 +9,7 @@ */ #include <linux/list.h> +#include <linux/module.h> #include <linux/netdevice.h> #include <linux/phy.h> #include <net/dsa.h> diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 5467c040824a..a2c62c2f30ee 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -9,6 +9,7 @@ */ #include <linux/list.h> +#include <linux/module.h> #include <linux/netdevice.h> #include <linux/phy.h> #include <net/dsa.h> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 2b731b253598..03f3935fd8c2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -3117,7 +3117,7 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index) int rx_ring_size = 0; #ifdef BCM_CNIC - if (IS_MF_ISCSI_SD(bp)) { + if (!bp->rx_ring_size && IS_MF_ISCSI_SD(bp)) { rx_ring_size = MIN_RX_SIZE_NONTPA; bp->rx_ring_size = rx_ring_size; } else diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index f99c6e312a5d..31a8b38ab15e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1738,7 +1738,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) struct bnx2x_fp_txdata *txdata = &fp_tx->txdata[0]; u16 tx_start_idx, tx_idx; u16 rx_start_idx, rx_idx; - u16 pkt_prod, bd_prod, rx_comp_cons; + u16 pkt_prod, bd_prod; struct sw_tx_bd *tx_buf; struct eth_tx_start_bd *tx_start_bd; struct eth_tx_parse_bd_e1x *pbd_e1x = NULL; @@ -1873,8 +1873,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) if (rx_idx != rx_start_idx + num_pkts) goto test_loopback_exit; - rx_comp_cons = le16_to_cpu(fp_rx->rx_comp_cons); - cqe = &fp_rx->rx_comp_ring[RCQ_BD(rx_comp_cons)]; + cqe = &fp_rx->rx_comp_ring[RCQ_BD(fp_rx->rx_comp_cons)]; cqe_fp_flags = cqe->fast_path_cqe.type_error_flags; cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE; if (!CQE_TYPE_FAST(cqe_fp_type) || (cqe_fp_flags & ETH_RX_ERROR_FALGS)) @@ -2121,18 +2120,16 @@ static int bnx2x_get_sset_count(struct net_device *dev, int stringset) case ETH_SS_STATS: if (is_multi(bp)) { num_stats = bnx2x_num_stat_queues(bp) * - BNX2X_NUM_Q_STATS; - if (!IS_MF_MODE_STAT(bp)) - num_stats += BNX2X_NUM_STATS; - } else { - if (IS_MF_MODE_STAT(bp)) { - num_stats = 0; - for (i = 0; i < BNX2X_NUM_STATS; i++) - if (IS_FUNC_STAT(i)) - num_stats++; - } else - num_stats = BNX2X_NUM_STATS; - } + BNX2X_NUM_Q_STATS; + } else + num_stats = 0; + if (IS_MF_MODE_STAT(bp)) { + for (i = 0; i < BNX2X_NUM_STATS; i++) + if (IS_FUNC_STAT(i)) + num_stats++; + } else + num_stats += BNX2X_NUM_STATS; + return num_stats; case ETH_SS_TEST: @@ -2151,8 +2148,8 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) switch (stringset) { case ETH_SS_STATS: + k = 0; if (is_multi(bp)) { - k = 0; for_each_eth_queue(bp, i) { memset(queue_name, 0, sizeof(queue_name)); sprintf(queue_name, "%d", i); @@ -2163,20 +2160,17 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) queue_name); k += BNX2X_NUM_Q_STATS; } - if (IS_MF_MODE_STAT(bp)) - break; - for (j = 0; j < BNX2X_NUM_STATS; j++) - strcpy(buf + (k + j)*ETH_GSTRING_LEN, - bnx2x_stats_arr[j].string); - } else { - for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { - if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i)) - continue; - strcpy(buf + j*ETH_GSTRING_LEN, - bnx2x_stats_arr[i].string); - j++; - } } + + + for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { + if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i)) + continue; + strcpy(buf + (k + j)*ETH_GSTRING_LEN, + bnx2x_stats_arr[i].string); + j++; + } + break; case ETH_SS_TEST: @@ -2190,10 +2184,9 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev, { struct bnx2x *bp = netdev_priv(dev); u32 *hw_stats, *offset; - int i, j, k; + int i, j, k = 0; if (is_multi(bp)) { - k = 0; for_each_eth_queue(bp, i) { hw_stats = (u32 *)&bp->fp[i].eth_q_stats; for (j = 0; j < BNX2X_NUM_Q_STATS; j++) { @@ -2214,46 +2207,28 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev, } k += BNX2X_NUM_Q_STATS; } - if (IS_MF_MODE_STAT(bp)) - return; - hw_stats = (u32 *)&bp->eth_stats; - for (j = 0; j < BNX2X_NUM_STATS; j++) { - if (bnx2x_stats_arr[j].size == 0) { - /* skip this counter */ - buf[k + j] = 0; - continue; - } - offset = (hw_stats + bnx2x_stats_arr[j].offset); - if (bnx2x_stats_arr[j].size == 4) { - /* 4-byte counter */ - buf[k + j] = (u64) *offset; - continue; - } - /* 8-byte counter */ - buf[k + j] = HILO_U64(*offset, *(offset + 1)); + } + + hw_stats = (u32 *)&bp->eth_stats; + for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { + if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i)) + continue; + if (bnx2x_stats_arr[i].size == 0) { + /* skip this counter */ + buf[k + j] = 0; + j++; + continue; } - } else { - hw_stats = (u32 *)&bp->eth_stats; - for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { - if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i)) - continue; - if (bnx2x_stats_arr[i].size == 0) { - /* skip this counter */ - buf[j] = 0; - j++; - continue; - } - offset = (hw_stats + bnx2x_stats_arr[i].offset); - if (bnx2x_stats_arr[i].size == 4) { - /* 4-byte counter */ - buf[j] = (u64) *offset; - j++; - continue; - } - /* 8-byte counter */ - buf[j] = HILO_U64(*offset, *(offset + 1)); + offset = (hw_stats + bnx2x_stats_arr[i].offset); + if (bnx2x_stats_arr[i].size == 4) { + /* 4-byte counter */ + buf[k + j] = (u64) *offset; j++; + continue; } + /* 8-byte counter */ + buf[k + j] = HILO_U64(*offset, *(offset + 1)); + j++; } } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index ffeaaa95ed96..1e3f978ee6da 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -941,7 +941,7 @@ void bnx2x_panic_dump(struct bnx2x *bp) struct sw_rx_bd *sw_bd = &fp->rx_buf_ring[j]; BNX2X_ERR("fp%d: rx_bd[%x]=[%x:%x] sw_bd=[%p]\n", - i, j, rx_bd[1], rx_bd[0], sw_bd->skb); + i, j, rx_bd[1], rx_bd[0], sw_bd->data); } start = RX_SGE(fp->rx_sge_prod); @@ -10536,6 +10536,9 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, { struct bnx2x *bp; int rc; + bool chip_is_e1x = (board_type == BCM57710 || + board_type == BCM57711 || + board_type == BCM57711E); SET_NETDEV_DEV(dev, &pdev->dev); bp = netdev_priv(dev); @@ -10624,7 +10627,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0, 0); REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0, 0); - if (CHIP_IS_E1x(bp)) { + if (chip_is_e1x) { REG_WR(bp, PXP2_REG_PGL_ADDR_88_F1, 0); REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F1, 0); REG_WR(bp, PXP2_REG_PGL_ADDR_90_F1, 0); @@ -10635,9 +10638,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, * Enable internal target-read (in case we are probed after PF FLR). * Must be done prior to any BAR read access. Only for 57712 and up */ - if (board_type != BCM57710 && - board_type != BCM57711 && - board_type != BCM57711E) + if (!chip_is_e1x) REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); /* Reset the load counter */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 5ac616093f9f..cb6339c35571 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -50,6 +50,7 @@ static inline void bnx2x_exe_queue_init(struct bnx2x *bp, int exe_len, union bnx2x_qable_obj *owner, exe_q_validate validate, + exe_q_remove remove, exe_q_optimize optimize, exe_q_execute exec, exe_q_get get) @@ -66,6 +67,7 @@ static inline void bnx2x_exe_queue_init(struct bnx2x *bp, /* Owner specific callbacks */ o->validate = validate; + o->remove = remove; o->optimize = optimize; o->execute = exec; o->get = get; @@ -1340,6 +1342,35 @@ static int bnx2x_validate_vlan_mac(struct bnx2x *bp, } } +static int bnx2x_remove_vlan_mac(struct bnx2x *bp, + union bnx2x_qable_obj *qo, + struct bnx2x_exeq_elem *elem) +{ + int rc = 0; + + /* If consumption wasn't required, nothing to do */ + if (test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT, + &elem->cmd_data.vlan_mac.vlan_mac_flags)) + return 0; + + switch (elem->cmd_data.vlan_mac.cmd) { + case BNX2X_VLAN_MAC_ADD: + case BNX2X_VLAN_MAC_MOVE: + rc = qo->vlan_mac.put_credit(&qo->vlan_mac); + break; + case BNX2X_VLAN_MAC_DEL: + rc = qo->vlan_mac.get_credit(&qo->vlan_mac); + break; + default: + return -EINVAL; + } + + if (rc != true) + return -EINVAL; + + return 0; +} + /** * bnx2x_wait_vlan_mac - passivly wait for 5 seconds until all work completes. * @@ -1801,8 +1832,14 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp, list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) { if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags == - *vlan_mac_flags) + *vlan_mac_flags) { + rc = exeq->remove(bp, exeq->owner, exeq_pos); + if (rc) { + BNX2X_ERR("Failed to remove command\n"); + return rc; + } list_del(&exeq_pos->link); + } } spin_unlock_bh(&exeq->lock); @@ -1908,6 +1945,7 @@ void bnx2x_init_mac_obj(struct bnx2x *bp, bnx2x_exe_queue_init(bp, &mac_obj->exe_queue, 1, qable_obj, bnx2x_validate_vlan_mac, + bnx2x_remove_vlan_mac, bnx2x_optimize_vlan_mac, bnx2x_execute_vlan_mac, bnx2x_exeq_get_mac); @@ -1924,6 +1962,7 @@ void bnx2x_init_mac_obj(struct bnx2x *bp, bnx2x_exe_queue_init(bp, &mac_obj->exe_queue, CLASSIFY_RULES_COUNT, qable_obj, bnx2x_validate_vlan_mac, + bnx2x_remove_vlan_mac, bnx2x_optimize_vlan_mac, bnx2x_execute_vlan_mac, bnx2x_exeq_get_mac); @@ -1963,6 +2002,7 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp, bnx2x_exe_queue_init(bp, &vlan_obj->exe_queue, CLASSIFY_RULES_COUNT, qable_obj, bnx2x_validate_vlan_mac, + bnx2x_remove_vlan_mac, bnx2x_optimize_vlan_mac, bnx2x_execute_vlan_mac, bnx2x_exeq_get_vlan); @@ -2009,6 +2049,7 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp, bnx2x_exe_queue_init(bp, &vlan_mac_obj->exe_queue, 1, qable_obj, bnx2x_validate_vlan_mac, + bnx2x_remove_vlan_mac, bnx2x_optimize_vlan_mac, bnx2x_execute_vlan_mac, bnx2x_exeq_get_vlan_mac); @@ -2025,6 +2066,7 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp, &vlan_mac_obj->exe_queue, CLASSIFY_RULES_COUNT, qable_obj, bnx2x_validate_vlan_mac, + bnx2x_remove_vlan_mac, bnx2x_optimize_vlan_mac, bnx2x_execute_vlan_mac, bnx2x_exeq_get_vlan_mac); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h index 992308ff82e8..66da39f0c84a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h @@ -161,6 +161,10 @@ typedef int (*exe_q_validate)(struct bnx2x *bp, union bnx2x_qable_obj *o, struct bnx2x_exeq_elem *elem); +typedef int (*exe_q_remove)(struct bnx2x *bp, + union bnx2x_qable_obj *o, + struct bnx2x_exeq_elem *elem); + /** * @return positive is entry was optimized, 0 - if not, negative * in case of an error. @@ -203,11 +207,18 @@ struct bnx2x_exe_queue_obj { */ exe_q_validate validate; + /** + * Called before removing pending commands, cleaning allocated + * resources (e.g., credits from validate) + */ + exe_q_remove remove; /** * This will try to cancel the current pending commands list * considering the new command. * + * Returns the number of optimized commands or a negative error code + * * Must run under exe_queue->lock */ exe_q_optimize optimize; diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index d529af99157d..a1f2e0fed78b 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -6667,14 +6667,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) iph = ip_hdr(skb); tcp_opt_len = tcp_optlen(skb); - if (skb_is_gso_v6(skb)) { - hdr_len = skb_headlen(skb) - ETH_HLEN; - } else { - u32 ip_tcp_len; - - ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr); - hdr_len = ip_tcp_len + tcp_opt_len; + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN; + if (!skb_is_gso_v6(skb)) { iph->check = 0; iph->tot_len = htons(mss + hdr_len); } diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h index fe0c29acdbe6..ee93a2087fe6 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -32,7 +32,7 @@ #define DRV_NAME "enic" #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" -#define DRV_VERSION "2.1.1.28" +#define DRV_VERSION "2.1.1.31" #define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc" #define ENIC_BARS_MAX 6 diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 2fd9db4b1be5..ab3f67f980d8 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -57,11 +57,13 @@ #define PCI_DEVICE_ID_CISCO_VIC_ENET 0x0043 /* ethernet vnic */ #define PCI_DEVICE_ID_CISCO_VIC_ENET_DYN 0x0044 /* enet dynamic vnic */ +#define PCI_DEVICE_ID_CISCO_VIC_ENET_VF 0x0071 /* enet SRIOV VF */ /* Supported devices */ static DEFINE_PCI_DEVICE_TABLE(enic_id_table) = { { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) }, { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_DYN) }, + { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) }, { 0, } /* end of table */ }; @@ -132,6 +134,11 @@ int enic_sriov_enabled(struct enic *enic) return (enic->priv_flags & ENIC_SRIOV_ENABLED) ? 1 : 0; } +static int enic_is_sriov_vf(struct enic *enic) +{ + return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_VF; +} + int enic_is_valid_vf(struct enic *enic, int vf) { #ifdef CONFIG_PCI_IOV @@ -437,7 +444,7 @@ static void enic_mtu_check(struct enic *enic) if (mtu && mtu != enic->port_mtu) { enic->port_mtu = mtu; - if (enic_is_dynamic(enic)) { + if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) { mtu = max_t(int, ENIC_MIN_MTU, min_t(int, ENIC_MAX_MTU, mtu)); if (mtu != netdev->mtu) @@ -849,7 +856,7 @@ static int enic_set_mac_addr(struct net_device *netdev, char *addr) { struct enic *enic = netdev_priv(netdev); - if (enic_is_dynamic(enic)) { + if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) { if (!is_valid_ether_addr(addr) && !is_zero_ether_addr(addr)) return -EADDRNOTAVAIL; } else { @@ -1608,7 +1615,7 @@ static int enic_open(struct net_device *netdev) for (i = 0; i < enic->rq_count; i++) vnic_rq_enable(&enic->rq[i]); - if (!enic_is_dynamic(enic)) + if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic)) enic_dev_add_station_addr(enic); enic_set_rx_mode(netdev); @@ -1659,7 +1666,7 @@ static int enic_stop(struct net_device *netdev) netif_carrier_off(netdev); netif_tx_disable(netdev); - if (!enic_is_dynamic(enic)) + if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic)) enic_dev_del_station_addr(enic); for (i = 0; i < enic->wq_count; i++) { @@ -1696,7 +1703,7 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu) if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU) return -EINVAL; - if (enic_is_dynamic(enic)) + if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) return -EOPNOTSUPP; if (running) @@ -2263,10 +2270,10 @@ static int __devinit enic_probe(struct pci_dev *pdev, int using_dac = 0; unsigned int i; int err; - int num_pps = 1; #ifdef CONFIG_PCI_IOV int pos = 0; #endif + int num_pps = 1; /* Allocate net device structure and initialize. Private * instance data is initialized to zero. @@ -2376,14 +2383,14 @@ static int __devinit enic_probe(struct pci_dev *pdev, num_pps = enic->num_vfs; } } - #endif + /* Allocate structure for port profiles */ enic->pp = kcalloc(num_pps, sizeof(*enic->pp), GFP_KERNEL); if (!enic->pp) { pr_err("port profile alloc failed, aborting\n"); err = -ENOMEM; - goto err_out_disable_sriov; + goto err_out_disable_sriov_pp; } /* Issue device open to get device in known state @@ -2392,7 +2399,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, err = enic_dev_open(enic); if (err) { dev_err(dev, "vNIC dev open failed, aborting\n"); - goto err_out_free_pp; + goto err_out_disable_sriov; } /* Setup devcmd lock @@ -2426,7 +2433,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, * called later by an upper layer. */ - if (!enic_is_dynamic(enic)) { + if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic)) { err = vnic_dev_init(enic->vdev, 0); if (err) { dev_err(dev, "vNIC dev init failed, aborting\n"); @@ -2460,8 +2467,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, (void)enic_change_mtu(netdev, enic->port_mtu); #ifdef CONFIG_PCI_IOV - if (enic_is_dynamic(enic) && pdev->is_virtfn && - is_zero_ether_addr(enic->mac_addr)) + if (enic_is_sriov_vf(enic) && is_zero_ether_addr(enic->mac_addr)) random_ether_addr(enic->mac_addr); #endif @@ -2474,7 +2480,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, enic->tx_coalesce_usecs = enic->config.intr_timer_usec; enic->rx_coalesce_usecs = enic->tx_coalesce_usecs; - if (enic_is_dynamic(enic)) + if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) netdev->netdev_ops = &enic_netdev_dynamic_ops; else netdev->netdev_ops = &enic_netdev_ops; @@ -2516,17 +2522,17 @@ err_out_dev_deinit: enic_dev_deinit(enic); err_out_dev_close: vnic_dev_close(enic->vdev); -err_out_free_pp: - kfree(enic->pp); err_out_disable_sriov: + kfree(enic->pp); +err_out_disable_sriov_pp: #ifdef CONFIG_PCI_IOV if (enic_sriov_enabled(enic)) { pci_disable_sriov(pdev); enic->priv_flags &= ~ENIC_SRIOV_ENABLED; } err_out_vnic_unregister: - vnic_dev_unregister(enic->vdev); #endif + vnic_dev_unregister(enic->vdev); err_out_iounmap: enic_iounmap(enic); err_out_release_regions: diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index a6bcdb5cd2be..e703d64434f8 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1786,8 +1786,7 @@ static void be_rx_queues_destroy(struct be_adapter *adapter) static u32 be_num_rxqs_want(struct be_adapter *adapter) { if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && - !sriov_enabled(adapter) && be_physfn(adapter) && - !be_is_mc(adapter)) { + !sriov_enabled(adapter) && be_physfn(adapter)) { return 1 + MAX_RSS_QS; /* one default non-RSS queue */ } else { dev_warn(&adapter->pdev->dev, diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index fb5579a3b19d..47f85c337cf7 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -25,6 +25,7 @@ #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> #include <linux/netdevice.h> diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c index a127cb2476c7..bb336a0959c9 100644 --- a/drivers/net/ethernet/faraday/ftmac100.c +++ b/drivers/net/ethernet/faraday/ftmac100.c @@ -25,6 +25,7 @@ #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/io.h> #include <linux/mii.h> #include <linux/module.h> diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile index c6e4621b6262..6565c463185c 100644 --- a/drivers/net/ethernet/intel/igb/Makefile +++ b/drivers/net/ethernet/intel/igb/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # Intel 82575 PCI-Express Ethernet Linux driver -# Copyright(c) 1999 - 2011 Intel Corporation. +# Copyright(c) 1999 - 2012 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index b8e20f037d0a..08bdc33715ee 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h index 08a757eb6608..b927d79ab536 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.h +++ b/drivers/net/ethernet/intel/igb/e1000_82575.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h index f5fc5725ea94..aed217449f0d 100644 --- a/drivers/net/ethernet/intel/igb/e1000_defines.h +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h index 4519a1367170..f67cbd3fa307 100644 --- a/drivers/net/ethernet/intel/igb/e1000_hw.h +++ b/drivers/net/ethernet/intel/igb/e1000_hw.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c index 73aac082c44d..f57338afd71f 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.c +++ b/drivers/net/ethernet/intel/igb/e1000_mac.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -151,7 +151,7 @@ void igb_clear_vfta_i350(struct e1000_hw *hw) * Writes value at the given offset in the register array which stores * the VLAN filter table. **/ -void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value) +static void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value) { int i; diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.h b/drivers/net/ethernet/intel/igb/e1000_mac.h index e45996b4ea34..cbddc4e51e30 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.h +++ b/drivers/net/ethernet/intel/igb/e1000_mac.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/e1000_mbx.c b/drivers/net/ethernet/intel/igb/e1000_mbx.c index 469d95eaa154..5988b8958baf 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mbx.c +++ b/drivers/net/ethernet/intel/igb/e1000_mbx.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/e1000_mbx.h b/drivers/net/ethernet/intel/igb/e1000_mbx.h index eddb0f83dcea..dbcfa3d5caec 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mbx.h +++ b/drivers/net/ethernet/intel/igb/e1000_mbx.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.c b/drivers/net/ethernet/intel/igb/e1000_nvm.c index 40407124e722..fa2c6ba62139 100644 --- a/drivers/net/ethernet/intel/igb/e1000_nvm.c +++ b/drivers/net/ethernet/intel/igb/e1000_nvm.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.h b/drivers/net/ethernet/intel/igb/e1000_nvm.h index a2a7ca9fa733..825b0228cac0 100644 --- a/drivers/net/ethernet/intel/igb/e1000_nvm.h +++ b/drivers/net/ethernet/intel/igb/e1000_nvm.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2011 Intel Corporation. + Copyright(c) 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c index b17d7c20f817..789de5b83aad 100644 --- a/drivers/net/ethernet/intel/igb/e1000_phy.c +++ b/drivers/net/ethernet/intel/igb/e1000_phy.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h index 8510797b9d81..4c32ac66ff39 100644 --- a/drivers/net/ethernet/intel/igb/e1000_phy.h +++ b/drivers/net/ethernet/intel/igb/e1000_phy.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h index 0a860bc1198e..ccdf36d503fd 100644 --- a/drivers/net/ethernet/intel/igb/e1000_regs.h +++ b/drivers/net/ethernet/intel/igb/e1000_regs.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 3d12e67eebb4..8e33bdd33eea 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index 7998bf4d5946..aa399a8a8f0d 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 01e5e89ef959..e91d73c8aa4e 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2011 Intel Corporation. + Copyright(c) 2007-2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -68,7 +68,7 @@ char igb_driver_name[] = "igb"; char igb_driver_version[] = DRV_VERSION; static const char igb_driver_string[] = "Intel(R) Gigabit Ethernet Network Driver"; -static const char igb_copyright[] = "Copyright (c) 2007-2011 Intel Corporation."; +static const char igb_copyright[] = "Copyright (c) 2007-2012 Intel Corporation."; static const struct e1000_info *igb_info_tbl[] = { [board_82575] = &e1000_82575_info, @@ -4003,8 +4003,8 @@ set_itr_now: } } -void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens, - u32 type_tucmd, u32 mss_l4len_idx) +static void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens, + u32 type_tucmd, u32 mss_l4len_idx) { struct e1000_adv_tx_context_desc *context_desc; u16 i = tx_ring->next_to_use; @@ -5623,7 +5623,7 @@ static irqreturn_t igb_intr(int irq, void *data) return IRQ_HANDLED; } -void igb_ring_irq_enable(struct igb_q_vector *q_vector) +static void igb_ring_irq_enable(struct igb_q_vector *q_vector) { struct igb_adapter *adapter = q_vector->adapter; struct e1000_hw *hw = &adapter->hw; diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c index 7b600a1f6366..2dba53446064 100644 --- a/drivers/net/ethernet/intel/igbvf/ethtool.c +++ b/drivers/net/ethernet/intel/igbvf/ethtool.c @@ -468,6 +468,5 @@ static const struct ethtool_ops igbvf_ethtool_ops = { void igbvf_set_ethtool_ops(struct net_device *netdev) { - /* have to "undeclare" const on this struct to remove warnings */ - SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igbvf_ethtool_ops); + SET_ETHTOOL_OPS(netdev, &igbvf_ethtool_ops); } diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index fd3da3076c2f..a4b20c865759 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -1194,11 +1194,6 @@ static int igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) struct igbvf_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - igbvf_irq_disable(adapter); - - if (!test_bit(__IGBVF_DOWN, &adapter->state)) - igbvf_irq_enable(adapter); - if (hw->mac.ops.set_vfta(hw, vid, false)) { dev_err(&adapter->pdev->dev, "Failed to remove vlan id %d\n", vid); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 802bfa0f62cc..775602ef90e5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -161,19 +161,19 @@ /* Receive DMA Registers */ #define IXGBE_RDBAL(_i) (((_i) < 64) ? (0x01000 + ((_i) * 0x40)) : \ - (0x0D000 + ((_i - 64) * 0x40))) + (0x0D000 + (((_i) - 64) * 0x40))) #define IXGBE_RDBAH(_i) (((_i) < 64) ? (0x01004 + ((_i) * 0x40)) : \ - (0x0D004 + ((_i - 64) * 0x40))) + (0x0D004 + (((_i) - 64) * 0x40))) #define IXGBE_RDLEN(_i) (((_i) < 64) ? (0x01008 + ((_i) * 0x40)) : \ - (0x0D008 + ((_i - 64) * 0x40))) + (0x0D008 + (((_i) - 64) * 0x40))) #define IXGBE_RDH(_i) (((_i) < 64) ? (0x01010 + ((_i) * 0x40)) : \ - (0x0D010 + ((_i - 64) * 0x40))) + (0x0D010 + (((_i) - 64) * 0x40))) #define IXGBE_RDT(_i) (((_i) < 64) ? (0x01018 + ((_i) * 0x40)) : \ - (0x0D018 + ((_i - 64) * 0x40))) + (0x0D018 + (((_i) - 64) * 0x40))) #define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : \ - (0x0D028 + ((_i - 64) * 0x40))) + (0x0D028 + (((_i) - 64) * 0x40))) #define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \ - (0x0D02C + ((_i - 64) * 0x40))) + (0x0D02C + (((_i) - 64) * 0x40))) #define IXGBE_RSCDBU 0x03028 #define IXGBE_RDDCC 0x02F20 #define IXGBE_RXMEMWRAP 0x03190 @@ -186,7 +186,7 @@ */ #define IXGBE_SRRCTL(_i) (((_i) <= 15) ? (0x02100 + ((_i) * 4)) : \ (((_i) < 64) ? (0x01014 + ((_i) * 0x40)) : \ - (0x0D014 + ((_i - 64) * 0x40)))) + (0x0D014 + (((_i) - 64) * 0x40)))) /* * Rx DCA Control Register: * 00-15 : 0x02200 + n*4 @@ -195,7 +195,7 @@ */ #define IXGBE_DCA_RXCTRL(_i) (((_i) <= 15) ? (0x02200 + ((_i) * 4)) : \ (((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \ - (0x0D00C + ((_i - 64) * 0x40)))) + (0x0D00C + (((_i) - 64) * 0x40)))) #define IXGBE_RDRXCTL 0x02F00 #define IXGBE_RXPBSIZE(_i) (0x03C00 + ((_i) * 4)) /* 8 of these 0x03C00 - 0x03C1C */ @@ -344,9 +344,9 @@ #define IXGBE_WUPL 0x05900 #define IXGBE_WUPM 0x05A00 /* wake up pkt memory 0x5A00-0x5A7C */ -#define IXGBE_FHFT(_n) (0x09000 + (_n * 0x100)) /* Flex host filter table */ -#define IXGBE_FHFT_EXT(_n) (0x09800 + (_n * 0x100)) /* Ext Flexible Host - * Filter Table */ +#define IXGBE_FHFT(_n) (0x09000 + ((_n) * 0x100)) /* Flex host filter table */ +#define IXGBE_FHFT_EXT(_n) (0x09800 + ((_n) * 0x100)) /* Ext Flexible Host + * Filter Table */ #define IXGBE_FLEXIBLE_FILTER_COUNT_MAX 4 #define IXGBE_EXT_FLEXIBLE_FILTER_COUNT_MAX 2 @@ -1485,7 +1485,7 @@ enum { #define IXGBE_LED_BLINK_BASE 0x00000080 #define IXGBE_LED_MODE_MASK_BASE 0x0000000F #define IXGBE_LED_OFFSET(_base, _i) (_base << (8 * (_i))) -#define IXGBE_LED_MODE_SHIFT(_i) (8*(_i)) +#define IXGBE_LED_MODE_SHIFT(_i) (8 * (_i)) #define IXGBE_LED_IVRT(_i) IXGBE_LED_OFFSET(IXGBE_LED_IVRT_BASE, _i) #define IXGBE_LED_BLINK(_i) IXGBE_LED_OFFSET(IXGBE_LED_BLINK_BASE, _i) #define IXGBE_LED_MODE_MASK(_i) IXGBE_LED_OFFSET(IXGBE_LED_MODE_MASK_BASE, _i) @@ -2068,9 +2068,9 @@ enum { /* SR-IOV specific macros */ #define IXGBE_MBVFICR_INDEX(vf_number) (vf_number >> 4) -#define IXGBE_MBVFICR(_i) (0x00710 + (_i * 4)) -#define IXGBE_VFLRE(_i) (((_i & 1) ? 0x001C0 : 0x00600)) -#define IXGBE_VFLREC(_i) (0x00700 + (_i * 4)) +#define IXGBE_MBVFICR(_i) (0x00710 + ((_i) * 4)) +#define IXGBE_VFLRE(_i) ((((_i) & 1) ? 0x001C0 : 0x00600)) +#define IXGBE_VFLREC(_i) (0x00700 + ((_i) * 4)) enum ixgbe_fdir_pballoc_type { IXGBE_FDIR_PBALLOC_NONE = 0, diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c index dc8e6511c640..c85700318147 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c +++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c @@ -56,7 +56,8 @@ struct ixgbe_stats { offsetof(struct ixgbevf_adapter, m), \ offsetof(struct ixgbevf_adapter, b), \ offsetof(struct ixgbevf_adapter, r) -static struct ixgbe_stats ixgbe_gstrings_stats[] = { + +static const struct ixgbe_stats ixgbe_gstrings_stats[] = { {"rx_packets", IXGBEVF_STAT(stats.vfgprc, stats.base_vfgprc, stats.saved_reset_vfgprc)}, {"tx_packets", IXGBEVF_STAT(stats.vfgptc, stats.base_vfgptc, @@ -671,7 +672,7 @@ static int ixgbevf_nway_reset(struct net_device *netdev) return 0; } -static struct ethtool_ops ixgbevf_ethtool_ops = { +static const struct ethtool_ops ixgbevf_ethtool_ops = { .get_settings = ixgbevf_get_settings, .get_drvinfo = ixgbevf_get_drvinfo, .get_regs_len = ixgbevf_get_regs_len, diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index e6c9d1a927a9..9075c1d61039 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -279,12 +279,12 @@ enum ixgbevf_boards { board_X540_vf, }; -extern struct ixgbevf_info ixgbevf_82599_vf_info; -extern struct ixgbevf_info ixgbevf_X540_vf_info; -extern struct ixgbe_mbx_operations ixgbevf_mbx_ops; +extern const struct ixgbevf_info ixgbevf_82599_vf_info; +extern const struct ixgbevf_info ixgbevf_X540_vf_info; +extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops; /* needed by ethtool.c */ -extern char ixgbevf_driver_name[]; +extern const char ixgbevf_driver_name[]; extern const char ixgbevf_driver_version[]; extern int ixgbevf_up(struct ixgbevf_adapter *adapter); diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 891162d1610c..bed411bada21 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -53,7 +53,7 @@ #include "ixgbevf.h" -char ixgbevf_driver_name[] = "ixgbevf"; +const char ixgbevf_driver_name[] = "ixgbevf"; static const char ixgbevf_driver_string[] = "Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver"; @@ -917,31 +917,34 @@ static irqreturn_t ixgbevf_msix_mbx(int irq, void *data) struct ixgbe_hw *hw = &adapter->hw; u32 eicr; u32 msg; + bool got_ack = false; eicr = IXGBE_READ_REG(hw, IXGBE_VTEICS); IXGBE_WRITE_REG(hw, IXGBE_VTEICR, eicr); - if (!hw->mbx.ops.check_for_ack(hw)) { - /* - * checking for the ack clears the PFACK bit. Place - * it back in the v2p_mailbox cache so that anyone - * polling for an ack will not miss it. Also - * avoid the read below because the code to read - * the mailbox will also clear the ack bit. This was - * causing lost acks. Just cache the bit and exit - * the IRQ handler. - */ - hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK; - goto out; - } + if (!hw->mbx.ops.check_for_ack(hw)) + got_ack = true; - /* Not an ack interrupt, go ahead and read the message */ - hw->mbx.ops.read(hw, &msg, 1); + if (!hw->mbx.ops.check_for_msg(hw)) { + hw->mbx.ops.read(hw, &msg, 1); - if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG) - mod_timer(&adapter->watchdog_timer, - round_jiffies(jiffies + 1)); + if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG) + mod_timer(&adapter->watchdog_timer, + round_jiffies(jiffies + 1)); + if (msg & IXGBE_VT_MSGTYPE_NACK) + pr_warn("Last Request of type %2.2x to PF Nacked\n", + msg & 0xFF); + goto out; + } + + /* + * checking for the ack clears the PFACK bit. Place + * it back in the v2p_mailbox cache so that anyone + * polling for an ack will not miss it + */ + if (got_ack) + hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK; out: return IRQ_HANDLED; } diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.c b/drivers/net/ethernet/intel/ixgbevf/mbx.c index 930fa83f2568..13532d9ba72d 100644 --- a/drivers/net/ethernet/intel/ixgbevf/mbx.c +++ b/drivers/net/ethernet/intel/ixgbevf/mbx.c @@ -26,6 +26,7 @@ *******************************************************************************/ #include "mbx.h" +#include "ixgbevf.h" /** * ixgbevf_poll_for_msg - Wait for message notification @@ -328,7 +329,7 @@ static s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw) return 0; } -struct ixgbe_mbx_operations ixgbevf_mbx_ops = { +const struct ixgbe_mbx_operations ixgbevf_mbx_ops = { .init_params = ixgbevf_init_mbx_params_vf, .read = ixgbevf_read_mbx_vf, .write = ixgbevf_write_mbx_vf, diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c index 21533e300367..d0138d7a31a1 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.c +++ b/drivers/net/ethernet/intel/ixgbevf/vf.c @@ -26,6 +26,7 @@ *******************************************************************************/ #include "vf.h" +#include "ixgbevf.h" /** * ixgbevf_start_hw_vf - Prepare hardware for Tx/Rx @@ -401,7 +402,7 @@ static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw, return 0; } -static struct ixgbe_mac_operations ixgbevf_mac_ops = { +static const struct ixgbe_mac_operations ixgbevf_mac_ops = { .init_hw = ixgbevf_init_hw_vf, .reset_hw = ixgbevf_reset_hw_vf, .start_hw = ixgbevf_start_hw_vf, @@ -415,12 +416,12 @@ static struct ixgbe_mac_operations ixgbevf_mac_ops = { .set_vfta = ixgbevf_set_vfta_vf, }; -struct ixgbevf_info ixgbevf_82599_vf_info = { +const struct ixgbevf_info ixgbevf_82599_vf_info = { .mac = ixgbe_mac_82599_vf, .mac_ops = &ixgbevf_mac_ops, }; -struct ixgbevf_info ixgbevf_X540_vf_info = { +const struct ixgbevf_info ixgbevf_X540_vf_info = { .mac = ixgbe_mac_X540_vf, .mac_ops = &ixgbevf_mac_ops, }; diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h index 10306b492ee6..d556619a9212 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.h +++ b/drivers/net/ethernet/intel/ixgbevf/vf.h @@ -167,7 +167,7 @@ struct ixgbevf_hw_stats { struct ixgbevf_info { enum ixgbe_mac_type mac; - struct ixgbe_mac_operations *mac_ops; + const struct ixgbe_mac_operations *mac_ops; }; #endif /* __IXGBE_VF_H__ */ diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 9c049d2cb97d..9edecfa1f0f4 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -136,6 +136,8 @@ static char mv643xx_eth_driver_version[] = "1.4"; #define INT_MASK 0x0068 #define INT_MASK_EXT 0x006c #define TX_FIFO_URGENT_THRESHOLD 0x0074 +#define RX_DISCARD_FRAME_CNT 0x0084 +#define RX_OVERRUN_FRAME_CNT 0x0088 #define TXQ_FIX_PRIO_CONF_MOVED 0x00dc #define TX_BW_RATE_MOVED 0x00e0 #define TX_BW_MTU_MOVED 0x00e8 @@ -334,6 +336,9 @@ struct mib_counters { u32 bad_crc_event; u32 collision; u32 late_collision; + /* Non MIB hardware counters */ + u32 rx_discard; + u32 rx_overrun; }; struct lro_counters { @@ -1225,6 +1230,10 @@ static void mib_counters_clear(struct mv643xx_eth_private *mp) for (i = 0; i < 0x80; i += 4) mib_read(mp, i); + + /* Clear non MIB hw counters also */ + rdlp(mp, RX_DISCARD_FRAME_CNT); + rdlp(mp, RX_OVERRUN_FRAME_CNT); } static void mib_counters_update(struct mv643xx_eth_private *mp) @@ -1262,6 +1271,9 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) p->bad_crc_event += mib_read(mp, 0x74); p->collision += mib_read(mp, 0x78); p->late_collision += mib_read(mp, 0x7c); + /* Non MIB hardware counters */ + p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT); + p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT); spin_unlock_bh(&mp->mib_counters_lock); mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); @@ -1413,6 +1425,8 @@ static const struct mv643xx_eth_stats mv643xx_eth_stats[] = { MIBSTAT(bad_crc_event), MIBSTAT(collision), MIBSTAT(late_collision), + MIBSTAT(rx_discard), + MIBSTAT(rx_overrun), LROSTAT(lro_aggregated), LROSTAT(lro_flushed), LROSTAT(lro_no_desc), diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 18a87a57fc0a..edb9bda55d55 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -931,17 +931,20 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base) } /* Allocate and setup a new buffer for receiving */ -static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, - struct sk_buff *skb, unsigned int bufsize) +static int skge_rx_setup(struct pci_dev *pdev, + struct skge_element *e, + struct sk_buff *skb, unsigned int bufsize) { struct skge_rx_desc *rd = e->desc; - u64 map; + dma_addr_t map; - map = pci_map_single(skge->hw->pdev, skb->data, bufsize, + map = pci_map_single(pdev, skb->data, bufsize, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, map)) + goto mapping_error; - rd->dma_lo = map; - rd->dma_hi = map >> 32; + rd->dma_lo = lower_32_bits(map); + rd->dma_hi = upper_32_bits(map); e->skb = skb; rd->csum1_start = ETH_HLEN; rd->csum2_start = ETH_HLEN; @@ -953,6 +956,13 @@ static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize; dma_unmap_addr_set(e, mapaddr, map); dma_unmap_len_set(e, maplen, bufsize); + return 0; + +mapping_error: + if (net_ratelimit()) + dev_warn(&pdev->dev, "%s: rx mapping error\n", + skb->dev->name); + return -EIO; } /* Resume receiving using existing skb, @@ -1014,7 +1024,11 @@ static int skge_rx_fill(struct net_device *dev) return -ENOMEM; skb_reserve(skb, NET_IP_ALIGN); - skge_rx_setup(skge, e, skb, skge->rx_buf_size); + if (skge_rx_setup(skge->hw->pdev, e, skb, skge->rx_buf_size)) { + kfree_skb(skb); + return -ENOMEM; + } + } while ((e = e->next) != ring->start); ring->to_clean = ring->start; @@ -2576,6 +2590,7 @@ static int skge_up(struct net_device *dev) } /* Initialize MAC */ + netif_carrier_off(dev); spin_lock_bh(&hw->phy_lock); if (is_genesis(hw)) genesis_mac_init(hw, port); @@ -2728,7 +2743,7 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, struct skge_tx_desc *td; int i; u32 control, len; - u64 map; + dma_addr_t map; if (skb_padto(skb, ETH_ZLEN)) return NETDEV_TX_OK; @@ -2742,11 +2757,14 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, e->skb = skb; len = skb_headlen(skb); map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(hw->pdev, map)) + goto mapping_error; + dma_unmap_addr_set(e, mapaddr, map); dma_unmap_len_set(e, maplen, len); - td->dma_lo = map; - td->dma_hi = map >> 32; + td->dma_lo = lower_32_bits(map); + td->dma_hi = upper_32_bits(map); if (skb->ip_summed == CHECKSUM_PARTIAL) { const int offset = skb_checksum_start_offset(skb); @@ -2777,14 +2795,16 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, map = skb_frag_dma_map(&hw->pdev->dev, frag, 0, skb_frag_size(frag), DMA_TO_DEVICE); + if (dma_mapping_error(&hw->pdev->dev, map)) + goto mapping_unwind; e = e->next; e->skb = skb; tf = e->desc; BUG_ON(tf->control & BMU_OWN); - tf->dma_lo = map; - tf->dma_hi = (u64) map >> 32; + tf->dma_lo = lower_32_bits(map); + tf->dma_hi = upper_32_bits(map); dma_unmap_addr_set(e, mapaddr, map); dma_unmap_len_set(e, maplen, skb_frag_size(frag)); @@ -2797,6 +2817,8 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, td->control = BMU_OWN | BMU_SW | BMU_STF | control | len; wmb(); + netdev_sent_queue(dev, skb->len); + skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START); netif_printk(skge, tx_queued, KERN_DEBUG, skge->netdev, @@ -2812,15 +2834,35 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, } return NETDEV_TX_OK; + +mapping_unwind: + /* unroll any pages that were already mapped. */ + if (e != skge->tx_ring.to_use) { + struct skge_element *u; + + for (u = skge->tx_ring.to_use->next; u != e; u = u->next) + pci_unmap_page(hw->pdev, dma_unmap_addr(u, mapaddr), + dma_unmap_len(u, maplen), + PCI_DMA_TODEVICE); + e = skge->tx_ring.to_use; + } + /* undo the mapping for the skb header */ + pci_unmap_single(hw->pdev, dma_unmap_addr(e, mapaddr), + dma_unmap_len(e, maplen), + PCI_DMA_TODEVICE); +mapping_error: + /* mapping error causes error message and packet to be discarded. */ + if (net_ratelimit()) + dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name); + dev_kfree_skb(skb); + return NETDEV_TX_OK; } /* Free resources associated with this reing element */ -static void skge_tx_free(struct skge_port *skge, struct skge_element *e, - u32 control) +static inline void skge_tx_unmap(struct pci_dev *pdev, struct skge_element *e, + u32 control) { - struct pci_dev *pdev = skge->hw->pdev; - /* skb header vs. fragment */ if (control & BMU_STF) pci_unmap_single(pdev, dma_unmap_addr(e, mapaddr), @@ -2830,13 +2872,6 @@ static void skge_tx_free(struct skge_port *skge, struct skge_element *e, pci_unmap_page(pdev, dma_unmap_addr(e, mapaddr), dma_unmap_len(e, maplen), PCI_DMA_TODEVICE); - - if (control & BMU_EOF) { - netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev, - "tx done slot %td\n", e - skge->tx_ring.start); - - dev_kfree_skb(e->skb); - } } /* Free all buffers in transmit ring */ @@ -2847,10 +2882,15 @@ static void skge_tx_clean(struct net_device *dev) for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { struct skge_tx_desc *td = e->desc; - skge_tx_free(skge, e, td->control); + + skge_tx_unmap(skge->hw->pdev, e, td->control); + + if (td->control & BMU_EOF) + dev_kfree_skb(e->skb); td->control = 0; } + netdev_reset_queue(dev); skge->tx_ring.to_clean = e; } @@ -3059,13 +3099,17 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, if (!nskb) goto resubmit; + if (unlikely(skge_rx_setup(skge->hw->pdev, e, nskb, skge->rx_buf_size))) { + dev_kfree_skb(nskb); + goto resubmit; + } + pci_unmap_single(skge->hw->pdev, dma_unmap_addr(e, mapaddr), dma_unmap_len(e, maplen), PCI_DMA_FROMDEVICE); skb = e->skb; prefetch(skb->data); - skge_rx_setup(skge, e, nskb, skge->rx_buf_size); } skb_put(skb, len); @@ -3111,6 +3155,7 @@ static void skge_tx_done(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); struct skge_ring *ring = &skge->tx_ring; struct skge_element *e; + unsigned int bytes_compl = 0, pkts_compl = 0; skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); @@ -3120,8 +3165,20 @@ static void skge_tx_done(struct net_device *dev) if (control & BMU_OWN) break; - skge_tx_free(skge, e, control); + skge_tx_unmap(skge->hw->pdev, e, control); + + if (control & BMU_EOF) { + netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev, + "tx done slot %td\n", + e - skge->tx_ring.start); + + pkts_compl++; + bytes_compl += e->skb->len; + + dev_kfree_skb(e->skb); + } } + netdev_completed_queue(dev, pkts_compl, bytes_compl); skge->tx_ring.to_clean = e; /* Can run lockless until we need to synchronize to restart queue. */ diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 978f593094c0..405e6ac3faf6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -1247,6 +1247,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, u32 reply; u32 slave_status = 0; u8 is_going_down = 0; + int i; slave_state[slave].comm_toggle ^= 1; reply = (u32) slave_state[slave].comm_toggle << 31; @@ -1258,6 +1259,10 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, if (cmd == MLX4_COMM_CMD_RESET) { mlx4_warn(dev, "Received reset from slave:%d\n", slave); slave_state[slave].active = false; + for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) { + slave_state[slave].event_eq[i].eqn = -1; + slave_state[slave].event_eq[i].token = 0; + } /*check if we are in the middle of FLR process, if so return "retry" status to the slave*/ if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) { @@ -1452,7 +1457,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_slave_state *s_state; - int i, err, port; + int i, j, err, port; priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE, &priv->mfunc.vhcr_dma, @@ -1485,6 +1490,8 @@ int mlx4_multi_func_init(struct mlx4_dev *dev) for (i = 0; i < dev->num_slaves; ++i) { s_state = &priv->mfunc.master.slave_state[i]; s_state->last_cmd = MLX4_COMM_CMD_RESET; + for (j = 0; j < MLX4_EVENT_TYPES_NUM; ++j) + s_state->event_eq[j].eqn = -1; __raw_writel((__force u32) 0, &priv->mfunc.comm[i].slave_write); __raw_writel((__force u32) 0, diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c index 475f9d6af955..7e64033d7de3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/cq.c @@ -96,7 +96,7 @@ void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type) static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int cq_num) { - return mlx4_cmd(dev, mailbox->dma | dev->caps.function, cq_num, 0, + return mlx4_cmd(dev, mailbox->dma, cq_num, 0, MLX4_CMD_SW2HW_CQ, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); } @@ -111,7 +111,7 @@ static int mlx4_MODIFY_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int cq_num) { - return mlx4_cmd_box(dev, dev->caps.function, mailbox ? mailbox->dma : 0, + return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, cq_num, mailbox ? 0 : 1, MLX4_CMD_HW2SW_CQ, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); } diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index 7dbc6a230779..70346fd7f9c4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -183,10 +183,11 @@ static int mlx4_en_set_wol(struct net_device *netdev, static int mlx4_en_get_sset_count(struct net_device *dev, int sset) { struct mlx4_en_priv *priv = netdev_priv(dev); + int bit_count = hweight64(priv->stats_bitmap); switch (sset) { case ETH_SS_STATS: - return NUM_ALL_STATS + + return (priv->stats_bitmap ? bit_count : NUM_ALL_STATS) + (priv->tx_ring_num + priv->rx_ring_num) * 2; case ETH_SS_TEST: return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags @@ -201,14 +202,34 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev, { struct mlx4_en_priv *priv = netdev_priv(dev); int index = 0; - int i; + int i, j = 0; spin_lock_bh(&priv->stats_lock); - for (i = 0; i < NUM_MAIN_STATS; i++) - data[index++] = ((unsigned long *) &priv->stats)[i]; - for (i = 0; i < NUM_PORT_STATS; i++) - data[index++] = ((unsigned long *) &priv->port_stats)[i]; + if (!(priv->stats_bitmap)) { + for (i = 0; i < NUM_MAIN_STATS; i++) + data[index++] = + ((unsigned long *) &priv->stats)[i]; + for (i = 0; i < NUM_PORT_STATS; i++) + data[index++] = + ((unsigned long *) &priv->port_stats)[i]; + for (i = 0; i < NUM_PKT_STATS; i++) + data[index++] = + ((unsigned long *) &priv->pkstats)[i]; + } else { + for (i = 0; i < NUM_MAIN_STATS; i++) { + if ((priv->stats_bitmap >> j) & 1) + data[index++] = + ((unsigned long *) &priv->stats)[i]; + j++; + } + for (i = 0; i < NUM_PORT_STATS; i++) { + if ((priv->stats_bitmap >> j) & 1) + data[index++] = + ((unsigned long *) &priv->port_stats)[i]; + j++; + } + } for (i = 0; i < priv->tx_ring_num; i++) { data[index++] = priv->tx_ring[i].packets; data[index++] = priv->tx_ring[i].bytes; @@ -217,8 +238,6 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev, data[index++] = priv->rx_ring[i].packets; data[index++] = priv->rx_ring[i].bytes; } - for (i = 0; i < NUM_PKT_STATS; i++) - data[index++] = ((unsigned long *) &priv->pkstats)[i]; spin_unlock_bh(&priv->stats_lock); } @@ -247,11 +266,29 @@ static void mlx4_en_get_strings(struct net_device *dev, case ETH_SS_STATS: /* Add main counters */ - for (i = 0; i < NUM_MAIN_STATS; i++) - strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]); - for (i = 0; i< NUM_PORT_STATS; i++) - strcpy(data + (index++) * ETH_GSTRING_LEN, - main_strings[i + NUM_MAIN_STATS]); + if (!priv->stats_bitmap) { + for (i = 0; i < NUM_MAIN_STATS; i++) + strcpy(data + (index++) * ETH_GSTRING_LEN, + main_strings[i]); + for (i = 0; i < NUM_PORT_STATS; i++) + strcpy(data + (index++) * ETH_GSTRING_LEN, + main_strings[i + + NUM_MAIN_STATS]); + for (i = 0; i < NUM_PKT_STATS; i++) + strcpy(data + (index++) * ETH_GSTRING_LEN, + main_strings[i + + NUM_MAIN_STATS + + NUM_PORT_STATS]); + } else + for (i = 0; i < NUM_MAIN_STATS + NUM_PORT_STATS; i++) { + if ((priv->stats_bitmap >> i) & 1) { + strcpy(data + + (index++) * ETH_GSTRING_LEN, + main_strings[i]); + } + if (!(priv->stats_bitmap >> i)) + break; + } for (i = 0; i < priv->tx_ring_num; i++) { sprintf(data + (index++) * ETH_GSTRING_LEN, "tx%d_packets", i); @@ -264,9 +301,6 @@ static void mlx4_en_get_strings(struct net_device *dev, sprintf(data + (index++) * ETH_GSTRING_LEN, "rx%d_bytes", i); } - for (i = 0; i< NUM_PKT_STATS; i++) - strcpy(data + (index++) * ETH_GSTRING_LEN, - main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]); break; } } @@ -479,6 +513,95 @@ static void mlx4_en_get_ringparam(struct net_device *dev, param->tx_pending = priv->tx_ring[0].size; } +static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + + return priv->rx_ring_num; +} + +static int mlx4_en_get_rxfh_indir(struct net_device *dev, u32 *ring_index) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_rss_map *rss_map = &priv->rss_map; + int rss_rings; + size_t n = priv->rx_ring_num; + int err = 0; + + rss_rings = priv->prof->rss_rings ?: priv->rx_ring_num; + + while (n--) { + ring_index[n] = rss_map->qps[n % rss_rings].qpn - + rss_map->base_qpn; + } + + return err; +} + +static int mlx4_en_set_rxfh_indir(struct net_device *dev, + const u32 *ring_index) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = priv->mdev; + int port_up = 0; + int err = 0; + int i; + int rss_rings = 0; + + /* Calculate RSS table size and make sure flows are spread evenly + * between rings + */ + for (i = 0; i < priv->rx_ring_num; i++) { + if (i > 0 && !ring_index[i] && !rss_rings) + rss_rings = i; + + if (ring_index[i] != (i % (rss_rings ?: priv->rx_ring_num))) + return -EINVAL; + } + + if (!rss_rings) + rss_rings = priv->rx_ring_num; + + /* RSS table size must be an order of 2 */ + if (!is_power_of_2(rss_rings)) + return -EINVAL; + + mutex_lock(&mdev->state_lock); + if (priv->port_up) { + port_up = 1; + mlx4_en_stop_port(dev); + } + + priv->prof->rss_rings = rss_rings; + + if (port_up) { + err = mlx4_en_start_port(dev); + if (err) + en_err(priv, "Failed starting port\n"); + } + + mutex_unlock(&mdev->state_lock); + return err; +} + +static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + u32 *rule_locs) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + int err = 0; + + switch (cmd->cmd) { + case ETHTOOL_GRXRINGS: + cmd->data = priv->rx_ring_num; + break; + default: + err = -EOPNOTSUPP; + break; + } + + return err; +} + const struct ethtool_ops mlx4_en_ethtool_ops = { .get_drvinfo = mlx4_en_get_drvinfo, .get_settings = mlx4_en_get_settings, @@ -498,6 +621,10 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { .set_pauseparam = mlx4_en_set_pauseparam, .get_ringparam = mlx4_en_get_ringparam, .set_ringparam = mlx4_en_set_ringparam, + .get_rxnfc = mlx4_en_get_rxnfc, + .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size, + .get_rxfh_indir = mlx4_en_get_rxfh_indir, + .set_rxfh_indir = mlx4_en_set_rxfh_indir, }; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index a06096fcc0b8..2097a7d3c5b8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -62,10 +62,6 @@ static const char mlx4_en_version[] = * Device scope module parameters */ - -/* Enable RSS TCP traffic */ -MLX4_EN_PARM_INT(tcp_rss, 1, - "Enable RSS for incomming TCP traffic or disabled (0)"); /* Enable RSS UDP traffic */ MLX4_EN_PARM_INT(udp_rss, 1, "Enable RSS for incomming UDP traffic or disabled (0)"); @@ -104,7 +100,6 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev) struct mlx4_en_profile *params = &mdev->profile; int i; - params->tcp_rss = tcp_rss; params->udp_rss = udp_rss; if (params->udp_rss && !(mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UDP_RSS)) { @@ -120,6 +115,7 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev) params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE; params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS + (!!pfcrx) * MLX4_EN_NUM_PPP_RINGS; + params->prof[i].rss_rings = 0; } return 0; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 72fa807b69ce..467ae5824875 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -702,6 +702,8 @@ int mlx4_en_start_port(struct net_device *dev) /* Schedule multicast task to populate multicast list */ queue_work(mdev->workqueue, &priv->mcast_task); + mlx4_set_stats_bitmap(mdev->dev, &priv->stats_bitmap); + priv->port_up = true; netif_tx_start_all_queues(dev); return 0; @@ -807,38 +809,50 @@ static void mlx4_en_restart(struct work_struct *work) mutex_unlock(&mdev->state_lock); } - -static int mlx4_en_open(struct net_device *dev) +static void mlx4_en_clear_stats(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; int i; - int err = 0; - - mutex_lock(&mdev->state_lock); - - if (!mdev->device_up) { - en_err(priv, "Cannot open - device down/disabled\n"); - err = -EBUSY; - goto out; - } - /* Reset HW statistics and performance counters */ if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1)) en_dbg(HW, priv, "Failed dumping statistics\n"); memset(&priv->stats, 0, sizeof(priv->stats)); memset(&priv->pstats, 0, sizeof(priv->pstats)); + memset(&priv->pkstats, 0, sizeof(priv->pkstats)); + memset(&priv->port_stats, 0, sizeof(priv->port_stats)); for (i = 0; i < priv->tx_ring_num; i++) { priv->tx_ring[i].bytes = 0; priv->tx_ring[i].packets = 0; + priv->tx_ring[i].tx_csum = 0; } for (i = 0; i < priv->rx_ring_num; i++) { priv->rx_ring[i].bytes = 0; priv->rx_ring[i].packets = 0; + priv->rx_ring[i].csum_ok = 0; + priv->rx_ring[i].csum_none = 0; + } +} + +static int mlx4_en_open(struct net_device *dev) +{ + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = priv->mdev; + int err = 0; + + mutex_lock(&mdev->state_lock); + + if (!mdev->device_up) { + en_err(priv, "Cannot open - device down/disabled\n"); + err = -EBUSY; + goto out; } + /* Reset HW statistics and SW counters */ + mlx4_en_clear_stats(dev); + err = mlx4_en_start_port(dev); if (err) en_err(priv, "Failed starting port:%d\n", priv->port); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index e8d6ad2dce0a..971d4b6b8dfe 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -853,6 +853,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) struct mlx4_en_rss_map *rss_map = &priv->rss_map; struct mlx4_qp_context context; struct mlx4_rss_context *rss_context; + int rss_rings; void *ptr; u8 rss_mask = (MLX4_RSS_IPV4 | MLX4_RSS_TCP_IPV4 | MLX4_RSS_IPV6 | MLX4_RSS_TCP_IPV6); @@ -893,10 +894,15 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn, priv->rx_ring[0].cqn, &context); + if (!priv->prof->rss_rings || priv->prof->rss_rings > priv->rx_ring_num) + rss_rings = priv->rx_ring_num; + else + rss_rings = priv->prof->rss_rings; + ptr = ((void *) &context) + offsetof(struct mlx4_qp_context, pri_path) + MLX4_RSS_OFFSET_IN_QPC_PRI_PATH; rss_context = ptr; - rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 | + rss_context->base_qpn = cpu_to_be32(ilog2(rss_rings) << 24 | (rss_map->base_qpn)); rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn); if (priv->mdev->profile.udp_rss) { diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 1e9b55eb7217..55d7bd4e210a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -513,25 +513,22 @@ int mlx4_MAP_EQ_wrapper(struct mlx4_dev *dev, int slave, { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_slave_event_eq_info *event_eq = - &priv->mfunc.master.slave_state[slave].event_eq; + priv->mfunc.master.slave_state[slave].event_eq; u32 in_modifier = vhcr->in_modifier; u32 eqn = in_modifier & 0x1FF; u64 in_param = vhcr->in_param; int err = 0; + int i; if (slave == dev->caps.function) err = mlx4_cmd(dev, in_param, (in_modifier & 0x80000000) | eqn, 0, MLX4_CMD_MAP_EQ, MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); - if (!err) { - if (in_modifier >> 31) { - /* unmap */ - event_eq->event_type &= ~in_param; - } else { - event_eq->eqn = eqn; - event_eq->event_type = in_param; - } - } + if (!err) + for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) + if (in_param & (1LL << i)) + event_eq[i].eqn = in_modifier >> 31 ? -1 : eqn; + return err; } @@ -546,7 +543,7 @@ static int mlx4_MAP_EQ(struct mlx4_dev *dev, u64 event_mask, int unmap, static int mlx4_SW2HW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int eq_num) { - return mlx4_cmd(dev, mailbox->dma | dev->caps.function, eq_num, 0, + return mlx4_cmd(dev, mailbox->dma, eq_num, 0, MLX4_CMD_SW2HW_EQ, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); } @@ -554,7 +551,7 @@ static int mlx4_SW2HW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, static int mlx4_HW2SW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int eq_num) { - return mlx4_cmd_box(dev, dev->caps.function, mailbox->dma, eq_num, + return mlx4_cmd_box(dev, 0, mailbox->dma, eq_num, 0, MLX4_CMD_HW2SW_EQ, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); } diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index a424a19280cc..8a21e10952ea 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -158,7 +158,6 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, #define QUERY_FUNC_CAP_FLAGS_OFFSET 0x0 #define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1 -#define QUERY_FUNC_CAP_FUNCTION_OFFSET 0x3 #define QUERY_FUNC_CAP_PF_BHVR_OFFSET 0x4 #define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x10 #define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x14 @@ -182,9 +181,6 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, field = 1 << 7; /* enable only ethernet interface */ MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET); - field = slave; - MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FUNCTION_OFFSET); - field = dev->caps.num_ports; MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); @@ -249,9 +245,6 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, struct mlx4_func_cap *func_cap) goto out; } - MLX4_GET(field, outbox, QUERY_FUNC_CAP_FUNCTION_OFFSET); - func_cap->function = field; - MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); func_cap->num_ports = field; diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h index 119e0cc9fab3..e1a5fa56bcbc 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/drivers/net/ethernet/mellanox/mlx4/fw.h @@ -119,7 +119,6 @@ struct mlx4_dev_cap { }; struct mlx4_func_cap { - u8 function; u8 num_ports; u8 flags; u32 pf_context_behaviour; diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 6bb62c580e2d..678558b502fc 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -108,7 +108,7 @@ static struct mlx4_profile default_profile = { .num_cq = 1 << 16, .num_mcg = 1 << 13, .num_mpt = 1 << 19, - .num_mtt = 1 << 20, + .num_mtt = 1 << 20, /* It is really num mtt segements */ }; static int log_num_mac = 7; @@ -471,7 +471,6 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) return -ENOSYS; } - dev->caps.function = func_cap.function; dev->caps.num_ports = func_cap.num_ports; dev->caps.num_qps = func_cap.qp_quota; dev->caps.num_srqs = func_cap.srq_quota; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index a80121a2b519..c92269f8c057 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -388,9 +388,8 @@ struct mlx4_slave_eqe { }; struct mlx4_slave_event_eq_info { - u32 eqn; + int eqn; u16 token; - u64 event_type; }; struct mlx4_profile { @@ -449,6 +448,8 @@ struct mlx4_steer_index { struct list_head duplicates; }; +#define MLX4_EVENT_TYPES_NUM 64 + struct mlx4_slave_state { u8 comm_toggle; u8 last_cmd; @@ -461,7 +462,8 @@ struct mlx4_slave_state { struct mlx4_slave_eqe eq[MLX4_MFUNC_MAX_EQES]; struct list_head mcast_filters[MLX4_MAX_PORTS + 1]; struct mlx4_vlan_fltr *vlan_filter[MLX4_MAX_PORTS + 1]; - struct mlx4_slave_event_eq_info event_eq; + /* event type to eq number lookup */ + struct mlx4_slave_event_eq_info event_eq[MLX4_EVENT_TYPES_NUM]; u16 eq_pi; u16 eq_ci; spinlock_t lock; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index f2a8e65f5f88..35f08840813c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -325,11 +325,11 @@ struct mlx4_en_port_profile { u8 rx_ppp; u8 tx_pause; u8 tx_ppp; + int rss_rings; }; struct mlx4_en_profile { int rss_xor; - int tcp_rss; int udp_rss; u8 rss_mask; u32 active_ports; @@ -476,6 +476,7 @@ struct mlx4_en_priv { struct mlx4_en_perf_stats pstats; struct mlx4_en_pkt_stats pkstats; struct mlx4_en_port_stats port_stats; + u64 stats_bitmap; char *mc_addrs; int mc_addrs_cnt; struct mlx4_en_stat_out_mbox hw_stats; diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index 01df5567e16e..8deeef98280c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -291,7 +291,7 @@ static u32 key_to_hw_index(u32 key) static int mlx4_SW2HW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int mpt_index) { - return mlx4_cmd(dev, mailbox->dma | dev->caps.function , mpt_index, + return mlx4_cmd(dev, mailbox->dma, mpt_index, 0, MLX4_CMD_SW2HW_MPT, MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); } diff --git a/drivers/net/ethernet/mellanox/mlx4/pd.c b/drivers/net/ethernet/mellanox/mlx4/pd.c index 5c9a54df17ab..db4746d0dca7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/pd.c +++ b/drivers/net/ethernet/mellanox/mlx4/pd.c @@ -52,8 +52,7 @@ int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn) *pdn = mlx4_bitmap_alloc(&priv->pd_bitmap); if (*pdn == -1) return -ENOMEM; - if (mlx4_is_mfunc(dev)) - *pdn |= (dev->caps.function + 1) << NOT_MASKED_PD_BITS; + return 0; } EXPORT_SYMBOL_GPL(mlx4_pd_alloc); diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index 88b52e547524..f44ae555bf43 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c @@ -44,6 +44,11 @@ #define MLX4_VLAN_VALID (1u << 31) #define MLX4_VLAN_MASK 0xfff +#define MLX4_STATS_TRAFFIC_COUNTERS_MASK 0xfULL +#define MLX4_STATS_TRAFFIC_DROPS_MASK 0xc0ULL +#define MLX4_STATS_ERROR_COUNTERS_MASK 0x1ffc30ULL +#define MLX4_STATS_PORT_COUNTERS_MASK 0x1fe00000ULL + void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table) { int i; @@ -898,6 +903,24 @@ int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_info *cmd) { + if (slave != dev->caps.function) + return 0; return mlx4_common_dump_eth_stats(dev, slave, vhcr->in_modifier, outbox); } + +void mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap) +{ + if (!mlx4_is_mfunc(dev)) { + *stats_bitmap = 0; + return; + } + + *stats_bitmap = (MLX4_STATS_TRAFFIC_COUNTERS_MASK | + MLX4_STATS_TRAFFIC_DROPS_MASK | + MLX4_STATS_PORT_COUNTERS_MASK); + + if (mlx4_is_master(dev)) + *stats_bitmap |= MLX4_STATS_ERROR_COUNTERS_MASK; +} +EXPORT_SYMBOL(mlx4_set_stats_bitmap); diff --git a/drivers/net/ethernet/mellanox/mlx4/profile.c b/drivers/net/ethernet/mellanox/mlx4/profile.c index 66f91ca7a7c6..1129677daa62 100644 --- a/drivers/net/ethernet/mellanox/mlx4/profile.c +++ b/drivers/net/ethernet/mellanox/mlx4/profile.c @@ -110,7 +110,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, profile[MLX4_RES_EQ].num = min_t(unsigned, dev_cap->max_eqs, MAX_MSIX); profile[MLX4_RES_DMPT].num = request->num_mpt; profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS; - profile[MLX4_RES_MTT].num = request->num_mtt; + profile[MLX4_RES_MTT].num = request->num_mtt * (1 << log_mtts_per_seg); profile[MLX4_RES_MCG].num = request->num_mcg; for (i = 0; i < MLX4_RES_NUM; ++i) { diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index 6b03ac8b9002..738f950a1ce5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -162,7 +162,7 @@ static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, ((struct mlx4_qp_context *) (mailbox->buf + 8))->local_qpn = cpu_to_be32(qp->qpn); - ret = mlx4_cmd(dev, mailbox->dma | dev->caps.function, + ret = mlx4_cmd(dev, mailbox->dma, qp->qpn | (!!sqd_event << 31), new_state == MLX4_QP_STATE_RST ? 2 : 0, op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C, native); diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index ed20751a057d..dcd819bfb2f0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -1561,11 +1561,6 @@ static int mr_get_mtt_size(struct mlx4_mpt_entry *mpt) return be32_to_cpu(mpt->mtt_sz); } -static int mr_get_pdn(struct mlx4_mpt_entry *mpt) -{ - return be32_to_cpu(mpt->pd_flags) & 0xffffff; -} - static int qp_get_mtt_addr(struct mlx4_qp_context *qpc) { return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8; @@ -1602,16 +1597,6 @@ static int qp_get_mtt_size(struct mlx4_qp_context *qpc) return total_pages; } -static int qp_get_pdn(struct mlx4_qp_context *qpc) -{ - return be32_to_cpu(qpc->pd) & 0xffffff; -} - -static int pdn2slave(int pdn) -{ - return (pdn >> NOT_MASKED_PD_BITS) - 1; -} - static int check_mtt_range(struct mlx4_dev *dev, int slave, int start, int size, struct res_mtt *mtt) { @@ -1656,11 +1641,6 @@ int mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave, mpt->mtt = mtt; } - if (pdn2slave(mr_get_pdn(inbox->buf)) != slave) { - err = -EPERM; - goto ex_put; - } - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); if (err) goto ex_put; @@ -1792,11 +1772,6 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave, if (err) goto ex_put_mtt; - if (pdn2slave(qp_get_pdn(qpc)) != slave) { - err = -EPERM; - goto ex_put_mtt; - } - err = get_res(dev, slave, rcqn, RES_CQ, &rcq); if (err) goto ex_put_mtt; @@ -2048,10 +2023,10 @@ int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe) if (!priv->mfunc.master.slave_state) return -EINVAL; - event_eq = &priv->mfunc.master.slave_state[slave].event_eq; + event_eq = &priv->mfunc.master.slave_state[slave].event_eq[eqe->type]; /* Create the event only if the slave is registered */ - if ((event_eq->event_type & (1 << eqe->type)) == 0) + if (event_eq->eqn < 0) return 0; mutex_lock(&priv->mfunc.master.gen_eqe_mutex[slave]); @@ -2289,11 +2264,6 @@ ex_put: return err; } -static int srq_get_pdn(struct mlx4_srq_context *srqc) -{ - return be32_to_cpu(srqc->pd) & 0xffffff; -} - static int srq_get_mtt_size(struct mlx4_srq_context *srqc) { int log_srq_size = (be32_to_cpu(srqc->state_logsize_srqn) >> 24) & 0xf; @@ -2333,11 +2303,6 @@ int mlx4_SW2HW_SRQ_wrapper(struct mlx4_dev *dev, int slave, if (err) goto ex_put_mtt; - if (pdn2slave(srq_get_pdn(srqc)) != slave) { - err = -EPERM; - goto ex_put_mtt; - } - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); if (err) goto ex_put_mtt; diff --git a/drivers/net/ethernet/mellanox/mlx4/srq.c b/drivers/net/ethernet/mellanox/mlx4/srq.c index 2823fffc6383..feda6c00829f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/srq.c +++ b/drivers/net/ethernet/mellanox/mlx4/srq.c @@ -67,7 +67,7 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type) static int mlx4_SW2HW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int srq_num) { - return mlx4_cmd(dev, mailbox->dma | dev->caps.function, srq_num, 0, + return mlx4_cmd(dev, mailbox->dma, srq_num, 0, MLX4_CMD_SW2HW_SRQ, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); } diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 964e9c0948bc..3ead111111e1 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -1745,6 +1745,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring; int err; + /* Ensure we have a valid MAC */ + if (!is_valid_ether_addr(adapter->hw.mac.addr)) { + pr_err("Error: Invalid MAC address\n"); + return -EINVAL; + } + /* hardware has been reset, we need to reload some things */ pch_gbe_set_multi(netdev); @@ -2468,9 +2474,14 @@ static int pch_gbe_probe(struct pci_dev *pdev, memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len); if (!is_valid_ether_addr(netdev->dev_addr)) { - dev_err(&pdev->dev, "Invalid MAC Address\n"); - ret = -EIO; - goto err_free_adapter; + /* + * If the MAC is invalid (or just missing), display a warning + * but do not abort setting up the device. pch_gbe_up will + * prevent the interface from being brought up until a valid MAC + * is set. + */ + dev_err(&pdev->dev, "Invalid MAC address, " + "interface disabled.\n"); } setup_timer(&adapter->watchdog_timer, pch_gbe_watchdog, (unsigned long)adapter); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index da4a1042523a..73195329aa46 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -154,7 +154,7 @@ int stmmac_mdio_register(struct net_device *ndev) else irqlist = priv->mii_irq; - new_bus->name = "STMMAC MII Bus"; + new_bus->name = "stmmac"; new_bus->read = &stmmac_mdio_read; new_bus->write = &stmmac_mdio_write; new_bus->reset = &stmmac_mdio_reset; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index 54a819a36487..c796de9eed72 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -170,9 +170,9 @@ static int stmmac_pci_resume(struct pci_dev *pdev) #define STMMAC_DEVICE_ID 0x1108 static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = { - { - PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)}, { - } + {PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)}, + {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)}, + {} }; MODULE_DEVICE_TABLE(pci, stmmac_id_table); diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 462d05f05e84..1a1ca6cfc74a 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -68,11 +68,11 @@ static void do_set_multicast(struct work_struct *w) nvdev = hv_get_drvdata(ndevctx->device_ctx); if (nvdev == NULL) - return; + goto out; rdev = nvdev->extension; if (rdev == NULL) - return; + goto out; if (net->flags & IFF_PROMISC) rndis_filter_set_packet_filter(rdev, @@ -83,6 +83,7 @@ static void do_set_multicast(struct work_struct *w) NDIS_PACKET_TYPE_ALL_MULTICAST | NDIS_PACKET_TYPE_DIRECTED); +out: kfree(w); } diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index f2f820c4b40a..9ea99217f116 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -173,6 +173,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) skb = ip_check_defrag(skb, IP_DEFRAG_MACVLAN); if (!skb) return RX_HANDLER_CONSUMED; + eth = eth_hdr(skb); src = macvlan_hash_lookup(port, eth->h_source); if (!src) /* frame comes from an external address */ diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 88cc5db9affd..8985cc62cf41 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -38,12 +38,11 @@ /** * mdiobus_alloc_size - allocate a mii_bus structure + * @size: extra amount of memory to allocate for private storage. + * If non-zero, then bus->priv is points to that memory. * * Description: called by a bus driver to allocate an mii_bus * structure to fill in. - * - * 'size' is an an extra amount of memory to allocate for private storage. - * If non-zero, then bus->priv is points to that memory. */ struct mii_bus *mdiobus_alloc_size(size_t size) { diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index ed2a862b835d..6b678f38e5ce 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -92,9 +92,9 @@ struct team_option *__team_find_option(struct team *team, const char *opt_name) return NULL; } -int team_options_register(struct team *team, - const struct team_option *option, - size_t option_count) +int __team_options_register(struct team *team, + const struct team_option *option, + size_t option_count) { int i; struct team_option **dst_opts; @@ -116,8 +116,11 @@ int team_options_register(struct team *team, } } - for (i = 0; i < option_count; i++) + for (i = 0; i < option_count; i++) { + dst_opts[i]->changed = true; + dst_opts[i]->removed = false; list_add_tail(&dst_opts[i]->list, &team->option_list); + } kfree(dst_opts); return 0; @@ -130,10 +133,22 @@ rollback: return err; } -EXPORT_SYMBOL(team_options_register); +static void __team_options_mark_removed(struct team *team, + const struct team_option *option, + size_t option_count) +{ + int i; + + for (i = 0; i < option_count; i++, option++) { + struct team_option *del_opt; -static void __team_options_change_check(struct team *team, - struct team_option *changed_option); + del_opt = __team_find_option(team, option->name); + if (del_opt) { + del_opt->changed = true; + del_opt->removed = true; + } + } +} static void __team_options_unregister(struct team *team, const struct team_option *option, @@ -152,12 +167,29 @@ static void __team_options_unregister(struct team *team, } } +static void __team_options_change_check(struct team *team); + +int team_options_register(struct team *team, + const struct team_option *option, + size_t option_count) +{ + int err; + + err = __team_options_register(team, option, option_count); + if (err) + return err; + __team_options_change_check(team); + return 0; +} +EXPORT_SYMBOL(team_options_register); + void team_options_unregister(struct team *team, const struct team_option *option, size_t option_count) { + __team_options_mark_removed(team, option, option_count); + __team_options_change_check(team); __team_options_unregister(team, option, option_count); - __team_options_change_check(team, NULL); } EXPORT_SYMBOL(team_options_unregister); @@ -176,7 +208,8 @@ static int team_option_set(struct team *team, struct team_option *option, if (err) return err; - __team_options_change_check(team, option); + option->changed = true; + __team_options_change_check(team); return err; } @@ -653,6 +686,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev) return -ENOENT; } + port->removed = true; __team_port_change_check(port, false); team_port_list_del_port(team, port); team_adjust_ops(team); @@ -1200,10 +1234,9 @@ err_fill: return err; } -static int team_nl_fill_options_get_changed(struct sk_buff *skb, - u32 pid, u32 seq, int flags, - struct team *team, - struct team_option *changed_option) +static int team_nl_fill_options_get(struct sk_buff *skb, + u32 pid, u32 seq, int flags, + struct team *team, bool fillall) { struct nlattr *option_list; void *hdr; @@ -1223,12 +1256,19 @@ static int team_nl_fill_options_get_changed(struct sk_buff *skb, struct nlattr *option_item; long arg; + /* Include only changed options if fill all mode is not on */ + if (!fillall && !option->changed) + continue; option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION); if (!option_item) goto nla_put_failure; NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_NAME, option->name); - if (option == changed_option) + if (option->changed) { NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_CHANGED); + option->changed = false; + } + if (option->removed) + NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_REMOVED); switch (option->type) { case TEAM_OPTION_TYPE_U32: NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32); @@ -1255,13 +1295,13 @@ nla_put_failure: return -EMSGSIZE; } -static int team_nl_fill_options_get(struct sk_buff *skb, - struct genl_info *info, int flags, - struct team *team) +static int team_nl_fill_options_get_all(struct sk_buff *skb, + struct genl_info *info, int flags, + struct team *team) { - return team_nl_fill_options_get_changed(skb, info->snd_pid, - info->snd_seq, NLM_F_ACK, - team, NULL); + return team_nl_fill_options_get(skb, info->snd_pid, + info->snd_seq, NLM_F_ACK, + team, true); } static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info) @@ -1273,7 +1313,7 @@ static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info) if (!team) return -EINVAL; - err = team_nl_send_generic(info, team, team_nl_fill_options_get); + err = team_nl_send_generic(info, team, team_nl_fill_options_get_all); team_nl_team_put(team); @@ -1365,10 +1405,10 @@ team_put: return err; } -static int team_nl_fill_port_list_get_changed(struct sk_buff *skb, - u32 pid, u32 seq, int flags, - struct team *team, - struct team_port *changed_port) +static int team_nl_fill_port_list_get(struct sk_buff *skb, + u32 pid, u32 seq, int flags, + struct team *team, + bool fillall) { struct nlattr *port_list; void *hdr; @@ -1387,12 +1427,19 @@ static int team_nl_fill_port_list_get_changed(struct sk_buff *skb, list_for_each_entry(port, &team->port_list, list) { struct nlattr *port_item; + /* Include only changed ports if fill all mode is not on */ + if (!fillall && !port->changed) + continue; port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT); if (!port_item) goto nla_put_failure; NLA_PUT_U32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex); - if (port == changed_port) + if (port->changed) { NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_CHANGED); + port->changed = false; + } + if (port->removed) + NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_REMOVED); if (port->linkup) NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_LINKUP); NLA_PUT_U32(skb, TEAM_ATTR_PORT_SPEED, port->speed); @@ -1408,13 +1455,13 @@ nla_put_failure: return -EMSGSIZE; } -static int team_nl_fill_port_list_get(struct sk_buff *skb, - struct genl_info *info, int flags, - struct team *team) +static int team_nl_fill_port_list_get_all(struct sk_buff *skb, + struct genl_info *info, int flags, + struct team *team) { - return team_nl_fill_port_list_get_changed(skb, info->snd_pid, - info->snd_seq, NLM_F_ACK, - team, NULL); + return team_nl_fill_port_list_get(skb, info->snd_pid, + info->snd_seq, NLM_F_ACK, + team, true); } static int team_nl_cmd_port_list_get(struct sk_buff *skb, @@ -1427,7 +1474,7 @@ static int team_nl_cmd_port_list_get(struct sk_buff *skb, if (!team) return -EINVAL; - err = team_nl_send_generic(info, team, team_nl_fill_port_list_get); + err = team_nl_send_generic(info, team, team_nl_fill_port_list_get_all); team_nl_team_put(team); @@ -1464,8 +1511,7 @@ static struct genl_multicast_group team_change_event_mcgrp = { .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, }; -static int team_nl_send_event_options_get(struct team *team, - struct team_option *changed_option) +static int team_nl_send_event_options_get(struct team *team) { struct sk_buff *skb; int err; @@ -1475,8 +1521,7 @@ static int team_nl_send_event_options_get(struct team *team, if (!skb) return -ENOMEM; - err = team_nl_fill_options_get_changed(skb, 0, 0, 0, team, - changed_option); + err = team_nl_fill_options_get(skb, 0, 0, 0, team, false); if (err < 0) goto err_fill; @@ -1489,18 +1534,17 @@ err_fill: return err; } -static int team_nl_send_event_port_list_get(struct team_port *port) +static int team_nl_send_event_port_list_get(struct team *team) { struct sk_buff *skb; int err; - struct net *net = dev_net(port->team->dev); + struct net *net = dev_net(team->dev); skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb) return -ENOMEM; - err = team_nl_fill_port_list_get_changed(skb, 0, 0, 0, - port->team, port); + err = team_nl_fill_port_list_get(skb, 0, 0, 0, team, false); if (err < 0) goto err_fill; @@ -1544,12 +1588,11 @@ static void team_nl_fini(void) * Change checkers ******************/ -static void __team_options_change_check(struct team *team, - struct team_option *changed_option) +static void __team_options_change_check(struct team *team) { int err; - err = team_nl_send_event_options_get(team, changed_option); + err = team_nl_send_event_options_get(team); if (err) netdev_warn(team->dev, "Failed to send options change via netlink\n"); } @@ -1559,9 +1602,10 @@ static void __team_port_change_check(struct team_port *port, bool linkup) { int err; - if (port->linkup == linkup) + if (!port->removed && port->linkup == linkup) return; + port->changed = true; port->linkup = linkup; if (linkup) { struct ethtool_cmd ecmd; @@ -1577,7 +1621,7 @@ static void __team_port_change_check(struct team_port *port, bool linkup) port->duplex = 0; send_event: - err = team_nl_send_event_port_list_get(port); + err = team_nl_send_event_port_list_get(port->team); if (err) netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n", port->dev->name); diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index b97a40ed5fff..3876c7ea54f4 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -31,6 +31,12 @@ config B43_BCMA depends on B43 && BCMA default y +config B43_BCMA_EXTRA + bool "Hardware support that overlaps with the brcmsmac driver" + depends on B43_BCMA + default n if BRCMSMAC || BRCMSMAC_MODULE + default y + config B43_SSB bool depends on B43 && SSB diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index b91f28ef1032..23ffb1b9a86f 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -116,8 +116,10 @@ MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); #ifdef CONFIG_B43_BCMA static const struct bcma_device_id b43_bcma_tbl[] = { BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS), +#ifdef CONFIG_B43_BCMA_EXTRA BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS), BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS), +#endif BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS), BCMA_CORETABLE_END }; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index f7ed34034f88..f6affc6fd12a 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -7981,13 +7981,21 @@ int brcms_c_get_curband(struct brcms_c_info *wlc) void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop) { + int timeout = 20; + /* flush packet queue when requested */ if (drop) brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL); /* wait for queue and DMA fifos to run dry */ - while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) + while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) { brcms_msleep(wlc->wl, 1); + + if (--timeout == 0) + break; + } + + WARN_ON_ONCE(timeout == 0); } void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 752493f00406..65d1f05007be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -972,11 +972,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans) } #endif - spin_unlock_irqrestore(&trans->shrd->lock, flags); - /* saved interrupt in inta variable now we can reset trans_pcie->inta */ trans_pcie->inta = 0; + spin_unlock_irqrestore(&trans->shrd->lock, flags); + /* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) { IWL_ERR(trans, "Hardware error detected. Restarting.\n"); diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index fa679057630f..698b905058dd 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -68,7 +68,7 @@ struct netfront_cb { #define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) #define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) -#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) +#define TX_MAX_TARGET min_t(int, NET_TX_RING_SIZE, 256) struct netfront_stats { u64 rx_packets; diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index 59866905ea37..27f2fe3b7fb4 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c @@ -205,7 +205,8 @@ static int __devexit pcmcia_remove(struct sa1111_dev *dev) dev_set_drvdata(&dev->dev, NULL); - for (; next = s->next, s; s = next) { + for (; s; s = next) { + next = s->next; soc_pcmcia_remove_one(&s->soc); kfree(s); } diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 569bdb3ef104..8fe15cf15ac8 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -510,10 +510,12 @@ static struct dentry *debugfs_root; static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev) { - static struct dentry *device_root; + struct dentry *device_root; device_root = debugfs_create_dir(dev_name(pctldev->dev), debugfs_root); + pctldev->device_root = device_root; + if (IS_ERR(device_root) || !device_root) { pr_warn("failed to create debugfs directory for %s\n", dev_name(pctldev->dev)); @@ -529,6 +531,11 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev) pinconf_init_device_debugfs(device_root, pctldev); } +static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev) +{ + debugfs_remove_recursive(pctldev->device_root); +} + static void pinctrl_init_debugfs(void) { debugfs_root = debugfs_create_dir("pinctrl", NULL); @@ -553,6 +560,10 @@ static void pinctrl_init_debugfs(void) { } +static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev) +{ +} + #endif /** @@ -572,40 +583,40 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, if (pctldesc->name == NULL) return NULL; + pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL); + if (pctldev == NULL) + return NULL; + + /* Initialize pin control device struct */ + pctldev->owner = pctldesc->owner; + pctldev->desc = pctldesc; + pctldev->driver_data = driver_data; + INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL); + spin_lock_init(&pctldev->pin_desc_tree_lock); + INIT_LIST_HEAD(&pctldev->gpio_ranges); + mutex_init(&pctldev->gpio_ranges_lock); + pctldev->dev = dev; + /* If we're implementing pinmuxing, check the ops for sanity */ if (pctldesc->pmxops) { - ret = pinmux_check_ops(pctldesc->pmxops); + ret = pinmux_check_ops(pctldev); if (ret) { pr_err("%s pinmux ops lacks necessary functions\n", pctldesc->name); - return NULL; + goto out_err; } } /* If we're implementing pinconfig, check the ops for sanity */ if (pctldesc->confops) { - ret = pinconf_check_ops(pctldesc->confops); + ret = pinconf_check_ops(pctldev); if (ret) { pr_err("%s pin config ops lacks necessary functions\n", pctldesc->name); - return NULL; + goto out_err; } } - pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL); - if (pctldev == NULL) - return NULL; - - /* Initialize pin control device struct */ - pctldev->owner = pctldesc->owner; - pctldev->desc = pctldesc; - pctldev->driver_data = driver_data; - INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL); - spin_lock_init(&pctldev->pin_desc_tree_lock); - INIT_LIST_HEAD(&pctldev->gpio_ranges); - mutex_init(&pctldev->gpio_ranges_lock); - pctldev->dev = dev; - /* Register all the pins */ pr_debug("try to register %d pins on %s...\n", pctldesc->npins, pctldesc->name); @@ -641,6 +652,7 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev) if (pctldev == NULL) return; + pinctrl_remove_device_debugfs(pctldev); pinmux_unhog_maps(pctldev); /* TODO: check that no pinmuxes are still active? */ mutex_lock(&pinctrldev_list_mutex); diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 177a3310547f..cfa86da6b4b1 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -41,6 +41,9 @@ struct pinctrl_dev { struct device *dev; struct module *owner; void *driver_data; +#ifdef CONFIG_DEBUG_FS + struct dentry *device_root; +#endif #ifdef CONFIG_PINMUX struct mutex pinmux_hogs_lock; struct list_head pinmux_hogs; diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 1259872b0a1d..9fb75456824c 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -205,8 +205,10 @@ int pin_config_group_set(const char *dev_name, const char *pin_group, } EXPORT_SYMBOL(pin_config_group_set); -int pinconf_check_ops(const struct pinconf_ops *ops) +int pinconf_check_ops(struct pinctrl_dev *pctldev) { + const struct pinconf_ops *ops = pctldev->desc->confops; + /* We must be able to read out pin status */ if (!ops->pin_config_get && !ops->pin_config_group_get) return -EINVAL; @@ -236,7 +238,7 @@ static int pinconf_pins_show(struct seq_file *s, void *what) seq_puts(s, "Format: pin (name): pinmux setting array\n"); /* The pin number can be retrived from the pin controller descriptor */ - for (i = 0; pin < pctldev->desc->npins; i++) { + for (i = 0; i < pctldev->desc->npins; i++) { struct pin_desc *desc; pin = pctldev->desc->pins[i].number; diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h index e7dc6165032a..006b77fa737e 100644 --- a/drivers/pinctrl/pinconf.h +++ b/drivers/pinctrl/pinconf.h @@ -13,7 +13,7 @@ #ifdef CONFIG_PINCONF -int pinconf_check_ops(const struct pinconf_ops *ops); +int pinconf_check_ops(struct pinctrl_dev *pctldev); void pinconf_init_device_debugfs(struct dentry *devroot, struct pinctrl_dev *pctldev); int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, @@ -23,7 +23,7 @@ int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, #else -static inline int pinconf_check_ops(const struct pinconf_ops *ops) +static inline int pinconf_check_ops(struct pinctrl_dev *pctldev) { return 0; } diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index a76a348321bb..7c3193f7a044 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -53,11 +53,6 @@ struct pinmux_group { * @dev: the device using this pinmux * @usecount: the number of active users of this mux setting, used to keep * track of nested use cases - * @pins: an array of discrete physical pins used in this mapping, taken - * from the global pin enumeration space (copied from pinmux map) - * @num_pins: the number of pins in this mapping array, i.e. the number of - * elements in .pins so we can iterate over that array (copied from - * pinmux map) * @pctldev: pin control device handling this pinmux * @func_selector: the function selector for the pinmux device handling * this pinmux @@ -152,8 +147,7 @@ static int pin_request(struct pinctrl_dev *pctldev, status = 0; if (status) - dev_err(pctldev->dev, "->request on device %s failed " - "for pin %d\n", + dev_err(pctldev->dev, "->request on device %s failed for pin %d\n", pctldev->desc->name, pin); out_free_pin: if (status) { @@ -355,21 +349,20 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps, /* First sanity check the new mapping */ for (i = 0; i < num_maps; i++) { if (!maps[i].name) { - pr_err("failed to register map %d: " - "no map name given\n", i); + pr_err("failed to register map %d: no map name given\n", + i); return -EINVAL; } if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) { - pr_err("failed to register map %s (%d): " - "no pin control device given\n", + pr_err("failed to register map %s (%d): no pin control device given\n", maps[i].name, i); return -EINVAL; } if (!maps[i].function) { - pr_err("failed to register map %s (%d): " - "no function ID given\n", maps[i].name, i); + pr_err("failed to register map %s (%d): no function ID given\n", + maps[i].name, i); return -EINVAL; } @@ -411,7 +404,7 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps, } /** - * acquire_pins() - acquire all the pins for a certain funcion on a pinmux + * acquire_pins() - acquire all the pins for a certain function on a pinmux * @pctldev: the device to take the pins on * @func_selector: the function selector to acquire the pins for * @group_selector: the group selector containing the pins to acquire @@ -442,8 +435,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev, ret = pin_request(pctldev, pins[i], func, NULL); if (ret) { dev_err(pctldev->dev, - "could not get pin %d for function %s " - "on device %s - conflicting mux mappings?\n", + "could not get pin %d for function %s on device %s - conflicting mux mappings?\n", pins[i], func ? : "(undefined)", pinctrl_dev_get_name(pctldev)); /* On error release all taken pins */ @@ -458,7 +450,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev, /** * release_pins() - release pins taken by earlier acquirement - * @pctldev: the device to free the pinx on + * @pctldev: the device to free the pins on * @group_selector: the group selector containing the pins to free */ static void release_pins(struct pinctrl_dev *pctldev, @@ -473,8 +465,7 @@ static void release_pins(struct pinctrl_dev *pctldev, ret = pctlops->get_group_pins(pctldev, group_selector, &pins, &num_pins); if (ret) { - dev_err(pctldev->dev, "could not get pins to release for " - "group selector %d\n", + dev_err(pctldev->dev, "could not get pins to release for group selector %d\n", group_selector); return; } @@ -526,8 +517,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev, ret = pinctrl_get_group_selector(pctldev, groups[0]); if (ret < 0) { dev_err(pctldev->dev, - "function %s wants group %s but the pin " - "controller does not seem to have that group\n", + "function %s wants group %s but the pin controller does not seem to have that group\n", pmxops->get_function_name(pctldev, func_selector), groups[0]); return ret; @@ -535,8 +525,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev, if (num_groups > 1) dev_dbg(pctldev->dev, - "function %s support more than one group, " - "default-selecting first group %s (%d)\n", + "function %s support more than one group, default-selecting first group %s (%d)\n", pmxops->get_function_name(pctldev, func_selector), groups[0], ret); @@ -628,10 +617,8 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev, if (pmx->pctldev && pmx->pctldev != pctldev) { dev_err(pctldev->dev, - "different pin control devices given for device %s, " - "function %s\n", - devname, - map->function); + "different pin control devices given for device %s, function %s\n", + devname, map->function); return -EINVAL; } pmx->dev = dev; @@ -695,7 +682,6 @@ static void pinmux_free_groups(struct pinmux *pmx) */ struct pinmux *pinmux_get(struct device *dev, const char *name) { - struct pinmux_map const *map = NULL; struct pinctrl_dev *pctldev = NULL; const char *devname = NULL; @@ -745,8 +731,7 @@ struct pinmux *pinmux_get(struct device *dev, const char *name) else if (map->ctrl_dev_name) devname = map->ctrl_dev_name; - pr_warning("could not find a pinctrl device for pinmux " - "function %s, fishy, they shall all have one\n", + pr_warning("could not find a pinctrl device for pinmux function %s, fishy, they shall all have one\n", map->function); pr_warning("given pinctrl device name: %s", devname ? devname : "UNDEFINED"); @@ -904,8 +889,11 @@ void pinmux_disable(struct pinmux *pmx) } EXPORT_SYMBOL_GPL(pinmux_disable); -int pinmux_check_ops(const struct pinmux_ops *ops) +int pinmux_check_ops(struct pinctrl_dev *pctldev) { + const struct pinmux_ops *ops = pctldev->desc->pmxops; + unsigned selector = 0; + /* Check that we implement required operations */ if (!ops->list_functions || !ops->get_function_name || @@ -914,6 +902,18 @@ int pinmux_check_ops(const struct pinmux_ops *ops) !ops->disable) return -EINVAL; + /* Check that all functions registered have names */ + while (ops->list_functions(pctldev, selector) >= 0) { + const char *fname = ops->get_function_name(pctldev, + selector); + if (!fname) { + pr_err("pinmux ops has no name for function%u\n", + selector); + return -EINVAL; + } + selector++; + } + return 0; } @@ -932,8 +932,8 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev, * without any problems, so then we can hog pinmuxes for * all devices that just want a static pin mux at this point. */ - dev_err(pctldev->dev, "map %s wants to hog a non-system " - "pinmux, this is not going to work\n", map->name); + dev_err(pctldev->dev, "map %s wants to hog a non-system pinmux, this is not going to work\n", + map->name); return -EINVAL; } @@ -993,9 +993,12 @@ int pinmux_hog_maps(struct pinctrl_dev *pctldev) for (i = 0; i < pinmux_maps_num; i++) { struct pinmux_map const *map = &pinmux_maps[i]; - if (((map->ctrl_dev == dev) || - !strcmp(map->ctrl_dev_name, devname)) && - map->hog_on_boot) { + if (!map->hog_on_boot) + continue; + + if ((map->ctrl_dev == dev) || + (map->ctrl_dev_name && + !strcmp(map->ctrl_dev_name, devname))) { /* OK time to hog! */ ret = pinmux_hog_map(pctldev, map); if (ret) @@ -1122,13 +1125,15 @@ static int pinmux_show(struct seq_file *s, void *what) seq_printf(s, "device: %s function: %s (%u),", pinctrl_dev_get_name(pmx->pctldev), - pmxops->get_function_name(pctldev, pmx->func_selector), + pmxops->get_function_name(pctldev, + pmx->func_selector), pmx->func_selector); seq_printf(s, " groups: ["); list_for_each_entry(grp, &pmx->groups, node) { seq_printf(s, " %s (%u)", - pctlops->get_group_name(pctldev, grp->group_selector), + pctlops->get_group_name(pctldev, + grp->group_selector), grp->group_selector); } seq_printf(s, " ]"); diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h index 844500b3331b..97f52223fbc2 100644 --- a/drivers/pinctrl/pinmux.h +++ b/drivers/pinctrl/pinmux.h @@ -12,7 +12,7 @@ */ #ifdef CONFIG_PINMUX -int pinmux_check_ops(const struct pinmux_ops *ops); +int pinmux_check_ops(struct pinctrl_dev *pctldev); void pinmux_init_device_debugfs(struct dentry *devroot, struct pinctrl_dev *pctldev); void pinmux_init_debugfs(struct dentry *subsys_root); @@ -21,7 +21,7 @@ void pinmux_unhog_maps(struct pinctrl_dev *pctldev); #else -static inline int pinmux_check_ops(const struct pinmux_ops *ops) +static inline int pinmux_check_ops(struct pinctrl_dev *pctldev) { return 0; } diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index b1fa25d6583a..e9a83f84adaf 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2731,7 +2731,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) * @dev: struct device for the regulator * @init_data: platform provided init data, passed through by driver * @driver_data: private regulator data - * @of_node: target open firmware device structure (may be NULL) + * @of_node: OpenFirmware node to parse for device tree bindings (may be + * NULL). * * Called by regulator drivers to register a regulator. * Returns 0 on success. diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index f1651eb69648..679734d26a16 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -35,7 +35,7 @@ static void of_get_regulation_constraints(struct device_node *np, if (constraints->min_uV != constraints->max_uV) constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; /* Only one voltage? Then make sure it's set. */ - if (constraints->min_uV == constraints->max_uV) + if (min_uV && max_uV && constraints->min_uV == constraints->max_uV) constraints->apply_uV = true; uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e19a4031f45e..3a125b835546 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -774,7 +774,7 @@ config RTC_DRV_EP93XX config RTC_DRV_SA1100 tristate "SA11x0/PXA2xx" - depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP + depends on ARCH_SA1100 || ARCH_PXA help If you say Y here you will get access to the real time clock built into your SA11x0 or PXA2xx CPU. diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 4595d3e645a7..cb9a585312cc 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -27,42 +27,34 @@ #include <linux/init.h> #include <linux/fs.h> #include <linux/interrupt.h> +#include <linux/string.h> #include <linux/pm.h> -#include <linux/slab.h> -#include <linux/clk.h> -#include <linux/io.h> +#include <linux/bitops.h> #include <mach/hardware.h> #include <asm/irq.h> +#ifdef CONFIG_ARCH_PXA +#include <mach/regs-rtc.h> +#endif + #define RTC_DEF_DIVIDER (32768 - 1) #define RTC_DEF_TRIM 0 -#define RTC_FREQ 1024 - -#define RCNR 0x00 /* RTC Count Register */ -#define RTAR 0x04 /* RTC Alarm Register */ -#define RTSR 0x08 /* RTC Status Register */ -#define RTTR 0x0c /* RTC Timer Trim Register */ - -#define RTSR_HZE (1 << 3) /* HZ interrupt enable */ -#define RTSR_ALE (1 << 2) /* RTC alarm interrupt enable */ -#define RTSR_HZ (1 << 1) /* HZ rising-edge detected */ -#define RTSR_AL (1 << 0) /* RTC alarm detected */ - -#define rtc_readl(sa1100_rtc, reg) \ - readl_relaxed((sa1100_rtc)->base + (reg)) -#define rtc_writel(sa1100_rtc, reg, value) \ - writel_relaxed((value), (sa1100_rtc)->base + (reg)) - -struct sa1100_rtc { - struct resource *ress; - void __iomem *base; - struct clk *clk; - int irq_1Hz; - int irq_Alrm; - struct rtc_device *rtc; - spinlock_t lock; /* Protects this structure */ -}; + +static const unsigned long RTC_FREQ = 1024; +static struct rtc_time rtc_alarm; +static DEFINE_SPINLOCK(sa1100_rtc_lock); + +static inline int rtc_periodic_alarm(struct rtc_time *tm) +{ + return (tm->tm_year == -1) || + ((unsigned)tm->tm_mon >= 12) || + ((unsigned)(tm->tm_mday - 1) >= 31) || + ((unsigned)tm->tm_hour > 23) || + ((unsigned)tm->tm_min > 59) || + ((unsigned)tm->tm_sec > 59); +} + /* * Calculate the next alarm time given the requested alarm time mask * and the current time. @@ -90,26 +82,46 @@ static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, } } +static int rtc_update_alarm(struct rtc_time *alrm) +{ + struct rtc_time alarm_tm, now_tm; + unsigned long now, time; + int ret; + + do { + now = RCNR; + rtc_time_to_tm(now, &now_tm); + rtc_next_alarm_time(&alarm_tm, &now_tm, alrm); + ret = rtc_tm_to_time(&alarm_tm, &time); + if (ret != 0) + break; + + RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL); + RTAR = time; + } while (now != RCNR); + + return ret; +} + static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) { struct platform_device *pdev = to_platform_device(dev_id); - struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev); + struct rtc_device *rtc = platform_get_drvdata(pdev); unsigned int rtsr; unsigned long events = 0; - spin_lock(&sa1100_rtc->lock); + spin_lock(&sa1100_rtc_lock); + rtsr = RTSR; /* clear interrupt sources */ - rtsr = rtc_readl(sa1100_rtc, RTSR); - rtc_writel(sa1100_rtc, RTSR, 0); - + RTSR = 0; /* Fix for a nasty initialization problem the in SA11xx RTSR register. * See also the comments in sa1100_rtc_probe(). */ if (rtsr & (RTSR_ALE | RTSR_HZE)) { /* This is the original code, before there was the if test * above. This code does not clear interrupts that were not * enabled. */ - rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ) & (rtsr >> 2)); + RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); } else { /* For some reason, it is possible to enter this routine * without interruptions enabled, it has been tested with @@ -118,13 +130,13 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) * This situation leads to an infinite "loop" of interrupt * routine calling and as a result the processor seems to * lock on its first call to open(). */ - rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ)); + RTSR = RTSR_AL | RTSR_HZ; } /* clear alarm interrupt if it has occurred */ if (rtsr & RTSR_AL) rtsr &= ~RTSR_ALE; - rtc_writel(sa1100_rtc, RTSR, rtsr & (RTSR_ALE | RTSR_HZE)); + RTSR = rtsr & (RTSR_ALE | RTSR_HZE); /* update irq data & counter */ if (rtsr & RTSR_AL) @@ -132,100 +144,89 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) if (rtsr & RTSR_HZ) events |= RTC_UF | RTC_IRQF; - rtc_update_irq(sa1100_rtc->rtc, 1, events); + rtc_update_irq(rtc, 1, events); - spin_unlock(&sa1100_rtc->lock); + if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) + rtc_update_alarm(&rtc_alarm); + + spin_unlock(&sa1100_rtc_lock); return IRQ_HANDLED; } static int sa1100_rtc_open(struct device *dev) { - struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); int ret; + struct platform_device *plat_dev = to_platform_device(dev); + struct rtc_device *rtc = platform_get_drvdata(plat_dev); - ret = request_irq(sa1100_rtc->irq_1Hz, sa1100_rtc_interrupt, - IRQF_DISABLED, "rtc 1Hz", dev); + ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, + "rtc 1Hz", dev); if (ret) { - dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_1Hz); + dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); goto fail_ui; } - ret = request_irq(sa1100_rtc->irq_Alrm, sa1100_rtc_interrupt, - IRQF_DISABLED, "rtc Alrm", dev); + ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED, + "rtc Alrm", dev); if (ret) { - dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_Alrm); + dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); goto fail_ai; } - sa1100_rtc->rtc->max_user_freq = RTC_FREQ; - rtc_irq_set_freq(sa1100_rtc->rtc, NULL, RTC_FREQ); + rtc->max_user_freq = RTC_FREQ; + rtc_irq_set_freq(rtc, NULL, RTC_FREQ); return 0; fail_ai: - free_irq(sa1100_rtc->irq_1Hz, dev); + free_irq(IRQ_RTC1Hz, dev); fail_ui: return ret; } static void sa1100_rtc_release(struct device *dev) { - struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); - - spin_lock_irq(&sa1100_rtc->lock); - rtc_writel(sa1100_rtc, RTSR, 0); - spin_unlock_irq(&sa1100_rtc->lock); + spin_lock_irq(&sa1100_rtc_lock); + RTSR = 0; + spin_unlock_irq(&sa1100_rtc_lock); - free_irq(sa1100_rtc->irq_Alrm, dev); - free_irq(sa1100_rtc->irq_1Hz, dev); + free_irq(IRQ_RTCAlrm, dev); + free_irq(IRQ_RTC1Hz, dev); } static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { - struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); - unsigned int rtsr; - - spin_lock_irq(&sa1100_rtc->lock); - - rtsr = rtc_readl(sa1100_rtc, RTSR); + spin_lock_irq(&sa1100_rtc_lock); if (enabled) - rtsr |= RTSR_ALE; + RTSR |= RTSR_ALE; else - rtsr &= ~RTSR_ALE; - rtc_writel(sa1100_rtc, RTSR, rtsr); - - spin_unlock_irq(&sa1100_rtc->lock); + RTSR &= ~RTSR_ALE; + spin_unlock_irq(&sa1100_rtc_lock); return 0; } static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) { - struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); - - rtc_time_to_tm(rtc_readl(sa1100_rtc, RCNR), tm); + rtc_time_to_tm(RCNR, tm); return 0; } static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); unsigned long time; int ret; ret = rtc_tm_to_time(tm, &time); if (ret == 0) - rtc_writel(sa1100_rtc, RCNR, time); + RCNR = time; return ret; } static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); - unsigned long time; - unsigned int rtsr; + u32 rtsr; - time = rtc_readl(sa1100_rtc, RCNR); - rtc_time_to_tm(time, &alrm->time); - rtsr = rtc_readl(sa1100_rtc, RTSR); + memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time)); + rtsr = RTSR; alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; return 0; @@ -233,39 +234,26 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); - struct rtc_time now_tm, alarm_tm; - unsigned long time, alarm; - unsigned int rtsr; - - spin_lock_irq(&sa1100_rtc->lock); - - time = rtc_readl(sa1100_rtc, RCNR); - rtc_time_to_tm(time, &now_tm); - rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time); - rtc_tm_to_time(&alarm_tm, &alarm); - rtc_writel(sa1100_rtc, RTAR, alarm); - - rtsr = rtc_readl(sa1100_rtc, RTSR); - if (alrm->enabled) - rtsr |= RTSR_ALE; - else - rtsr &= ~RTSR_ALE; - rtc_writel(sa1100_rtc, RTSR, rtsr); + int ret; - spin_unlock_irq(&sa1100_rtc->lock); + spin_lock_irq(&sa1100_rtc_lock); + ret = rtc_update_alarm(&alrm->time); + if (ret == 0) { + if (alrm->enabled) + RTSR |= RTSR_ALE; + else + RTSR &= ~RTSR_ALE; + } + spin_unlock_irq(&sa1100_rtc_lock); - return 0; + return ret; } static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) { - struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); + seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR); + seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR); - seq_printf(seq, "trim/divider\t\t: 0x%08x\n", - rtc_readl(sa1100_rtc, RTTR)); - seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", - rtc_readl(sa1100_rtc, RTSR)); return 0; } @@ -282,51 +270,7 @@ static const struct rtc_class_ops sa1100_rtc_ops = { static int sa1100_rtc_probe(struct platform_device *pdev) { - struct sa1100_rtc *sa1100_rtc; - unsigned int rttr; - int ret; - - sa1100_rtc = kzalloc(sizeof(struct sa1100_rtc), GFP_KERNEL); - if (!sa1100_rtc) - return -ENOMEM; - - spin_lock_init(&sa1100_rtc->lock); - platform_set_drvdata(pdev, sa1100_rtc); - - ret = -ENXIO; - sa1100_rtc->ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!sa1100_rtc->ress) { - dev_err(&pdev->dev, "No I/O memory resource defined\n"); - goto err_ress; - } - - sa1100_rtc->irq_1Hz = platform_get_irq(pdev, 0); - if (sa1100_rtc->irq_1Hz < 0) { - dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n"); - goto err_ress; - } - sa1100_rtc->irq_Alrm = platform_get_irq(pdev, 1); - if (sa1100_rtc->irq_Alrm < 0) { - dev_err(&pdev->dev, "No alarm IRQ resource defined\n"); - goto err_ress; - } - - ret = -ENOMEM; - sa1100_rtc->base = ioremap(sa1100_rtc->ress->start, - resource_size(sa1100_rtc->ress)); - if (!sa1100_rtc->base) { - dev_err(&pdev->dev, "Unable to map pxa RTC I/O memory\n"); - goto err_map; - } - - sa1100_rtc->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(sa1100_rtc->clk)) { - dev_err(&pdev->dev, "failed to find rtc clock source\n"); - ret = PTR_ERR(sa1100_rtc->clk); - goto err_clk; - } - clk_prepare(sa1100_rtc->clk); - clk_enable(sa1100_rtc->clk); + struct rtc_device *rtc; /* * According to the manual we should be able to let RTTR be zero @@ -335,24 +279,24 @@ static int sa1100_rtc_probe(struct platform_device *pdev) * If the clock divider is uninitialized then reset it to the * default value to get the 1Hz clock. */ - if (rtc_readl(sa1100_rtc, RTTR) == 0) { - rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); - rtc_writel(sa1100_rtc, RTTR, rttr); - dev_warn(&pdev->dev, "warning: initializing default clock" - " divider/trim value\n"); + if (RTTR == 0) { + RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); + dev_warn(&pdev->dev, "warning: " + "initializing default clock divider/trim value\n"); /* The current RTC value probably doesn't make sense either */ - rtc_writel(sa1100_rtc, RCNR, 0); + RCNR = 0; } device_init_wakeup(&pdev->dev, 1); - sa1100_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, - &sa1100_rtc_ops, THIS_MODULE); - if (IS_ERR(sa1100_rtc->rtc)) { - dev_err(&pdev->dev, "Failed to register RTC device -> %d\n", - ret); - goto err_rtc_reg; - } + rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, + THIS_MODULE); + + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + platform_set_drvdata(pdev, rtc); + /* Fix for a nasty initialization problem the in SA11xx RTSR register. * See also the comments in sa1100_rtc_interrupt(). * @@ -375,46 +319,33 @@ static int sa1100_rtc_probe(struct platform_device *pdev) * * Notice that clearing bit 1 and 0 is accomplished by writting ONES to * the corresponding bits in RTSR. */ - rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ)); + RTSR = RTSR_AL | RTSR_HZ; return 0; - -err_rtc_reg: -err_clk: - iounmap(sa1100_rtc->base); -err_ress: -err_map: - kfree(sa1100_rtc); - return ret; } static int sa1100_rtc_remove(struct platform_device *pdev) { - struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev); + struct rtc_device *rtc = platform_get_drvdata(pdev); + + if (rtc) + rtc_device_unregister(rtc); - rtc_device_unregister(sa1100_rtc->rtc); - clk_disable(sa1100_rtc->clk); - clk_unprepare(sa1100_rtc->clk); - iounmap(sa1100_rtc->base); return 0; } #ifdef CONFIG_PM static int sa1100_rtc_suspend(struct device *dev) { - struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); - if (device_may_wakeup(dev)) - enable_irq_wake(sa1100_rtc->irq_Alrm); + enable_irq_wake(IRQ_RTCAlrm); return 0; } static int sa1100_rtc_resume(struct device *dev) { - struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); - if (device_may_wakeup(dev)) - disable_irq_wake(sa1100_rtc->irq_Alrm); + disable_irq_wake(IRQ_RTCAlrm); return 0; } diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index eef27a197c00..110137e7ec81 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -3261,6 +3261,12 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event) device->path_data.tbvpm |= eventlpm; dasd_schedule_device_bh(device); } + if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) { + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "Pathgroup re-established\n"); + if (device->discipline->kick_validate) + device->discipline->kick_validate(device); + } } dasd_put_device(device); } diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 553b3c5abb0a..b3beed5434e4 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -189,14 +189,12 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) unsigned long flags; struct alias_server *server, *newserver; struct alias_lcu *lcu, *newlcu; - int is_lcu_known; struct dasd_uid uid; private = (struct dasd_eckd_private *) device->private; device->discipline->get_uid(device, &uid); spin_lock_irqsave(&aliastree.lock, flags); - is_lcu_known = 1; server = _find_server(&uid); if (!server) { spin_unlock_irqrestore(&aliastree.lock, flags); @@ -208,7 +206,6 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) if (!server) { list_add(&newserver->server, &aliastree.serverlist); server = newserver; - is_lcu_known = 0; } else { /* someone was faster */ _free_server(newserver); @@ -226,12 +223,10 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) if (!lcu) { list_add(&newlcu->lcu, &server->lculist); lcu = newlcu; - is_lcu_known = 0; } else { /* someone was faster */ _free_lcu(newlcu); } - is_lcu_known = 0; } spin_lock(&lcu->lock); list_add(&device->alias_list, &lcu->inactive_devices); @@ -239,64 +234,7 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) spin_unlock(&lcu->lock); spin_unlock_irqrestore(&aliastree.lock, flags); - return is_lcu_known; -} - -/* - * The first device to be registered on an LCU will have to do - * some additional setup steps to configure that LCU on the - * storage server. All further devices should wait with their - * initialization until the first device is done. - * To synchronize this work, the first device will call - * dasd_alias_lcu_setup_complete when it is done, and all - * other devices will wait for it with dasd_alias_wait_for_lcu_setup. - */ -void dasd_alias_lcu_setup_complete(struct dasd_device *device) -{ - unsigned long flags; - struct alias_server *server; - struct alias_lcu *lcu; - struct dasd_uid uid; - - device->discipline->get_uid(device, &uid); - lcu = NULL; - spin_lock_irqsave(&aliastree.lock, flags); - server = _find_server(&uid); - if (server) - lcu = _find_lcu(server, &uid); - spin_unlock_irqrestore(&aliastree.lock, flags); - if (!lcu) { - DBF_EVENT_DEVID(DBF_ERR, device->cdev, - "could not find lcu for %04x %02x", - uid.ssid, uid.real_unit_addr); - WARN_ON(1); - return; - } - complete_all(&lcu->lcu_setup); -} - -void dasd_alias_wait_for_lcu_setup(struct dasd_device *device) -{ - unsigned long flags; - struct alias_server *server; - struct alias_lcu *lcu; - struct dasd_uid uid; - - device->discipline->get_uid(device, &uid); - lcu = NULL; - spin_lock_irqsave(&aliastree.lock, flags); - server = _find_server(&uid); - if (server) - lcu = _find_lcu(server, &uid); - spin_unlock_irqrestore(&aliastree.lock, flags); - if (!lcu) { - DBF_EVENT_DEVID(DBF_ERR, device->cdev, - "could not find lcu for %04x %02x", - uid.ssid, uid.real_unit_addr); - WARN_ON(1); - return; - } - wait_for_completion(&lcu->lcu_setup); + return 0; } /* diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index bbcd5e9206ee..70880be26015 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1534,6 +1534,10 @@ static void dasd_eckd_validate_server(struct dasd_device *device) struct dasd_eckd_private *private; int enable_pav; + private = (struct dasd_eckd_private *) device->private; + if (private->uid.type == UA_BASE_PAV_ALIAS || + private->uid.type == UA_HYPER_PAV_ALIAS) + return; if (dasd_nopav || MACHINE_IS_VM) enable_pav = 0; else @@ -1542,11 +1546,28 @@ static void dasd_eckd_validate_server(struct dasd_device *device) /* may be requested feature is not available on server, * therefore just report error and go ahead */ - private = (struct dasd_eckd_private *) device->private; DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x " "returned rc=%d", private->uid.ssid, rc); } +/* + * worker to do a validate server in case of a lost pathgroup + */ +static void dasd_eckd_do_validate_server(struct work_struct *work) +{ + struct dasd_device *device = container_of(work, struct dasd_device, + kick_validate); + dasd_eckd_validate_server(device); + dasd_put_device(device); +} + +static void dasd_eckd_kick_validate_server(struct dasd_device *device) +{ + dasd_get_device(device); + /* queue call to do_validate_server to the kernel event daemon. */ + schedule_work(&device->kick_validate); +} + static u32 get_fcx_max_data(struct dasd_device *device) { #if defined(CONFIG_64BIT) @@ -1588,10 +1609,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device) struct dasd_eckd_private *private; struct dasd_block *block; struct dasd_uid temp_uid; - int is_known, rc, i; + int rc, i; int readonly; unsigned long value; + /* setup work queue for validate server*/ + INIT_WORK(&device->kick_validate, dasd_eckd_do_validate_server); + if (!ccw_device_is_pathgroup(device->cdev)) { dev_warn(&device->cdev->dev, "A channel path group could not be established\n"); @@ -1651,22 +1675,12 @@ dasd_eckd_check_characteristics(struct dasd_device *device) block->base = device; } - /* register lcu with alias handling, enable PAV if this is a new lcu */ - is_known = dasd_alias_make_device_known_to_lcu(device); - if (is_known < 0) { - rc = is_known; + /* register lcu with alias handling, enable PAV */ + rc = dasd_alias_make_device_known_to_lcu(device); + if (rc) goto out_err2; - } - /* - * dasd_eckd_validate_server is done on the first device that - * is found for an LCU. All later other devices have to wait - * for it, so they will read the correct feature codes. - */ - if (!is_known) { - dasd_eckd_validate_server(device); - dasd_alias_lcu_setup_complete(device); - } else - dasd_alias_wait_for_lcu_setup(device); + + dasd_eckd_validate_server(device); /* device may report different configuration data after LCU setup */ rc = dasd_eckd_read_conf(device); @@ -4098,7 +4112,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device) { struct dasd_eckd_private *private; struct dasd_eckd_characteristics temp_rdc_data; - int is_known, rc; + int rc; struct dasd_uid temp_uid; unsigned long flags; @@ -4121,14 +4135,10 @@ static int dasd_eckd_restore_device(struct dasd_device *device) goto out_err; /* register lcu with alias handling, enable PAV if this is a new lcu */ - is_known = dasd_alias_make_device_known_to_lcu(device); - if (is_known < 0) - return is_known; - if (!is_known) { - dasd_eckd_validate_server(device); - dasd_alias_lcu_setup_complete(device); - } else - dasd_alias_wait_for_lcu_setup(device); + rc = dasd_alias_make_device_known_to_lcu(device); + if (rc) + return rc; + dasd_eckd_validate_server(device); /* RE-Read Configuration Data */ rc = dasd_eckd_read_conf(device); @@ -4270,6 +4280,7 @@ static struct dasd_discipline dasd_eckd_discipline = { .restore = dasd_eckd_restore_device, .reload = dasd_eckd_reload_device, .get_uid = dasd_eckd_get_uid, + .kick_validate = dasd_eckd_kick_validate_server, }; static int __init diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index afe8c33422ed..33a6743ddc55 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -355,6 +355,7 @@ struct dasd_discipline { int (*reload) (struct dasd_device *); int (*get_uid) (struct dasd_device *, struct dasd_uid *); + void (*kick_validate) (struct dasd_device *); }; extern struct dasd_discipline *dasd_diag_discipline_pointer; @@ -455,6 +456,7 @@ struct dasd_device { struct work_struct kick_work; struct work_struct restore_device; struct work_struct reload_device; + struct work_struct kick_validate; struct timer_list timer; debug_info_t *debug_area; diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index 4ceeace80453..70eb1f79b1ba 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c @@ -565,8 +565,7 @@ static int __devinit esp_mac_probe(struct platform_device *dev) esp_chips[dev->id] = esp; mb(); if (esp_chips[!dev->id] == NULL) { - err = request_irq(host->irq, mac_scsi_esp_intr, 0, - "Mac ESP", NULL); + err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL); if (err < 0) { esp_chips[dev->id] = NULL; goto fail_free_priv; diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index ea2bde206f7f..2bccfbe5661e 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -339,9 +339,6 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance) printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." ); - /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */ - disable_irq(IRQ_MAC_SCSI); - /* get in phase */ NCR5380_write( TARGET_COMMAND_REG, PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) )); @@ -357,9 +354,6 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance) for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); ) barrier(); - /* switch on SCSI IRQ again */ - enable_irq(IRQ_MAC_SCSI); - printk(KERN_INFO " done\n" ); } #endif diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c index 70e006b50f29..5443e25086e9 100644 --- a/drivers/staging/media/go7007/go7007-usb.c +++ b/drivers/staging/media/go7007/go7007-usb.c @@ -1279,3 +1279,4 @@ static struct usb_driver go7007_usb_driver = { }; module_usb_driver(go7007_usb_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index dd9a5743fa99..220ce7e31cf5 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -1304,7 +1304,7 @@ static struct genl_multicast_group thermal_event_mcgrp = { .name = THERMAL_GENL_MCAST_GROUP_NAME, }; -int generate_netlink_event(u32 orig, enum events event) +int thermal_generate_netlink_event(u32 orig, enum events event) { struct sk_buff *skb; struct nlattr *attr; @@ -1363,7 +1363,7 @@ int generate_netlink_event(u32 orig, enum events event) return result; } -EXPORT_SYMBOL(generate_netlink_event); +EXPORT_SYMBOL(thermal_generate_netlink_event); static int genetlink_init(void) { diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250/8250.c index 9f50c4e3c2be..9f50c4e3c2be 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250/8250.c diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250/8250.h index ae027be57e25..ae027be57e25 100644 --- a/drivers/tty/serial/8250.h +++ b/drivers/tty/serial/8250/8250.h diff --git a/drivers/tty/serial/8250_accent.c b/drivers/tty/serial/8250/8250_accent.c index 34b51c651192..34b51c651192 100644 --- a/drivers/tty/serial/8250_accent.c +++ b/drivers/tty/serial/8250/8250_accent.c diff --git a/drivers/tty/serial/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c index b0ce8c56f1a4..b0ce8c56f1a4 100644 --- a/drivers/tty/serial/8250_acorn.c +++ b/drivers/tty/serial/8250/8250_acorn.c diff --git a/drivers/tty/serial/8250_boca.c b/drivers/tty/serial/8250/8250_boca.c index d125dc107985..d125dc107985 100644 --- a/drivers/tty/serial/8250_boca.c +++ b/drivers/tty/serial/8250/8250_boca.c diff --git a/drivers/tty/serial/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index f574eef3075f..f574eef3075f 100644 --- a/drivers/tty/serial/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c diff --git a/drivers/tty/serial/8250_early.c b/drivers/tty/serial/8250/8250_early.c index eaafb98debed..eaafb98debed 100644 --- a/drivers/tty/serial/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c diff --git a/drivers/tty/serial/8250_exar_st16c554.c b/drivers/tty/serial/8250/8250_exar_st16c554.c index bf53aabf9b5e..bf53aabf9b5e 100644 --- a/drivers/tty/serial/8250_exar_st16c554.c +++ b/drivers/tty/serial/8250/8250_exar_st16c554.c diff --git a/drivers/tty/serial/8250_fourport.c b/drivers/tty/serial/8250/8250_fourport.c index be1582609626..be1582609626 100644 --- a/drivers/tty/serial/8250_fourport.c +++ b/drivers/tty/serial/8250/8250_fourport.c diff --git a/drivers/tty/serial/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c index f4d3c47b88e8..f4d3c47b88e8 100644 --- a/drivers/tty/serial/8250_fsl.c +++ b/drivers/tty/serial/8250/8250_fsl.c diff --git a/drivers/tty/serial/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c index d8c0ffbfa6e3..d8c0ffbfa6e3 100644 --- a/drivers/tty/serial/8250_gsc.c +++ b/drivers/tty/serial/8250/8250_gsc.c diff --git a/drivers/tty/serial/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c index c13438c93012..c13438c93012 100644 --- a/drivers/tty/serial/8250_hp300.c +++ b/drivers/tty/serial/8250/8250_hp300.c diff --git a/drivers/tty/serial/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c index a5c778e83de0..a5c778e83de0 100644 --- a/drivers/tty/serial/8250_hub6.c +++ b/drivers/tty/serial/8250/8250_hub6.c diff --git a/drivers/tty/serial/8250_mca.c b/drivers/tty/serial/8250/8250_mca.c index d20abf04541e..d20abf04541e 100644 --- a/drivers/tty/serial/8250_mca.c +++ b/drivers/tty/serial/8250/8250_mca.c diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index da2b0b0a183f..da2b0b0a183f 100644 --- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c diff --git a/drivers/tty/serial/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index a2f236510ff1..a2f236510ff1 100644 --- a/drivers/tty/serial/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig new file mode 100644 index 000000000000..591f8018e7dd --- /dev/null +++ b/drivers/tty/serial/8250/Kconfig @@ -0,0 +1,280 @@ +# +# The 8250/16550 serial drivers. You shouldn't be in this list unless +# you somehow have an implicit or explicit dependency on SERIAL_8250. +# + +config SERIAL_8250 + tristate "8250/16550 and compatible serial support" + select SERIAL_CORE + ---help--- + This selects whether you want to include the driver for the standard + serial ports. The standard answer is Y. People who might say N + here are those that are setting up dedicated Ethernet WWW/FTP + servers, or users that have one of the various bus mice instead of a + serial mouse and don't intend to use their machine's standard serial + port for anything. (Note that the Cyclades and Stallion multi + serial port drivers do not need this driver built in for them to + work.) + + To compile this driver as a module, choose M here: the + module will be called 8250. + [WARNING: Do not compile this driver as a module if you are using + non-standard serial ports, since the configuration information will + be lost when the driver is unloaded. This limitation may be lifted + in the future.] + + BTW1: If you have a mouseman serial mouse which is not recognized by + the X window system, try running gpm first. + + BTW2: If you intend to use a software modem (also called Winmodem) + under Linux, forget it. These modems are crippled and require + proprietary drivers which are only available under Windows. + + Most people will say Y or M here, so that they can use serial mice, + modems and similar devices connecting to the standard serial ports. + +config SERIAL_8250_CONSOLE + bool "Console on 8250/16550 and compatible serial port" + depends on SERIAL_8250=y + select SERIAL_CORE_CONSOLE + ---help--- + If you say Y here, it will be possible to use a serial port as the + system console (the system console is the device which receives all + kernel messages and warnings and which allows logins in single user + mode). This could be useful if some terminal or printer is connected + to that serial port. + + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttyS1". (Try "man bootparam" or see the documentation of + your boot loader (grub or lilo or loadlin) about how to pass options + to the kernel at boot time.) + + If you don't have a VGA card installed and you say Y here, the + kernel will automatically use the first serial line, /dev/ttyS0, as + system console. + + You can set that using a kernel command line option such as + "console=uart8250,io,0x3f8,9600n8" + "console=uart8250,mmio,0xff5e0000,115200n8". + and it will switch to normal serial console when the corresponding + port is ready. + "earlycon=uart8250,io,0x3f8,9600n8" + "earlycon=uart8250,mmio,0xff5e0000,115200n8". + it will not only setup early console. + + If unsure, say N. + +config FIX_EARLYCON_MEM + bool + depends on X86 + default y + +config SERIAL_8250_GSC + tristate + depends on SERIAL_8250 && GSC + default SERIAL_8250 + +config SERIAL_8250_PCI + tristate "8250/16550 PCI device support" if EXPERT + depends on SERIAL_8250 && PCI + default SERIAL_8250 + help + This builds standard PCI serial support. You may be able to + disable this feature if you only need legacy serial support. + Saves about 9K. + +config SERIAL_8250_PNP + tristate "8250/16550 PNP device support" if EXPERT + depends on SERIAL_8250 && PNP + default SERIAL_8250 + help + This builds standard PNP serial support. You may be able to + disable this feature if you only need legacy serial support. + +config SERIAL_8250_HP300 + tristate + depends on SERIAL_8250 && HP300 + default SERIAL_8250 + +config SERIAL_8250_CS + tristate "8250/16550 PCMCIA device support" + depends on PCMCIA && SERIAL_8250 + ---help--- + Say Y here to enable support for 16-bit PCMCIA serial devices, + including serial port cards, modems, and the modem functions of + multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are + credit-card size devices often used with laptops.) + + To compile this driver as a module, choose M here: the + module will be called serial_cs. + + If unsure, say N. + +config SERIAL_8250_NR_UARTS + int "Maximum number of 8250/16550 serial ports" + depends on SERIAL_8250 + default "4" + help + Set this to the number of serial ports you want the driver + to support. This includes any ports discovered via ACPI or + PCI enumeration and any ports that may be added at run-time + via hot-plug, or any ISA multi-port serial cards. + +config SERIAL_8250_RUNTIME_UARTS + int "Number of 8250/16550 serial ports to register at runtime" + depends on SERIAL_8250 + range 0 SERIAL_8250_NR_UARTS + default "4" + help + Set this to the maximum number of serial ports you want + the kernel to register at boot time. This can be overridden + with the module parameter "nr_uarts", or boot-time parameter + 8250.nr_uarts + +config SERIAL_8250_EXTENDED + bool "Extended 8250/16550 serial driver options" + depends on SERIAL_8250 + help + If you wish to use any non-standard features of the standard "dumb" + driver, say Y here. This includes HUB6 support, shared serial + interrupts, special multiport support, support for more than the + four COM 1/2/3/4 boards, etc. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about serial driver options. If unsure, say N. + +config SERIAL_8250_MANY_PORTS + bool "Support more than 4 legacy serial ports" + depends on SERIAL_8250_EXTENDED && !IA64 + help + Say Y here if you have dumb serial boards other than the four + standard COM 1/2/3/4 ports. This may happen if you have an AST + FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available + from <http://www.tldp.org/docs.html#howto>), or other custom + serial port hardware which acts similar to standard serial port + hardware. If you only use the standard COM 1/2/3/4 ports, you can + say N here to save some memory. You can also say Y if you have an + "intelligent" multiport card such as Cyclades, Digiboards, etc. + +# +# Multi-port serial cards +# + +config SERIAL_8250_FOURPORT + tristate "Support Fourport cards" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + Say Y here if you have an AST FourPort serial board. + + To compile this driver as a module, choose M here: the module + will be called 8250_fourport. + +config SERIAL_8250_ACCENT + tristate "Support Accent cards" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + Say Y here if you have an Accent Async serial board. + + To compile this driver as a module, choose M here: the module + will be called 8250_accent. + +config SERIAL_8250_BOCA + tristate "Support Boca cards" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + Say Y here if you have a Boca serial board. Please read the Boca + mini-HOWTO, available from <http://www.tldp.org/docs.html#howto> + + To compile this driver as a module, choose M here: the module + will be called 8250_boca. + +config SERIAL_8250_EXAR_ST16C554 + tristate "Support Exar ST16C554/554D Quad UART" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + The Uplogix Envoy TU301 uses this Exar Quad UART. If you are + tinkering with your Envoy TU301, or have a machine with this UART, + say Y here. + + To compile this driver as a module, choose M here: the module + will be called 8250_exar_st16c554. + +config SERIAL_8250_HUB6 + tristate "Support Hub6 cards" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + Say Y here if you have a HUB6 serial board. + + To compile this driver as a module, choose M here: the module + will be called 8250_hub6. + +# +# Misc. options/drivers. +# + +config SERIAL_8250_SHARE_IRQ + bool "Support for sharing serial interrupts" + depends on SERIAL_8250_EXTENDED + help + Some serial boards have hardware support which allows multiple dumb + serial ports on the same board to share a single IRQ. To enable + support for this in the serial driver, say Y here. + +config SERIAL_8250_DETECT_IRQ + bool "Autodetect IRQ on standard ports (unsafe)" + depends on SERIAL_8250_EXTENDED + help + Say Y here if you want the kernel to try to guess which IRQ + to use for your serial port. + + This is considered unsafe; it is far better to configure the IRQ in + a boot script using the setserial command. + + If unsure, say N. + +config SERIAL_8250_RSA + bool "Support RSA serial ports" + depends on SERIAL_8250_EXTENDED + help + ::: To be written ::: + +config SERIAL_8250_MCA + tristate "Support 8250-type ports on MCA buses" + depends on SERIAL_8250 != n && MCA + help + Say Y here if you have a MCA serial ports. + + To compile this driver as a module, choose M here: the module + will be called 8250_mca. + +config SERIAL_8250_ACORN + tristate "Acorn expansion card serial port support" + depends on ARCH_ACORN && SERIAL_8250 + help + If you have an Atomwide Serial card or Serial Port card for an Acorn + system, say Y to this option. The driver can handle 1, 2, or 3 port + cards. If unsure, say N. + +config SERIAL_8250_RM9K + bool "Support for MIPS RM9xxx integrated serial port" + depends on SERIAL_8250 != n && SERIAL_RM9000 + select SERIAL_8250_SHARE_IRQ + help + Selecting this option will add support for the integrated serial + port hardware found on MIPS RM9122 and similar processors. + If unsure, say N. + +config SERIAL_8250_FSL + bool + depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550 + default PPC + +config SERIAL_8250_DW + tristate "Support for Synopsys DesignWare 8250 quirks" + depends on SERIAL_8250 && OF + help + Selecting this option will enable handling of the extra features + present in the Synopsys DesignWare APB UART. diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile new file mode 100644 index 000000000000..867bba738908 --- /dev/null +++ b/drivers/tty/serial/8250/Makefile @@ -0,0 +1,20 @@ +# +# Makefile for the 8250 serial device drivers. +# + +obj-$(CONFIG_SERIAL_8250) += 8250.o +obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o +obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o +obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o +obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o +obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o +obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o +obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o +obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o +obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o +obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o +obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o +obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o +obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o +obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/8250/m32r_sio.c index 94a6792bf97b..94a6792bf97b 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/8250/m32r_sio.c diff --git a/drivers/tty/serial/m32r_sio.h b/drivers/tty/serial/8250/m32r_sio.h index e9b7e11793b1..e9b7e11793b1 100644 --- a/drivers/tty/serial/m32r_sio.h +++ b/drivers/tty/serial/8250/m32r_sio.h diff --git a/drivers/tty/serial/m32r_sio_reg.h b/drivers/tty/serial/8250/m32r_sio_reg.h index 4671473793e3..4671473793e3 100644 --- a/drivers/tty/serial/m32r_sio_reg.h +++ b/drivers/tty/serial/8250/m32r_sio_reg.h diff --git a/drivers/tty/serial/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 86090605a84e..86090605a84e 100644 --- a/drivers/tty/serial/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index aca2386c5ef1..2de99248dfae 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -5,279 +5,7 @@ menu "Serial drivers" depends on HAS_IOMEM -# -# The new 8250/16550 serial drivers -config SERIAL_8250 - tristate "8250/16550 and compatible serial support" - select SERIAL_CORE - ---help--- - This selects whether you want to include the driver for the standard - serial ports. The standard answer is Y. People who might say N - here are those that are setting up dedicated Ethernet WWW/FTP - servers, or users that have one of the various bus mice instead of a - serial mouse and don't intend to use their machine's standard serial - port for anything. (Note that the Cyclades and Stallion multi - serial port drivers do not need this driver built in for them to - work.) - - To compile this driver as a module, choose M here: the - module will be called 8250. - [WARNING: Do not compile this driver as a module if you are using - non-standard serial ports, since the configuration information will - be lost when the driver is unloaded. This limitation may be lifted - in the future.] - - BTW1: If you have a mouseman serial mouse which is not recognized by - the X window system, try running gpm first. - - BTW2: If you intend to use a software modem (also called Winmodem) - under Linux, forget it. These modems are crippled and require - proprietary drivers which are only available under Windows. - - Most people will say Y or M here, so that they can use serial mice, - modems and similar devices connecting to the standard serial ports. - -config SERIAL_8250_CONSOLE - bool "Console on 8250/16550 and compatible serial port" - depends on SERIAL_8250=y - select SERIAL_CORE_CONSOLE - ---help--- - If you say Y here, it will be possible to use a serial port as the - system console (the system console is the device which receives all - kernel messages and warnings and which allows logins in single user - mode). This could be useful if some terminal or printer is connected - to that serial port. - - Even if you say Y here, the currently visible virtual console - (/dev/tty0) will still be used as the system console by default, but - you can alter that using a kernel command line option such as - "console=ttyS1". (Try "man bootparam" or see the documentation of - your boot loader (grub or lilo or loadlin) about how to pass options - to the kernel at boot time.) - - If you don't have a VGA card installed and you say Y here, the - kernel will automatically use the first serial line, /dev/ttyS0, as - system console. - - You can set that using a kernel command line option such as - "console=uart8250,io,0x3f8,9600n8" - "console=uart8250,mmio,0xff5e0000,115200n8". - and it will switch to normal serial console when the corresponding - port is ready. - "earlycon=uart8250,io,0x3f8,9600n8" - "earlycon=uart8250,mmio,0xff5e0000,115200n8". - it will not only setup early console. - - If unsure, say N. - -config FIX_EARLYCON_MEM - bool - depends on X86 - default y - -config SERIAL_8250_GSC - tristate - depends on SERIAL_8250 && GSC - default SERIAL_8250 - -config SERIAL_8250_PCI - tristate "8250/16550 PCI device support" if EXPERT - depends on SERIAL_8250 && PCI - default SERIAL_8250 - help - This builds standard PCI serial support. You may be able to - disable this feature if you only need legacy serial support. - Saves about 9K. - -config SERIAL_8250_PNP - tristate "8250/16550 PNP device support" if EXPERT - depends on SERIAL_8250 && PNP - default SERIAL_8250 - help - This builds standard PNP serial support. You may be able to - disable this feature if you only need legacy serial support. - -config SERIAL_8250_FSL - bool - depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550 - default PPC - -config SERIAL_8250_HP300 - tristate - depends on SERIAL_8250 && HP300 - default SERIAL_8250 - -config SERIAL_8250_CS - tristate "8250/16550 PCMCIA device support" - depends on PCMCIA && SERIAL_8250 - ---help--- - Say Y here to enable support for 16-bit PCMCIA serial devices, - including serial port cards, modems, and the modem functions of - multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are - credit-card size devices often used with laptops.) - - To compile this driver as a module, choose M here: the - module will be called serial_cs. - - If unsure, say N. - -config SERIAL_8250_NR_UARTS - int "Maximum number of 8250/16550 serial ports" - depends on SERIAL_8250 - default "4" - help - Set this to the number of serial ports you want the driver - to support. This includes any ports discovered via ACPI or - PCI enumeration and any ports that may be added at run-time - via hot-plug, or any ISA multi-port serial cards. - -config SERIAL_8250_RUNTIME_UARTS - int "Number of 8250/16550 serial ports to register at runtime" - depends on SERIAL_8250 - range 0 SERIAL_8250_NR_UARTS - default "4" - help - Set this to the maximum number of serial ports you want - the kernel to register at boot time. This can be overridden - with the module parameter "nr_uarts", or boot-time parameter - 8250.nr_uarts - -config SERIAL_8250_EXTENDED - bool "Extended 8250/16550 serial driver options" - depends on SERIAL_8250 - help - If you wish to use any non-standard features of the standard "dumb" - driver, say Y here. This includes HUB6 support, shared serial - interrupts, special multiport support, support for more than the - four COM 1/2/3/4 boards, etc. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about serial driver options. If unsure, say N. - -config SERIAL_8250_MANY_PORTS - bool "Support more than 4 legacy serial ports" - depends on SERIAL_8250_EXTENDED && !IA64 - help - Say Y here if you have dumb serial boards other than the four - standard COM 1/2/3/4 ports. This may happen if you have an AST - FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available - from <http://www.tldp.org/docs.html#howto>), or other custom - serial port hardware which acts similar to standard serial port - hardware. If you only use the standard COM 1/2/3/4 ports, you can - say N here to save some memory. You can also say Y if you have an - "intelligent" multiport card such as Cyclades, Digiboards, etc. - -# -# Multi-port serial cards -# - -config SERIAL_8250_FOURPORT - tristate "Support Fourport cards" - depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS - help - Say Y here if you have an AST FourPort serial board. - - To compile this driver as a module, choose M here: the module - will be called 8250_fourport. - -config SERIAL_8250_ACCENT - tristate "Support Accent cards" - depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS - help - Say Y here if you have an Accent Async serial board. - - To compile this driver as a module, choose M here: the module - will be called 8250_accent. - -config SERIAL_8250_BOCA - tristate "Support Boca cards" - depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS - help - Say Y here if you have a Boca serial board. Please read the Boca - mini-HOWTO, available from <http://www.tldp.org/docs.html#howto> - - To compile this driver as a module, choose M here: the module - will be called 8250_boca. - -config SERIAL_8250_EXAR_ST16C554 - tristate "Support Exar ST16C554/554D Quad UART" - depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS - help - The Uplogix Envoy TU301 uses this Exar Quad UART. If you are - tinkering with your Envoy TU301, or have a machine with this UART, - say Y here. - - To compile this driver as a module, choose M here: the module - will be called 8250_exar_st16c554. - -config SERIAL_8250_HUB6 - tristate "Support Hub6 cards" - depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS - help - Say Y here if you have a HUB6 serial board. - - To compile this driver as a module, choose M here: the module - will be called 8250_hub6. - -config SERIAL_8250_SHARE_IRQ - bool "Support for sharing serial interrupts" - depends on SERIAL_8250_EXTENDED - help - Some serial boards have hardware support which allows multiple dumb - serial ports on the same board to share a single IRQ. To enable - support for this in the serial driver, say Y here. - -config SERIAL_8250_DETECT_IRQ - bool "Autodetect IRQ on standard ports (unsafe)" - depends on SERIAL_8250_EXTENDED - help - Say Y here if you want the kernel to try to guess which IRQ - to use for your serial port. - - This is considered unsafe; it is far better to configure the IRQ in - a boot script using the setserial command. - - If unsure, say N. - -config SERIAL_8250_RSA - bool "Support RSA serial ports" - depends on SERIAL_8250_EXTENDED - help - ::: To be written ::: - -config SERIAL_8250_MCA - tristate "Support 8250-type ports on MCA buses" - depends on SERIAL_8250 != n && MCA - help - Say Y here if you have a MCA serial ports. - - To compile this driver as a module, choose M here: the module - will be called 8250_mca. - -config SERIAL_8250_ACORN - tristate "Acorn expansion card serial port support" - depends on ARCH_ACORN && SERIAL_8250 - help - If you have an Atomwide Serial card or Serial Port card for an Acorn - system, say Y to this option. The driver can handle 1, 2, or 3 port - cards. If unsure, say N. - -config SERIAL_8250_RM9K - bool "Support for MIPS RM9xxx integrated serial port" - depends on SERIAL_8250 != n && SERIAL_RM9000 - select SERIAL_8250_SHARE_IRQ - help - Selecting this option will add support for the integrated serial - port hardware found on MIPS RM9122 and similar processors. - If unsure, say N. - -config SERIAL_8250_DW - tristate "Support for Synopsys DesignWare 8250 quirks" - depends on SERIAL_8250 && OF - help - Selecting this option will enable handling of the extra features - present in the Synopsys DesignWare APB UART. +source "drivers/tty/serial/8250/Kconfig" comment "Non-8250 serial port support" @@ -536,15 +264,6 @@ config SERIAL_MAX3107 help MAX3107 chip support -config SERIAL_MAX3107_AAVA - tristate "MAX3107 AAVA platform support" - depends on X86_MRST && SERIAL_MAX3107 && GPIOLIB - select SERIAL_CORE - help - Support for the MAX3107 chip configuration found on the AAVA - platform. Includes the extra initialisation and GPIO support - neded for this device. - config SERIAL_DZ bool "DECstation DZ serial driver" depends on MACH_DECSTATION && 32BIT diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index f5b01f2ce525..fef32e10c851 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -14,22 +14,9 @@ obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o -obj-$(CONFIG_SERIAL_8250) += 8250.o -obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o -obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o -obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o -obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o -obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o -obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o -obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o -obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o -obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o -obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o -obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o -obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o -obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o -obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o -obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o +# Now bring in any enabled 8250/16450/16550 type drivers. +obj-$(CONFIG_SERIAL_8250) += 8250/ + obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o @@ -42,7 +29,6 @@ obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_MAX3107) += max3107.o -obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 9ae024025ff3..6800f5f26241 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -159,6 +159,7 @@ struct uart_amba_port { unsigned int fifosize; /* vendor-specific */ unsigned int lcrh_tx; /* vendor-specific */ unsigned int lcrh_rx; /* vendor-specific */ + unsigned int old_cr; /* state during shutdown */ bool autorts; char type[12]; bool interrupt_may_hang; /* vendor-specific */ @@ -1411,7 +1412,9 @@ static int pl011_startup(struct uart_port *port) while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) barrier(); - cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; + /* restore RTS and DTR */ + cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); + cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; writew(cr, uap->port.membase + UART011_CR); /* Clear pending error interrupts */ @@ -1469,6 +1472,7 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap, static void pl011_shutdown(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int cr; /* * disable all interrupts @@ -1488,9 +1492,16 @@ static void pl011_shutdown(struct uart_port *port) /* * disable the port + * disable the port. It should not disable RTS and DTR. + * Also RTS and DTR state should be preserved to restore + * it during startup(). */ uap->autorts = false; - writew(UART01x_CR_UARTEN | UART011_CR_TXE, uap->port.membase + UART011_CR); + cr = readw(uap->port.membase + UART011_CR); + uap->old_cr = cr; + cr &= UART011_CR_RTS | UART011_CR_DTR; + cr |= UART01x_CR_UARTEN | UART011_CR_TXE; + writew(cr, uap->port.membase + UART011_CR); /* * disable break condition and fifos @@ -1740,9 +1751,19 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) { struct uart_amba_port *uap = amba_ports[co->index]; unsigned int status, old_cr, new_cr; + unsigned long flags; + int locked = 1; clk_enable(uap->clk); + local_irq_save(flags); + if (uap->port.sysrq) + locked = 0; + else if (oops_in_progress) + locked = spin_trylock(&uap->port.lock); + else + spin_lock(&uap->port.lock); + /* * First save the CR then disable the interrupts */ @@ -1762,6 +1783,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) } while (status & UART01x_FR_BUSY); writew(old_cr, uap->port.membase + UART011_CR); + if (locked) + spin_unlock(&uap->port.lock); + local_irq_restore(flags); + clk_disable(uap->clk); } @@ -1905,6 +1930,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->vendor = vendor; uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx; + uap->old_cr = 0; uap->fifosize = vendor->fifosize; uap->interrupt_may_hang = vendor->interrupt_may_hang; uap->port.dev = &dev->dev; diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c index 7c867a046c97..7545fe1b9925 100644 --- a/drivers/tty/serial/jsm/jsm_driver.c +++ b/drivers/tty/serial/jsm/jsm_driver.c @@ -251,6 +251,7 @@ static void jsm_io_resume(struct pci_dev *pdev) struct jsm_board *brd = pci_get_drvdata(pdev); pci_restore_state(pdev); + pci_save_state(pdev); jsm_uart_port_init(brd); } diff --git a/drivers/tty/serial/max3107-aava.c b/drivers/tty/serial/max3107-aava.c deleted file mode 100644 index aae772a71de6..000000000000 --- a/drivers/tty/serial/max3107-aava.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * max3107.c - spi uart protocol driver for Maxim 3107 - * Based on max3100.c - * by Christian Pellegrin <chripell@evolware.org> - * and max3110.c - * by Feng Tang <feng.tang@intel.com> - * - * Copyright (C) Aavamobile 2009 - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - */ - -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/serial_core.h> -#include <linux/serial.h> -#include <linux/spi/spi.h> -#include <linux/freezer.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <linux/sfi.h> -#include <linux/module.h> -#include <asm/mrst.h> -#include "max3107.h" - -/* GPIO direction to input function */ -static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset) -{ - struct max3107_port *s = container_of(chip, struct max3107_port, chip); - u16 buf[1]; /* Buffer for SPI transfer */ - - if (offset >= MAX3107_GPIO_COUNT) { - dev_err(&s->spi->dev, "Invalid GPIO\n"); - return -EINVAL; - } - - /* Read current GPIO configuration register */ - buf[0] = MAX3107_GPIOCFG_REG; - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { - dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n"); - return -EIO; - } - buf[0] &= MAX3107_SPI_RX_DATA_MASK; - - /* Set GPIO to input */ - buf[0] &= ~(0x0001 << offset); - - /* Write new GPIO configuration register value */ - buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, NULL, 2)) { - dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n"); - return -EIO; - } - return 0; -} - -/* GPIO direction to output function */ -static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset, - int value) -{ - struct max3107_port *s = container_of(chip, struct max3107_port, chip); - u16 buf[2]; /* Buffer for SPI transfers */ - - if (offset >= MAX3107_GPIO_COUNT) { - dev_err(&s->spi->dev, "Invalid GPIO\n"); - return -EINVAL; - } - - /* Read current GPIO configuration and data registers */ - buf[0] = MAX3107_GPIOCFG_REG; - buf[1] = MAX3107_GPIODATA_REG; - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { - dev_err(&s->spi->dev, "SPI transfer gpio failed\n"); - return -EIO; - } - buf[0] &= MAX3107_SPI_RX_DATA_MASK; - buf[1] &= MAX3107_SPI_RX_DATA_MASK; - - /* Set GPIO to output */ - buf[0] |= (0x0001 << offset); - /* Set value */ - if (value) - buf[1] |= (0x0001 << offset); - else - buf[1] &= ~(0x0001 << offset); - - /* Write new GPIO configuration and data register values */ - buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); - buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, NULL, 4)) { - dev_err(&s->spi->dev, - "SPI transfer for GPIO conf data w failed\n"); - return -EIO; - } - return 0; -} - -/* GPIO value query function */ -static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct max3107_port *s = container_of(chip, struct max3107_port, chip); - u16 buf[1]; /* Buffer for SPI transfer */ - - if (offset >= MAX3107_GPIO_COUNT) { - dev_err(&s->spi->dev, "Invalid GPIO\n"); - return -EINVAL; - } - - /* Read current GPIO data register */ - buf[0] = MAX3107_GPIODATA_REG; - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { - dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n"); - return -EIO; - } - buf[0] &= MAX3107_SPI_RX_DATA_MASK; - - /* Return value */ - return buf[0] & (0x0001 << offset); -} - -/* GPIO value set function */ -static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct max3107_port *s = container_of(chip, struct max3107_port, chip); - u16 buf[2]; /* Buffer for SPI transfers */ - - if (offset >= MAX3107_GPIO_COUNT) { - dev_err(&s->spi->dev, "Invalid GPIO\n"); - return; - } - - /* Read current GPIO configuration registers*/ - buf[0] = MAX3107_GPIODATA_REG; - buf[1] = MAX3107_GPIOCFG_REG; - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { - dev_err(&s->spi->dev, - "SPI transfer for GPIO data and config read failed\n"); - return; - } - buf[0] &= MAX3107_SPI_RX_DATA_MASK; - buf[1] &= MAX3107_SPI_RX_DATA_MASK; - - if (!(buf[1] & (0x0001 << offset))) { - /* Configured as input, can't set value */ - dev_warn(&s->spi->dev, - "Trying to set value for input GPIO\n"); - return; - } - - /* Set value */ - if (value) - buf[0] |= (0x0001 << offset); - else - buf[0] &= ~(0x0001 << offset); - - /* Write new GPIO data register value */ - buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, NULL, 2)) - dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n"); -} - -/* GPIO chip data */ -static struct gpio_chip max3107_gpio_chip = { - .owner = THIS_MODULE, - .direction_input = max3107_gpio_direction_in, - .direction_output = max3107_gpio_direction_out, - .get = max3107_gpio_get, - .set = max3107_gpio_set, - .can_sleep = 1, - .base = MAX3107_GPIO_BASE, - .ngpio = MAX3107_GPIO_COUNT, -}; - -/** - * max3107_aava_reset - reset on AAVA systems - * @spi: The SPI device we are probing - * - * Reset the device ready for probing. - */ - -static int max3107_aava_reset(struct spi_device *spi) -{ - /* Reset the chip */ - if (gpio_request(MAX3107_RESET_GPIO, "max3107")) { - pr_err("Requesting RESET GPIO failed\n"); - return -EIO; - } - if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) { - pr_err("Setting RESET GPIO to 0 failed\n"); - gpio_free(MAX3107_RESET_GPIO); - return -EIO; - } - msleep(MAX3107_RESET_DELAY); - if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) { - pr_err("Setting RESET GPIO to 1 failed\n"); - gpio_free(MAX3107_RESET_GPIO); - return -EIO; - } - gpio_free(MAX3107_RESET_GPIO); - msleep(MAX3107_WAKEUP_DELAY); - return 0; -} - -static int max3107_aava_configure(struct max3107_port *s) -{ - int retval; - - /* Initialize GPIO chip data */ - s->chip = max3107_gpio_chip; - s->chip.label = s->spi->modalias; - s->chip.dev = &s->spi->dev; - - /* Add GPIO chip */ - retval = gpiochip_add(&s->chip); - if (retval) { - dev_err(&s->spi->dev, "Adding GPIO chip failed\n"); - return retval; - } - - /* Temporary fix for EV2 boot problems, set modem reset to 0 */ - max3107_gpio_direction_out(&s->chip, 3, 0); - return 0; -} - -#if 0 -/* This will get enabled once we have the board stuff merged for this - specific case */ - -static const struct baud_table brg13_ext[] = { - { 300, MAX3107_BRG13_B300 }, - { 600, MAX3107_BRG13_B600 }, - { 1200, MAX3107_BRG13_B1200 }, - { 2400, MAX3107_BRG13_B2400 }, - { 4800, MAX3107_BRG13_B4800 }, - { 9600, MAX3107_BRG13_B9600 }, - { 19200, MAX3107_BRG13_B19200 }, - { 57600, MAX3107_BRG13_B57600 }, - { 115200, MAX3107_BRG13_B115200 }, - { 230400, MAX3107_BRG13_B230400 }, - { 460800, MAX3107_BRG13_B460800 }, - { 921600, MAX3107_BRG13_B921600 }, - { 0, 0 } -}; - -static void max3107_aava_init(struct max3107_port *s) -{ - /*override for AAVA SC specific*/ - if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) { - if (get_koski_build_id() <= KOSKI_EV2) - if (s->ext_clk) { - s->brg_cfg = MAX3107_BRG13_B9600; - s->baud_tbl = (struct baud_table *)brg13_ext; - } - } -} -#endif - -static int __devexit max3107_aava_remove(struct spi_device *spi) -{ - struct max3107_port *s = dev_get_drvdata(&spi->dev); - - /* Remove GPIO chip */ - if (gpiochip_remove(&s->chip)) - dev_warn(&spi->dev, "Removing GPIO chip failed\n"); - - /* Then do the default remove */ - return max3107_remove(spi); -} - -/* Platform data */ -static struct max3107_plat aava_plat_data = { - .loopback = 0, - .ext_clk = 1, -/* .init = max3107_aava_init, */ - .configure = max3107_aava_configure, - .hw_suspend = max3107_hw_susp, - .polled_mode = 0, - .poll_time = 0, -}; - - -static int __devinit max3107_probe_aava(struct spi_device *spi) -{ - int err = max3107_aava_reset(spi); - if (err < 0) - return err; - return max3107_probe(spi, &aava_plat_data); -} - -/* Spi driver data */ -static struct spi_driver max3107_driver = { - .driver = { - .name = "aava-max3107", - .owner = THIS_MODULE, - }, - .probe = max3107_probe_aava, - .remove = __devexit_p(max3107_aava_remove), - .suspend = max3107_suspend, - .resume = max3107_resume, -}; - -/* Driver init function */ -static int __init max3107_init(void) -{ - return spi_register_driver(&max3107_driver); -} - -/* Driver exit function */ -static void __exit max3107_exit(void) -{ - spi_unregister_driver(&max3107_driver); -} - -module_init(max3107_init); -module_exit(max3107_exit); - -MODULE_DESCRIPTION("MAX3107 driver"); -MODULE_AUTHOR("Aavamobile"); -MODULE_ALIAS("spi:aava-max3107"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index d192dcbb82f5..1c2426931484 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1160,7 +1160,7 @@ static struct uart_driver serial_omap_reg = { .cons = OMAP_CONSOLE, }; -#ifdef CONFIG_SUSPEND +#ifdef CONFIG_PM_SLEEP static int serial_omap_suspend(struct device *dev) { struct uart_omap_port *up = dev_get_drvdata(dev); @@ -1521,6 +1521,7 @@ static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1) } } +#ifdef CONFIG_PM_RUNTIME static void serial_omap_restore_context(struct uart_omap_port *up) { if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) @@ -1550,7 +1551,6 @@ static void serial_omap_restore_context(struct uart_omap_port *up) serial_out(up, UART_OMAP_MDR1, up->mdr1); } -#ifdef CONFIG_PM_RUNTIME static int serial_omap_runtime_suspend(struct device *dev) { struct uart_omap_port *up = dev_get_drvdata(dev); diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index c7bf31a6a7e7..13056180adf5 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2348,11 +2348,11 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) */ tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev); if (likely(!IS_ERR(tty_dev))) { - device_init_wakeup(tty_dev, 1); - device_set_wakeup_enable(tty_dev, 0); - } else + device_set_wakeup_capable(tty_dev, 1); + } else { printk(KERN_ERR "Cannot register tty device on line %d\n", uport->line); + } /* * Ensure UPF_DEAD is not set. diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index ef9dd628ba0b..bf6e238146ae 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -227,7 +227,6 @@ int tty_port_block_til_ready(struct tty_port *port, int do_clocal = 0, retval; unsigned long flags; DEFINE_WAIT(wait); - int cd; /* block if port is in the process of being closed */ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { @@ -284,11 +283,14 @@ int tty_port_block_til_ready(struct tty_port *port, retval = -ERESTARTSYS; break; } - /* Probe the carrier. For devices with no carrier detect this - will always return true */ - cd = tty_port_carrier_raised(port); + /* + * Probe the carrier. For devices with no carrier detect + * tty_port_carrier_raised will always return true. + * Never ask drivers if CLOCAL is set, this causes troubles + * on some hardware. + */ if (!(port->flags & ASYNC_CLOSING) && - (do_clocal || cd)) + (do_clocal || tty_port_carrier_raised(port))) break; if (signal_pending(current)) { retval = -ERESTARTSYS; diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 5e096f43bcea..65447c5f91d7 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -1463,7 +1463,6 @@ compat_kdfontop_ioctl(struct compat_console_font_op __user *fontop, if (!perm && op->op != KD_FONT_OP_GET) return -EPERM; op->data = compat_ptr(((struct compat_console_font_op *)op)->data); - op->flags |= KD_FONT_FLAG_OLD; i = con_font_op(vc, op); if (i) return i; diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 1c50baff7725..d2b3cffca3f7 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -57,6 +57,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); #define WDM_MAX 16 +/* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */ +#define WDM_DEFAULT_BUFSIZE 256 static DEFINE_MUTEX(wdm_mutex); @@ -88,7 +90,8 @@ struct wdm_device { int count; dma_addr_t shandle; dma_addr_t ihandle; - struct mutex lock; + struct mutex wlock; + struct mutex rlock; wait_queue_head_t wait; struct work_struct rxwork; int werr; @@ -323,7 +326,7 @@ static ssize_t wdm_write } /* concurrent writes and disconnect */ - r = mutex_lock_interruptible(&desc->lock); + r = mutex_lock_interruptible(&desc->wlock); rv = -ERESTARTSYS; if (r) { kfree(buf); @@ -386,7 +389,7 @@ static ssize_t wdm_write out: usb_autopm_put_interface(desc->intf); outnp: - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); outnl: return rv < 0 ? rv : count; } @@ -399,7 +402,7 @@ static ssize_t wdm_read struct wdm_device *desc = file->private_data; - rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */ + rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */ if (rv < 0) return -ERESTARTSYS; @@ -467,14 +470,16 @@ retry: for (i = 0; i < desc->length - cntr; i++) desc->ubuf[i] = desc->ubuf[i + cntr]; + spin_lock_irq(&desc->iuspin); desc->length -= cntr; + spin_unlock_irq(&desc->iuspin); /* in case we had outstanding data */ if (!desc->length) clear_bit(WDM_READ, &desc->flags); rv = cntr; err: - mutex_unlock(&desc->lock); + mutex_unlock(&desc->rlock); return rv; } @@ -540,7 +545,8 @@ static int wdm_open(struct inode *inode, struct file *file) } intf->needs_remote_wakeup = 1; - mutex_lock(&desc->lock); + /* using write lock to protect desc->count */ + mutex_lock(&desc->wlock); if (!desc->count++) { desc->werr = 0; desc->rerr = 0; @@ -553,7 +559,7 @@ static int wdm_open(struct inode *inode, struct file *file) } else { rv = 0; } - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); usb_autopm_put_interface(desc->intf); out: mutex_unlock(&wdm_mutex); @@ -565,9 +571,11 @@ static int wdm_release(struct inode *inode, struct file *file) struct wdm_device *desc = file->private_data; mutex_lock(&wdm_mutex); - mutex_lock(&desc->lock); + + /* using write lock to protect desc->count */ + mutex_lock(&desc->wlock); desc->count--; - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); if (!desc->count) { dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); @@ -630,7 +638,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) struct usb_cdc_dmm_desc *dmhd; u8 *buffer = intf->altsetting->extra; int buflen = intf->altsetting->extralen; - u16 maxcom = 0; + u16 maxcom = WDM_DEFAULT_BUFSIZE; if (!buffer) goto out; @@ -665,7 +673,8 @@ next_desc: desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); if (!desc) goto out; - mutex_init(&desc->lock); + mutex_init(&desc->rlock); + mutex_init(&desc->wlock); spin_lock_init(&desc->iuspin); init_waitqueue_head(&desc->wait); desc->wMaxCommand = maxcom; @@ -716,7 +725,7 @@ next_desc: goto err; desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf), - desc->bMaxPacketSize0, + desc->wMaxCommand, GFP_KERNEL, &desc->response->transfer_dma); if (!desc->inbuf) @@ -779,11 +788,13 @@ static void wdm_disconnect(struct usb_interface *intf) /* to terminate pending flushes */ clear_bit(WDM_IN_USE, &desc->flags); spin_unlock_irqrestore(&desc->iuspin, flags); - mutex_lock(&desc->lock); + wake_up_all(&desc->wait); + mutex_lock(&desc->rlock); + mutex_lock(&desc->wlock); kill_urbs(desc); cancel_work_sync(&desc->rxwork); - mutex_unlock(&desc->lock); - wake_up_all(&desc->wait); + mutex_unlock(&desc->wlock); + mutex_unlock(&desc->rlock); if (!desc->count) cleanup(desc); mutex_unlock(&wdm_mutex); @@ -798,8 +809,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); /* if this is an autosuspend the caller does the locking */ - if (!PMSG_IS_AUTO(message)) - mutex_lock(&desc->lock); + if (!PMSG_IS_AUTO(message)) { + mutex_lock(&desc->rlock); + mutex_lock(&desc->wlock); + } spin_lock_irq(&desc->iuspin); if (PMSG_IS_AUTO(message) && @@ -815,8 +828,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) kill_urbs(desc); cancel_work_sync(&desc->rxwork); } - if (!PMSG_IS_AUTO(message)) - mutex_unlock(&desc->lock); + if (!PMSG_IS_AUTO(message)) { + mutex_unlock(&desc->wlock); + mutex_unlock(&desc->rlock); + } return rv; } @@ -854,7 +869,8 @@ static int wdm_pre_reset(struct usb_interface *intf) { struct wdm_device *desc = usb_get_intfdata(intf); - mutex_lock(&desc->lock); + mutex_lock(&desc->rlock); + mutex_lock(&desc->wlock); kill_urbs(desc); /* @@ -876,7 +892,8 @@ static int wdm_post_reset(struct usb_interface *intf) int rv; rv = recover_from_urb_loss(desc); - mutex_unlock(&desc->lock); + mutex_unlock(&desc->wlock); + mutex_unlock(&desc->rlock); return 0; } diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 2f51de57593a..c8df1dd967ef 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -126,7 +126,6 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, struct dwc3_request *req) { struct dwc3 *dwc = dep->dwc; - u32 type; int ret = 0; req->request.actual = 0; @@ -149,20 +148,14 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, direction = !!(dep->flags & DWC3_EP0_DIR_IN); - if (dwc->ep0state == EP0_STATUS_PHASE) { - type = dwc->three_stage_setup - ? DWC3_TRBCTL_CONTROL_STATUS3 - : DWC3_TRBCTL_CONTROL_STATUS2; - } else if (dwc->ep0state == EP0_DATA_PHASE) { - type = DWC3_TRBCTL_CONTROL_DATA; - } else { - /* should never happen */ - WARN_ON(1); + if (dwc->ep0state != EP0_DATA_PHASE) { + dev_WARN(dwc->dev, "Unexpected pending request\n"); return 0; } ret = dwc3_ep0_start_trans(dwc, direction, - req->request.dma, req->request.length, type); + req->request.dma, req->request.length, + DWC3_TRBCTL_CONTROL_DATA); dep->flags &= ~(DWC3_EP_PENDING_REQUEST | DWC3_EP0_DIR_IN); } else if (dwc->delayed_status) { diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index a696bde53222..064b6e2cd411 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -101,7 +101,7 @@ void dwc3_unmap_buffer_from_dma(struct dwc3_request *req) if (req->request.num_mapped_sgs) { req->request.dma = DMA_ADDR_INVALID; dma_unmap_sg(dwc->dev, req->request.sg, - req->request.num_sgs, + req->request.num_mapped_sgs, req->direction ? DMA_TO_DEVICE : DMA_FROM_DEVICE); diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index a95de6a4a134..baaebf2830fc 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -175,13 +175,12 @@ ep_found: _ep->comp_desc = comp_desc; if (g->speed == USB_SPEED_SUPER) { switch (usb_endpoint_type(_ep->desc)) { - case USB_ENDPOINT_XFER_BULK: - case USB_ENDPOINT_XFER_INT: - _ep->maxburst = comp_desc->bMaxBurst; - break; case USB_ENDPOINT_XFER_ISOC: /* mult: bits 1:0 of bmAttributes */ _ep->mult = comp_desc->bmAttributes & 0x3; + case USB_ENDPOINT_XFER_BULK: + case USB_ENDPOINT_XFER_INT: + _ep->maxburst = comp_desc->bMaxBurst; break; default: /* Do nothing for control endpoints */ diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 753aa0683ac1..e0e6375ef5dd 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -126,7 +126,7 @@ ep_matches ( * descriptor and see if the EP matches it */ if (usb_endpoint_xfer_bulk(desc)) { - if (ep_comp) { + if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) { num_req_streams = ep_comp->bmAttributes & 0x1f; if (num_req_streams > ep->max_streams) return 0; diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 6353eca1e852..ee8ceec01560 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -3123,15 +3123,15 @@ fsg_add(struct usb_composite_dev *cdev, struct usb_configuration *c, struct fsg_module_parameters { char *file[FSG_MAX_LUNS]; - int ro[FSG_MAX_LUNS]; - int removable[FSG_MAX_LUNS]; - int cdrom[FSG_MAX_LUNS]; - int nofua[FSG_MAX_LUNS]; + bool ro[FSG_MAX_LUNS]; + bool removable[FSG_MAX_LUNS]; + bool cdrom[FSG_MAX_LUNS]; + bool nofua[FSG_MAX_LUNS]; unsigned int file_count, ro_count, removable_count, cdrom_count; unsigned int nofua_count; unsigned int luns; /* nluns */ - int stall; /* can_stall */ + bool stall; /* can_stall */ }; #define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \ diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index d7ea6c076ce9..b04712f19f1e 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1430,7 +1430,7 @@ static void setup_received_irq(struct fsl_udc *udc, int pipe = get_pipe_by_windex(wIndex); struct fsl_ep *ep; - if (wValue != 0 || wLength != 0 || pipe > udc->max_ep) + if (wValue != 0 || wLength != 0 || pipe >= udc->max_ep) break; ep = get_ep_by_pipe(udc, pipe); @@ -1673,7 +1673,7 @@ static void dtd_complete_irq(struct fsl_udc *udc) if (!bit_pos) return; - for (i = 0; i < udc->max_ep * 2; i++) { + for (i = 0; i < udc->max_ep; i++) { ep_num = i >> 1; direction = i % 2; diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index fa0fcc11263f..e2293c1588ee 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -11,11 +11,6 @@ /* #undef DEBUG */ /* #undef VERBOSE_DEBUG */ -#if defined(CONFIG_USB_LANGWELL_OTG) -#define OTG_TRANSCEIVER -#endif - - #include <linux/module.h> #include <linux/pci.h> #include <linux/dma-mapping.h> @@ -1522,8 +1517,7 @@ static void langwell_udc_stop(struct langwell_udc *dev) /* stop all USB activities */ -static void stop_activity(struct langwell_udc *dev, - struct usb_gadget_driver *driver) +static void stop_activity(struct langwell_udc *dev) { struct langwell_ep *ep; dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); @@ -1535,9 +1529,9 @@ static void stop_activity(struct langwell_udc *dev, } /* report disconnect; the driver is already quiesced */ - if (driver) { + if (dev->driver) { spin_unlock(&dev->lock); - driver->disconnect(&dev->gadget); + dev->driver->disconnect(&dev->gadget); spin_lock(&dev->lock); } @@ -1925,11 +1919,10 @@ static int langwell_stop(struct usb_gadget *g, /* stop all usb activities */ dev->gadget.speed = USB_SPEED_UNKNOWN; - stop_activity(dev, driver); - spin_unlock_irqrestore(&dev->lock, flags); - dev->gadget.dev.driver = NULL; dev->driver = NULL; + stop_activity(dev); + spin_unlock_irqrestore(&dev->lock, flags); device_remove_file(&dev->pdev->dev, &dev_attr_function); @@ -2315,13 +2308,9 @@ static void handle_setup_packet(struct langwell_udc *dev, if (!gadget_is_otg(&dev->gadget)) break; - else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) { + else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) dev->gadget.b_hnp_enable = 1; -#ifdef OTG_TRANSCEIVER - if (!dev->lotg->otg.default_a) - dev->lotg->hsm.b_hnp_enable = 1; -#endif - } else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT) + else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT) dev->gadget.a_hnp_support = 1; else if (setup->bRequest == USB_DEVICE_A_ALT_HNP_SUPPORT) @@ -2733,7 +2722,7 @@ static void handle_usb_reset(struct langwell_udc *dev) dev->bus_reset = 1; /* reset all the queues, stop all USB activities */ - stop_activity(dev, dev->driver); + stop_activity(dev); dev->usb_state = USB_STATE_DEFAULT; } else { dev_vdbg(&dev->pdev->dev, "device controller reset\n"); @@ -2741,7 +2730,7 @@ static void handle_usb_reset(struct langwell_udc *dev) langwell_udc_reset(dev); /* reset all the queues, stop all USB activities */ - stop_activity(dev, dev->driver); + stop_activity(dev); /* reset ep0 dQH and endptctrl */ ep0_reset(dev); @@ -2752,12 +2741,6 @@ static void handle_usb_reset(struct langwell_udc *dev) dev->usb_state = USB_STATE_ATTACHED; } -#ifdef OTG_TRANSCEIVER - /* refer to USB OTG 6.6.2.3 b_hnp_en is cleared */ - if (!dev->lotg->otg.default_a) - dev->lotg->hsm.b_hnp_enable = 0; -#endif - dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -2770,29 +2753,6 @@ static void handle_bus_suspend(struct langwell_udc *dev) dev->resume_state = dev->usb_state; dev->usb_state = USB_STATE_SUSPENDED; -#ifdef OTG_TRANSCEIVER - if (dev->lotg->otg.default_a) { - if (dev->lotg->hsm.b_bus_suspend_vld == 1) { - dev->lotg->hsm.b_bus_suspend = 1; - /* notify transceiver the state changes */ - if (spin_trylock(&dev->lotg->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&dev->lotg->wq_lock); - } - } - dev->lotg->hsm.b_bus_suspend_vld++; - } else { - if (!dev->lotg->hsm.a_bus_suspend) { - dev->lotg->hsm.a_bus_suspend = 1; - /* notify transceiver the state changes */ - if (spin_trylock(&dev->lotg->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&dev->lotg->wq_lock); - } - } - } -#endif - /* report suspend to the driver */ if (dev->driver) { if (dev->driver->suspend) { @@ -2823,11 +2783,6 @@ static void handle_bus_resume(struct langwell_udc *dev) if (dev->pdev->device != 0x0829) langwell_phy_low_power(dev, 0); -#ifdef OTG_TRANSCEIVER - if (dev->lotg->otg.default_a == 0) - dev->lotg->hsm.a_bus_suspend = 0; -#endif - /* report resume to the driver */ if (dev->driver) { if (dev->driver->resume) { @@ -3020,7 +2975,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) dev->done = &done; -#ifndef OTG_TRANSCEIVER /* free dTD dma_pool and dQH */ if (dev->dtd_pool) dma_pool_destroy(dev->dtd_pool); @@ -3032,7 +2986,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) /* release SRAM caching */ if (dev->has_sram && dev->got_sram) sram_deinit(dev); -#endif if (dev->status_req) { kfree(dev->status_req->req.buf); @@ -3045,7 +2998,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) if (dev->got_irq) free_irq(pdev->irq, dev); -#ifndef OTG_TRANSCEIVER if (dev->cap_regs) iounmap(dev->cap_regs); @@ -3055,13 +3007,6 @@ static void langwell_udc_remove(struct pci_dev *pdev) if (dev->enabled) pci_disable_device(pdev); -#else - if (dev->transceiver) { - otg_put_transceiver(dev->transceiver); - dev->transceiver = NULL; - dev->lotg = NULL; - } -#endif dev->cap_regs = NULL; @@ -3072,9 +3017,7 @@ static void langwell_udc_remove(struct pci_dev *pdev) device_remove_file(&pdev->dev, &dev_attr_langwell_udc); device_remove_file(&pdev->dev, &dev_attr_remote_wakeup); -#ifndef OTG_TRANSCEIVER pci_set_drvdata(pdev, NULL); -#endif /* free dev, wait for the release() finished */ wait_for_completion(&done); @@ -3089,9 +3032,7 @@ static int langwell_udc_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct langwell_udc *dev; -#ifndef OTG_TRANSCEIVER unsigned long resource, len; -#endif void __iomem *base = NULL; size_t size; int retval; @@ -3109,16 +3050,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->pdev = pdev; dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); -#ifdef OTG_TRANSCEIVER - /* PCI device is already enabled by otg_transceiver driver */ - dev->enabled = 1; - - /* mem region and register base */ - dev->region = 1; - dev->transceiver = otg_get_transceiver(); - dev->lotg = otg_to_langwell(dev->transceiver); - base = dev->lotg->regs; -#else pci_set_drvdata(pdev, dev); /* now all the pci goodies ... */ @@ -3139,7 +3070,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->region = 1; base = ioremap_nocache(resource, len); -#endif if (base == NULL) { dev_err(&dev->pdev->dev, "can't map memory\n"); retval = -EFAULT; @@ -3163,7 +3093,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->got_sram = 0; dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram); -#ifndef OTG_TRANSCEIVER /* enable SRAM caching if detected */ if (dev->has_sram && !dev->got_sram) sram_init(dev); @@ -3182,7 +3111,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, goto error; } dev->got_irq = 1; -#endif /* set stopped bit */ dev->stopped = 1; @@ -3257,10 +3185,8 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->remote_wakeup = 0; dev->dev_status = 1 << USB_DEVICE_SELF_POWERED; -#ifndef OTG_TRANSCEIVER /* reset device controller */ langwell_udc_reset(dev); -#endif /* initialize gadget structure */ dev->gadget.ops = &langwell_ops; /* usb_gadget_ops */ @@ -3268,9 +3194,6 @@ static int langwell_udc_probe(struct pci_dev *pdev, INIT_LIST_HEAD(&dev->gadget.ep_list); /* ep_list */ dev->gadget.speed = USB_SPEED_UNKNOWN; /* speed */ dev->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */ -#ifdef OTG_TRANSCEIVER - dev->gadget.is_otg = 1; /* support otg mode */ -#endif /* the "gadget" abstracts/virtualizes the controller */ dev_set_name(&dev->gadget.dev, "gadget"); @@ -3282,10 +3205,8 @@ static int langwell_udc_probe(struct pci_dev *pdev, /* controller endpoints reinit */ eps_reinit(dev); -#ifndef OTG_TRANSCEIVER /* reset ep0 dQH and endptctrl */ ep0_reset(dev); -#endif /* create dTD dma_pool resource */ dev->dtd_pool = dma_pool_create("langwell_dtd", @@ -3367,7 +3288,7 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) spin_lock_irq(&dev->lock); /* stop all usb activities */ - stop_activity(dev, dev->driver); + stop_activity(dev); spin_unlock_irq(&dev->lock); /* free dTD dma_pool and dQH */ @@ -3525,22 +3446,14 @@ static struct pci_driver langwell_pci_driver = { static int __init init(void) { -#ifdef OTG_TRANSCEIVER - return langwell_register_peripheral(&langwell_pci_driver); -#else return pci_register_driver(&langwell_pci_driver); -#endif } module_init(init); static void __exit cleanup(void) { -#ifdef OTG_TRANSCEIVER - return langwell_unregister_peripheral(&langwell_pci_driver); -#else pci_unregister_driver(&langwell_pci_driver); -#endif } module_exit(cleanup); diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h index ef79e242b7b0..d6e78accaffe 100644 --- a/drivers/usb/gadget/langwell_udc.h +++ b/drivers/usb/gadget/langwell_udc.h @@ -8,7 +8,6 @@ */ #include <linux/usb/langwell_udc.h> -#include <linux/usb/langwell_otg.h> /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index c7f291a331df..85ea14e2545e 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -598,16 +598,16 @@ static __maybe_unused struct usb_ss_cap_descriptor fsg_ss_cap_desc = { | USB_5GBPS_OPERATION), .bFunctionalitySupport = USB_LOW_SPEED_OPERATION, .bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT, - .bU2DevExitLat = USB_DEFAULT_U2_DEV_EXIT_LAT, + .bU2DevExitLat = cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT), }; static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = { .bLength = USB_DT_BOS_SIZE, .bDescriptorType = USB_DT_BOS, - .wTotalLength = USB_DT_BOS_SIZE + .wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE + USB_DT_USB_EXT_CAP_SIZE - + USB_DT_USB_SS_CAP_SIZE, + + USB_DT_USB_SS_CAP_SIZE), .bNumDeviceCaps = 2, }; diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index e90344a17631..b556a72264d1 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -125,7 +125,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, */ if (pdata->init && pdata->init(pdev)) { retval = -ENODEV; - goto err3; + goto err4; } /* Enable USB controller, 83xx or 8536 */ diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index f4b627d343ac..01bb7241d6ef 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -276,6 +276,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* Serial Bus Release Number is at PCI 0x60 offset */ pci_read_config_byte(pdev, 0x60, &ehci->sbrn); + if (pdev->vendor == PCI_VENDOR_ID_STMICRO + && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST) + ehci->sbrn = 0x20; /* ConneXT has no sbrn register */ /* Keep this around for a while just in case some EHCI * implementation uses legacy PCI PM support. This test @@ -526,6 +529,9 @@ static const struct pci_device_id pci_ids [] = { { /* handle any USB 2.0 EHCI controller */ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0), .driver_data = (unsigned long) &ehci_pci_hc_driver, + }, { + PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_HOST), + .driver_data = (unsigned long) &ehci_pci_hc_driver, }, { /* end: all zeroes */ } }; diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 5df0b0e3392b..77afabc77f9b 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -139,8 +139,23 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, } iclk = clk_get(&pdev->dev, "ohci_clk"); + if (IS_ERR(iclk)) { + dev_err(&pdev->dev, "failed to get ohci_clk\n"); + retval = PTR_ERR(iclk); + goto err3; + } fclk = clk_get(&pdev->dev, "uhpck"); + if (IS_ERR(fclk)) { + dev_err(&pdev->dev, "failed to get uhpck\n"); + retval = PTR_ERR(fclk); + goto err4; + } hclk = clk_get(&pdev->dev, "hclk"); + if (IS_ERR(hclk)) { + dev_err(&pdev->dev, "failed to get hclk\n"); + retval = PTR_ERR(hclk); + goto err5; + } at91_start_hc(pdev); ohci_hcd_init(hcd_to_ohci(hcd)); @@ -153,9 +168,12 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, at91_stop_hc(pdev); clk_put(hclk); + err5: clk_put(fclk); + err4: clk_put(iclk); + err3: iounmap(hcd->regs); err2: @@ -226,7 +244,8 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int if (!gpio_is_valid(pdata->vbus_pin[port])) return; - gpio_set_value(pdata->vbus_pin[port], !pdata->vbus_pin_inverted ^ enable); + gpio_set_value(pdata->vbus_pin[port], + !pdata->vbus_pin_active_low[port] ^ enable); } static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) @@ -237,7 +256,8 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) if (!gpio_is_valid(pdata->vbus_pin[port])) return -EINVAL; - return gpio_get_value(pdata->vbus_pin[port]) ^ !pdata->vbus_pin_inverted; + return gpio_get_value(pdata->vbus_pin[port]) ^ + !pdata->vbus_pin_active_low[port]; } /* diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 5179fcd73d8a..e4bcb62b930a 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -82,6 +82,14 @@ urb_print(struct urb * urb, char * str, int small, int status) ohci_dbg(ohci,format, ## arg ); \ } while (0); +/* Version for use where "next" is the address of a local variable */ +#define ohci_dbg_nosw(ohci, next, size, format, arg...) \ + do { \ + unsigned s_len; \ + s_len = scnprintf(*next, *size, format, ## arg); \ + *size -= s_len; *next += s_len; \ + } while (0); + static void ohci_dump_intr_mask ( struct ohci_hcd *ohci, @@ -653,7 +661,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) /* dump driver info, then registers in spec order */ - ohci_dbg_sw (ohci, &next, &size, + ohci_dbg_nosw(ohci, &next, &size, "bus %s, device %s\n" "%s\n" "%s\n", @@ -672,7 +680,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) /* hcca */ if (ohci->hcca) - ohci_dbg_sw (ohci, &next, &size, + ohci_dbg_nosw(ohci, &next, &size, "hcca frame 0x%04x\n", ohci_frame_no(ohci)); /* other registers mostly affect frame timings */ diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 6109810cc2d3..1843bb68ac7c 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -397,6 +397,10 @@ static const struct pci_device_id pci_ids [] = { { /* handle any USB OHCI controller */ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0), .driver_data = (unsigned long) &ohci_pci_hc_driver, + }, { + /* The device in the ConneXT I/O hub has no class reg */ + PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_OHCI), + .driver_data = (unsigned long) &ohci_pci_hc_driver, }, { /* end: all zeroes */ } }; MODULE_DEVICE_TABLE (pci, pci_ids); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b90e1386418b..b62037bff688 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1204,6 +1204,7 @@ static void handle_vendor_event(struct xhci_hcd *xhci, * * Returns a zero-based port number, which is suitable for indexing into each of * the split roothubs' port arrays and bus state arrays. + * Add one to it in order to call xhci_find_slot_id_by_port. */ static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd, struct xhci_hcd *xhci, u32 port_id) @@ -1324,7 +1325,7 @@ static void handle_port_status(struct xhci_hcd *xhci, xhci_set_link_state(xhci, port_array, faked_port_index, XDEV_U0); slot_id = xhci_find_slot_id_by_port(hcd, xhci, - faked_port_index); + faked_port_index + 1); if (!slot_id) { xhci_dbg(xhci, "slot_id is zero\n"); goto cleanup; @@ -3323,7 +3324,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* Check TD length */ if (running_total != td_len) { xhci_err(xhci, "ISOC TD length unmatch\n"); - return -EINVAL; + ret = -EINVAL; + goto cleanup; } } diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index d9b6a0355443..da97dcec1f32 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c @@ -37,9 +37,6 @@ static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit); static int emi26_load_firmware (struct usb_device *dev); static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id); static void emi26_disconnect(struct usb_interface *intf); -static int __init emi26_init (void); -static void __exit emi26_exit (void); - /* thanks to drivers/usb/serial/keyspan_pda.c code */ static int emi26_writememory (struct usb_device *dev, int address, diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 9f39062ebb08..4e0f167a6c4e 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -46,9 +46,6 @@ static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit); static int emi62_load_firmware (struct usb_device *dev); static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id); static void emi62_disconnect(struct usb_interface *intf); -static int __init emi62_init (void); -static void __exit emi62_exit (void); - /* thanks to drivers/usb/serial/keyspan_pda.c code */ static int emi62_writememory(struct usb_device *dev, int address, diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c index 107bf13b1cf1..b2d82b937392 100644 --- a/drivers/usb/misc/usbsevseg.c +++ b/drivers/usb/misc/usbsevseg.c @@ -24,7 +24,7 @@ #define VENDOR_ID 0x0fc5 #define PRODUCT_ID 0x1227 -#define MAXLEN 6 +#define MAXLEN 8 /* table of devices that work with this driver */ static const struct usb_device_id id_table[] = { diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index f9a3f62a83b5..7c569f51212a 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -33,9 +33,6 @@ #include <linux/platform_device.h> #include <linux/dma-mapping.h> -#include <mach/hardware.h> -#include <mach/memory.h> -#include <asm/gpio.h> #include <mach/cputype.h> #include <asm/mach-types.h> diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 56cf0243979e..3d11cf64ebd1 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -981,6 +981,9 @@ static void musb_shutdown(struct platform_device *pdev) unsigned long flags; pm_runtime_get_sync(musb->controller); + + musb_gadget_cleanup(musb); + spin_lock_irqsave(&musb->lock, flags); musb_platform_disable(musb); musb_generic_disable(musb); @@ -1827,8 +1830,6 @@ static void musb_free(struct musb *musb) sysfs_remove_group(&musb->controller->kobj, &musb_attr_group); #endif - musb_gadget_cleanup(musb); - if (musb->nIrq >= 0) { if (musb->irq_wake) disable_irq_wake(musb->nIrq); diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index c27bbbf32b52..df719eae3b03 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -222,7 +222,6 @@ static inline void omap2430_low_level_init(struct musb *musb) musb_writel(musb->mregs, OTG_FORCESTDBY, l); } -/* blocking notifier support */ static int musb_otg_notifications(struct notifier_block *nb, unsigned long event, void *unused) { @@ -231,7 +230,7 @@ static int musb_otg_notifications(struct notifier_block *nb, musb->xceiv_event = event; schedule_work(&musb->otg_notifier_work); - return 0; + return NOTIFY_OK; } static void musb_otg_notifier_work(struct work_struct *data_notifier_work) @@ -386,6 +385,7 @@ static void omap2430_musb_disable(struct musb *musb) static int omap2430_musb_exit(struct musb *musb) { del_timer_sync(&musb_idle_timer); + cancel_work_sync(&musb->otg_notifier_work); omap2430_low_level_exit(musb); otg_put_transceiver(musb->xceiv); diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 2a25955881fc..76d629345418 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -86,20 +86,6 @@ config NOP_USB_XCEIV built-in with usb ip or which are autonomous and doesn't require any phy programming such as ISP1x04 etc. -config USB_LANGWELL_OTG - tristate "Intel Langwell USB OTG dual-role support" - depends on USB && PCI && INTEL_SCU_IPC - select USB_OTG - select USB_OTG_UTILS - help - Say Y here if you want to build Intel Langwell USB OTG - transciever driver in kernel. This driver implements role - switch between EHCI host driver and Langwell USB OTG - client driver. - - To compile this driver as a module, choose M here: the - module will be called langwell_otg. - config USB_MSM_OTG tristate "OTG support for Qualcomm on-chip USB controller" depends on (USB || USB_GADGET) && ARCH_MSM @@ -124,7 +110,7 @@ config AB8500_USB config FSL_USB2_OTG bool "Freescale USB OTG Transceiver Driver" - depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 + depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 && USB_SUSPEND select USB_OTG select USB_OTG_UTILS help @@ -132,7 +118,7 @@ config FSL_USB2_OTG config USB_MV_OTG tristate "Marvell USB OTG support" - depends on USB_MV_UDC + depends on USB_MV_UDC && USB_SUSPEND select USB_OTG select USB_OTG_UTILS help diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index b2c5a9598637..41aa5098b139 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o -obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o obj-$(CONFIG_USB_ULPI) += ulpi.o obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi_viewport.o diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c deleted file mode 100644 index f08f784086f7..000000000000 --- a/drivers/usb/otg/langwell_otg.c +++ /dev/null @@ -1,2347 +0,0 @@ -/* - * Intel Langwell USB OTG transceiver driver - * Copyright (C) 2008 - 2010, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -/* This driver helps to switch Langwell OTG controller function between host - * and peripheral. It works with EHCI driver and Langwell client controller - * driver together. - */ -#include <linux/module.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/moduleparam.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#include <linux/usb.h> -#include <linux/usb/otg.h> -#include <linux/usb/hcd.h> -#include <linux/notifier.h> -#include <linux/delay.h> -#include <asm/intel_scu_ipc.h> - -#include <linux/usb/langwell_otg.h> - -#define DRIVER_DESC "Intel Langwell USB OTG transceiver driver" -#define DRIVER_VERSION "July 10, 2010" - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>"); -MODULE_VERSION(DRIVER_VERSION); -MODULE_LICENSE("GPL"); - -static const char driver_name[] = "langwell_otg"; - -static int langwell_otg_probe(struct pci_dev *pdev, - const struct pci_device_id *id); -static void langwell_otg_remove(struct pci_dev *pdev); -static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message); -static int langwell_otg_resume(struct pci_dev *pdev); - -static int langwell_otg_set_host(struct otg_transceiver *otg, - struct usb_bus *host); -static int langwell_otg_set_peripheral(struct otg_transceiver *otg, - struct usb_gadget *gadget); -static int langwell_otg_start_srp(struct otg_transceiver *otg); - -static const struct pci_device_id pci_ids[] = {{ - .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), - .class_mask = ~0, - .vendor = 0x8086, - .device = 0x0811, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, -}, { /* end: all zeroes */ } -}; - -static struct pci_driver otg_pci_driver = { - .name = (char *) driver_name, - .id_table = pci_ids, - - .probe = langwell_otg_probe, - .remove = langwell_otg_remove, - - .suspend = langwell_otg_suspend, - .resume = langwell_otg_resume, -}; - -/* HSM timers */ -static inline struct langwell_otg_timer *otg_timer_initializer -(void (*function)(unsigned long), unsigned long expires, unsigned long data) -{ - struct langwell_otg_timer *timer; - timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL); - if (timer == NULL) - return timer; - - timer->function = function; - timer->expires = expires; - timer->data = data; - return timer; -} - -static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr, - *b_se0_srp_tmr, *b_srp_init_tmr; - -static struct list_head active_timers; - -static struct langwell_otg *the_transceiver; - -/* host/client notify transceiver when event affects HNP state */ -void langwell_update_transceiver(void) -{ - struct langwell_otg *lnw = the_transceiver; - - dev_dbg(lnw->dev, "transceiver is updated\n"); - - if (!lnw->qwork) - return ; - - queue_work(lnw->qwork, &lnw->work); -} -EXPORT_SYMBOL(langwell_update_transceiver); - -static int langwell_otg_set_host(struct otg_transceiver *otg, - struct usb_bus *host) -{ - otg->host = host; - - return 0; -} - -static int langwell_otg_set_peripheral(struct otg_transceiver *otg, - struct usb_gadget *gadget) -{ - otg->gadget = gadget; - - return 0; -} - -static int langwell_otg_set_power(struct otg_transceiver *otg, - unsigned mA) -{ - return 0; -} - -/* A-device drives vbus, controlled through IPC commands */ -static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled) -{ - struct langwell_otg *lnw = the_transceiver; - u8 sub_id; - - dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off"); - - if (enabled) - sub_id = 0x8; /* Turn on the VBus */ - else - sub_id = 0x9; /* Turn off the VBus */ - - if (intel_scu_ipc_simple_command(0xef, sub_id)) { - dev_dbg(lnw->dev, "Failed to set Vbus via IPC commands\n"); - return -EBUSY; - } - - dev_dbg(lnw->dev, "%s --->\n", __func__); - - return 0; -} - -/* charge vbus or discharge vbus through a resistor to ground */ -static void langwell_otg_chrg_vbus(int on) -{ - struct langwell_otg *lnw = the_transceiver; - u32 val; - - val = readl(lnw->iotg.base + CI_OTGSC); - - if (on) - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC, - lnw->iotg.base + CI_OTGSC); - else - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD, - lnw->iotg.base + CI_OTGSC); -} - -/* Start SRP */ -static int langwell_otg_start_srp(struct otg_transceiver *otg) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val; - - dev_dbg(lnw->dev, "%s --->\n", __func__); - - val = readl(iotg->base + CI_OTGSC); - - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, - iotg->base + CI_OTGSC); - - /* Check if the data plus is finished or not */ - msleep(8); - val = readl(iotg->base + CI_OTGSC); - if (val & (OTGSC_HADP | OTGSC_DP)) - dev_dbg(lnw->dev, "DataLine SRP Error\n"); - - /* Disable interrupt - b_sess_vld */ - val = readl(iotg->base + CI_OTGSC); - val &= (~(OTGSC_BSVIE | OTGSC_BSEIE)); - writel(val, iotg->base + CI_OTGSC); - - /* Start VBus SRP, drive vbus to generate VBus pulse */ - iotg->otg.set_vbus(&iotg->otg, true); - msleep(15); - iotg->otg.set_vbus(&iotg->otg, false); - - /* Enable interrupt - b_sess_vld*/ - val = readl(iotg->base + CI_OTGSC); - dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val); - - val |= (OTGSC_BSVIE | OTGSC_BSEIE); - writel(val, iotg->base + CI_OTGSC); - - /* If Vbus is valid, then update the hsm */ - if (val & OTGSC_BSV) { - dev_dbg(lnw->dev, "no b_sess_vld interrupt\n"); - - lnw->iotg.hsm.b_sess_vld = 1; - langwell_update_transceiver(); - } - - dev_dbg(lnw->dev, "%s <---\n", __func__); - return 0; -} - -/* stop SOF via bus_suspend */ -static void langwell_otg_loc_sof(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct usb_hcd *hcd; - int err; - - dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume"); - - hcd = bus_to_hcd(lnw->iotg.otg.host); - if (on) - err = hcd->driver->bus_resume(hcd); - else - err = hcd->driver->bus_suspend(hcd); - - if (err) - dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err); - - dev_dbg(lnw->dev, "%s <---\n", __func__); -} - -static int langwell_otg_check_otgsc(void) -{ - struct langwell_otg *lnw = the_transceiver; - u32 otgsc, usbcfg; - - dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n"); - - otgsc = readl(lnw->iotg.base + CI_OTGSC); - usbcfg = readl(lnw->usbcfg); - - dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n", - otgsc, usbcfg); - dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV)); - dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n", - !!(usbcfg & USBCFG_VBUSVAL)); - dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV)); - dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n", - !!(usbcfg & USBCFG_AVALID)); - dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV)); - dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n", - !!(usbcfg & USBCFG_BVALID)); - dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE)); - dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n", - !!(usbcfg & USBCFG_SESEND)); - - /* Check USBCFG VBusValid/AValid/BValid/SessEnd */ - if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) { - dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n"); - goto err; - } - if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) { - dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n"); - goto err; - } - if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) { - dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n"); - goto err; - } - if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) { - dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n"); - goto err; - } - - dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n"); - - return 0; - -err: - dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n"); - return -EPIPE; -} - - -static void langwell_otg_phy_low_power(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u8 val, phcd; - int retval; - - dev_dbg(lnw->dev, "%s ---> %s mode\n", - __func__, on ? "Low power" : "Normal"); - - phcd = 0x40; - - val = readb(iotg->base + CI_HOSTPC1 + 2); - - if (on) { - /* Due to hardware issue, after set PHCD, sync will failed - * between USBCFG and OTGSC, so before set PHCD, check if - * sync is in process now. If the answer is "yes", then do - * not touch PHCD bit */ - retval = langwell_otg_check_otgsc(); - if (retval) { - dev_dbg(lnw->dev, "Skip PHCD programming..\n"); - return ; - } - - writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2); - } else - writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2); - - dev_dbg(lnw->dev, "%s <--- done\n", __func__); -} - -/* After drv vbus, add 5 ms delay to set PHCD */ -static void langwell_otg_phy_low_power_wait(int on) -{ - struct langwell_otg *lnw = the_transceiver; - - dev_dbg(lnw->dev, "add 5ms delay before programing PHCD\n"); - - mdelay(5); - langwell_otg_phy_low_power(on); -} - -/* Enable/Disable OTG interrupt */ -static void langwell_otg_intr(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val; - - dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); - - val = readl(iotg->base + CI_OTGSC); - - /* OTGSC_INT_MASK doesn't contains 1msInt */ - if (on) { - val = val | (OTGSC_INT_MASK); - writel(val, iotg->base + CI_OTGSC); - } else { - val = val & ~(OTGSC_INT_MASK); - writel(val, iotg->base + CI_OTGSC); - } - - dev_dbg(lnw->dev, "%s <---\n", __func__); -} - -/* set HAAR: Hardware Assist Auto-Reset */ -static void langwell_otg_HAAR(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val; - - dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); - - val = readl(iotg->base + CI_OTGSC); - if (on) - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR, - iotg->base + CI_OTGSC); - else - writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR, - iotg->base + CI_OTGSC); - - dev_dbg(lnw->dev, "%s <---\n", __func__); -} - -/* set HABA: Hardware Assist B-Disconnect to A-Connect */ -static void langwell_otg_HABA(int on) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val; - - dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); - - val = readl(iotg->base + CI_OTGSC); - if (on) - writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA, - iotg->base + CI_OTGSC); - else - writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA, - iotg->base + CI_OTGSC); - - dev_dbg(lnw->dev, "%s <---\n", __func__); -} - -static int langwell_otg_check_se0_srp(int on) -{ - struct langwell_otg *lnw = the_transceiver; - int delay_time = TB_SE0_SRP * 10; - u32 val; - - dev_dbg(lnw->dev, "%s --->\n", __func__); - - do { - udelay(100); - if (!delay_time--) - break; - val = readl(lnw->iotg.base + CI_PORTSC1); - val &= PORTSC_LS; - } while (!val); - - dev_dbg(lnw->dev, "%s <---\n", __func__); - return val; -} - -/* The timeout callback function to set time out bit */ -static void set_tmout(unsigned long indicator) -{ - *(int *)indicator = 1; -} - -void langwell_otg_nsf_msg(unsigned long indicator) -{ - struct langwell_otg *lnw = the_transceiver; - - switch (indicator) { - case 2: - case 4: - case 6: - case 7: - dev_warn(lnw->dev, - "OTG:NSF-%lu - deivce not responding\n", indicator); - break; - case 3: - dev_warn(lnw->dev, - "OTG:NSF-%lu - deivce not supported\n", indicator); - break; - default: - dev_warn(lnw->dev, "Do not have this kind of NSF\n"); - break; - } -} - -/* Initialize timers */ -static int langwell_otg_init_timers(struct otg_hsm *hsm) -{ - /* HSM used timers */ - a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, - (unsigned long)&hsm->a_wait_vrise_tmout); - if (a_wait_vrise_tmr == NULL) - return -ENOMEM; - a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, - (unsigned long)&hsm->a_aidl_bdis_tmout); - if (a_aidl_bdis_tmr == NULL) - return -ENOMEM; - b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, - (unsigned long)&hsm->b_se0_srp); - if (b_se0_srp_tmr == NULL) - return -ENOMEM; - b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT, - (unsigned long)&hsm->b_srp_init_tmout); - if (b_srp_init_tmr == NULL) - return -ENOMEM; - - return 0; -} - -/* Free timers */ -static void langwell_otg_free_timers(void) -{ - kfree(a_wait_vrise_tmr); - kfree(a_aidl_bdis_tmr); - kfree(b_se0_srp_tmr); - kfree(b_srp_init_tmr); -} - -/* The timeout callback function to set time out bit */ -static void langwell_otg_timer_fn(unsigned long indicator) -{ - struct langwell_otg *lnw = the_transceiver; - - *(int *)indicator = 1; - - dev_dbg(lnw->dev, "kernel timer - timeout\n"); - - langwell_update_transceiver(); -} - -/* kernel timer used instead of HW based interrupt */ -static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - unsigned long j = jiffies; - unsigned long data, time; - - switch (timers) { - case TA_WAIT_VRISE_TMR: - iotg->hsm.a_wait_vrise_tmout = 0; - data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout; - time = TA_WAIT_VRISE; - break; - case TA_WAIT_BCON_TMR: - iotg->hsm.a_wait_bcon_tmout = 0; - data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout; - time = TA_WAIT_BCON; - break; - case TA_AIDL_BDIS_TMR: - iotg->hsm.a_aidl_bdis_tmout = 0; - data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout; - time = TA_AIDL_BDIS; - break; - case TB_ASE0_BRST_TMR: - iotg->hsm.b_ase0_brst_tmout = 0; - data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout; - time = TB_ASE0_BRST; - break; - case TB_SRP_INIT_TMR: - iotg->hsm.b_srp_init_tmout = 0; - data = (unsigned long)&iotg->hsm.b_srp_init_tmout; - time = TB_SRP_INIT; - break; - case TB_SRP_FAIL_TMR: - iotg->hsm.b_srp_fail_tmout = 0; - data = (unsigned long)&iotg->hsm.b_srp_fail_tmout; - time = TB_SRP_FAIL; - break; - case TB_BUS_SUSPEND_TMR: - iotg->hsm.b_bus_suspend_tmout = 0; - data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout; - time = TB_BUS_SUSPEND; - break; - default: - dev_dbg(lnw->dev, "unknown timer, cannot enable it\n"); - return; - } - - lnw->hsm_timer.data = data; - lnw->hsm_timer.function = langwell_otg_timer_fn; - lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */ - - add_timer(&lnw->hsm_timer); - - dev_dbg(lnw->dev, "add timer successfully\n"); -} - -/* Add timer to timer list */ -static void langwell_otg_add_timer(void *gtimer) -{ - struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; - struct langwell_otg_timer *tmp_timer; - struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg; - u32 val32; - - /* Check if the timer is already in the active list, - * if so update timer count - */ - list_for_each_entry(tmp_timer, &active_timers, list) - if (tmp_timer == timer) { - timer->count = timer->expires; - return; - } - timer->count = timer->expires; - - if (list_empty(&active_timers)) { - val32 = readl(iotg->base + CI_OTGSC); - writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC); - } - - list_add_tail(&timer->list, &active_timers); -} - -/* Remove timer from the timer list; clear timeout status */ -static void langwell_otg_del_timer(void *gtimer) -{ - struct langwell_otg *lnw = the_transceiver; - struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; - struct langwell_otg_timer *tmp_timer, *del_tmp; - u32 val32; - - list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) - if (tmp_timer == timer) - list_del(&timer->list); - - if (list_empty(&active_timers)) { - val32 = readl(lnw->iotg.base + CI_OTGSC); - writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC); - } -} - -/* Reduce timer count by 1, and find timeout conditions.*/ -static int langwell_otg_tick_timer(u32 *int_sts) -{ - struct langwell_otg *lnw = the_transceiver; - struct langwell_otg_timer *tmp_timer, *del_tmp; - int expired = 0; - - list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { - tmp_timer->count--; - /* check if timer expires */ - if (!tmp_timer->count) { - list_del(&tmp_timer->list); - tmp_timer->function(tmp_timer->data); - expired = 1; - } - } - - if (list_empty(&active_timers)) { - dev_dbg(lnw->dev, "tick timer: disable 1ms int\n"); - *int_sts = *int_sts & ~OTGSC_1MSE; - } - return expired; -} - -static void reset_otg(void) -{ - struct langwell_otg *lnw = the_transceiver; - int delay_time = 1000; - u32 val; - - dev_dbg(lnw->dev, "reseting OTG controller ...\n"); - val = readl(lnw->iotg.base + CI_USBCMD); - writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD); - do { - udelay(100); - if (!delay_time--) - dev_dbg(lnw->dev, "reset timeout\n"); - val = readl(lnw->iotg.base + CI_USBCMD); - val &= USBCMD_RST; - } while (val != 0); - dev_dbg(lnw->dev, "reset done.\n"); -} - -static void set_host_mode(void) -{ - struct langwell_otg *lnw = the_transceiver; - u32 val; - - reset_otg(); - val = readl(lnw->iotg.base + CI_USBMODE); - val = (val & (~USBMODE_CM)) | USBMODE_HOST; - writel(val, lnw->iotg.base + CI_USBMODE); -} - -static void set_client_mode(void) -{ - struct langwell_otg *lnw = the_transceiver; - u32 val; - - reset_otg(); - val = readl(lnw->iotg.base + CI_USBMODE); - val = (val & (~USBMODE_CM)) | USBMODE_DEVICE; - writel(val, lnw->iotg.base + CI_USBMODE); -} - -static void init_hsm(void) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val32; - - /* read OTGSC after reset */ - val32 = readl(lnw->iotg.base + CI_OTGSC); - dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32); - - /* set init state */ - if (val32 & OTGSC_ID) { - iotg->hsm.id = 1; - iotg->otg.default_a = 0; - set_client_mode(); - iotg->otg.state = OTG_STATE_B_IDLE; - } else { - iotg->hsm.id = 0; - iotg->otg.default_a = 1; - set_host_mode(); - iotg->otg.state = OTG_STATE_A_IDLE; - } - - /* set session indicator */ - if (val32 & OTGSC_BSE) - iotg->hsm.b_sess_end = 1; - if (val32 & OTGSC_BSV) - iotg->hsm.b_sess_vld = 1; - if (val32 & OTGSC_ASV) - iotg->hsm.a_sess_vld = 1; - if (val32 & OTGSC_AVV) - iotg->hsm.a_vbus_vld = 1; - - /* defautly power the bus */ - iotg->hsm.a_bus_req = 1; - iotg->hsm.a_bus_drop = 0; - /* defautly don't request bus as B device */ - iotg->hsm.b_bus_req = 0; - /* no system error */ - iotg->hsm.a_clr_err = 0; - - langwell_otg_phy_low_power_wait(1); -} - -static void update_hsm(void) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 val32; - - /* read OTGSC */ - val32 = readl(lnw->iotg.base + CI_OTGSC); - dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32); - - iotg->hsm.id = !!(val32 & OTGSC_ID); - iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE); - iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV); - iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV); - iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV); -} - -static irqreturn_t otg_dummy_irq(int irq, void *_dev) -{ - struct langwell_otg *lnw = the_transceiver; - void __iomem *reg_base = _dev; - u32 val; - u32 int_mask = 0; - - val = readl(reg_base + CI_USBMODE); - if ((val & USBMODE_CM) != USBMODE_DEVICE) - return IRQ_NONE; - - val = readl(reg_base + CI_USBSTS); - int_mask = val & INTR_DUMMY_MASK; - - if (int_mask == 0) - return IRQ_NONE; - - /* clear hsm.b_conn here since host driver can't detect it - * otg_dummy_irq called means B-disconnect happened. - */ - if (lnw->iotg.hsm.b_conn) { - lnw->iotg.hsm.b_conn = 0; - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - } - - /* Clear interrupts */ - writel(int_mask, reg_base + CI_USBSTS); - return IRQ_HANDLED; -} - -static irqreturn_t otg_irq(int irq, void *_dev) -{ - struct langwell_otg *lnw = _dev; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - u32 int_sts, int_en; - u32 int_mask = 0; - int flag = 0; - - int_sts = readl(lnw->iotg.base + CI_OTGSC); - int_en = (int_sts & OTGSC_INTEN_MASK) >> 8; - int_mask = int_sts & int_en; - if (int_mask == 0) - return IRQ_NONE; - - if (int_mask & OTGSC_IDIS) { - dev_dbg(lnw->dev, "%s: id change int\n", __func__); - iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0; - dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id); - flag = 1; - } - if (int_mask & OTGSC_DPIS) { - dev_dbg(lnw->dev, "%s: data pulse int\n", __func__); - iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0; - dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det); - flag = 1; - } - if (int_mask & OTGSC_BSEIS) { - dev_dbg(lnw->dev, "%s: b session end int\n", __func__); - iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0; - dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end); - flag = 1; - } - if (int_mask & OTGSC_BSVIS) { - dev_dbg(lnw->dev, "%s: b session valid int\n", __func__); - iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0; - dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end); - flag = 1; - } - if (int_mask & OTGSC_ASVIS) { - dev_dbg(lnw->dev, "%s: a session valid int\n", __func__); - iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0; - dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld); - flag = 1; - } - if (int_mask & OTGSC_AVVIS) { - dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__); - iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0; - dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld); - flag = 1; - } - - if (int_mask & OTGSC_1MSS) { - /* need to schedule otg_work if any timer is expired */ - if (langwell_otg_tick_timer(&int_sts)) - flag = 1; - } - - writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask, - lnw->iotg.base + CI_OTGSC); - if (flag) - langwell_update_transceiver(); - - return IRQ_HANDLED; -} - -static int langwell_otg_iotg_notify(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = data; - int flag = 0; - - if (iotg == NULL) - return NOTIFY_BAD; - - if (lnw == NULL) - return NOTIFY_BAD; - - switch (action) { - case MID_OTG_NOTIFY_CONNECT: - dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.b_conn = 1; - else - iotg->hsm.a_conn = 1; - flag = 1; - break; - case MID_OTG_NOTIFY_DISCONN: - dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.b_conn = 0; - else - iotg->hsm.a_conn = 0; - flag = 1; - break; - case MID_OTG_NOTIFY_HSUSPEND: - dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.a_suspend_req = 1; - else - iotg->hsm.b_bus_req = 0; - flag = 1; - break; - case MID_OTG_NOTIFY_HRESUME: - dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n"); - if (iotg->otg.default_a == 1) - iotg->hsm.b_bus_resume = 1; - flag = 1; - break; - case MID_OTG_NOTIFY_CSUSPEND: - dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n"); - if (iotg->otg.default_a == 1) { - if (iotg->hsm.b_bus_suspend_vld == 2) { - iotg->hsm.b_bus_suspend = 1; - iotg->hsm.b_bus_suspend_vld = 0; - flag = 1; - } else { - iotg->hsm.b_bus_suspend_vld++; - flag = 0; - } - } else { - if (iotg->hsm.a_bus_suspend == 0) { - iotg->hsm.a_bus_suspend = 1; - flag = 1; - } - } - break; - case MID_OTG_NOTIFY_CRESUME: - dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n"); - if (iotg->otg.default_a == 0) - iotg->hsm.a_bus_suspend = 0; - flag = 0; - break; - case MID_OTG_NOTIFY_HOSTADD: - dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n"); - flag = 1; - break; - case MID_OTG_NOTIFY_HOSTREMOVE: - dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n"); - flag = 1; - break; - case MID_OTG_NOTIFY_CLIENTADD: - dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n"); - flag = 1; - break; - case MID_OTG_NOTIFY_CLIENTREMOVE: - dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n"); - flag = 1; - break; - default: - dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n"); - return NOTIFY_DONE; - } - - if (flag) - langwell_update_transceiver(); - - return NOTIFY_OK; -} - -static void langwell_otg_work(struct work_struct *work) -{ - struct langwell_otg *lnw; - struct intel_mid_otg_xceiv *iotg; - int retval; - struct pci_dev *pdev; - - lnw = container_of(work, struct langwell_otg, work); - iotg = &lnw->iotg; - pdev = to_pci_dev(lnw->dev); - - dev_dbg(lnw->dev, "%s: old state = %s\n", __func__, - otg_state_string(iotg->otg.state)); - - switch (iotg->otg.state) { - case OTG_STATE_UNDEFINED: - case OTG_STATE_B_IDLE: - if (!iotg->hsm.id) { - langwell_otg_del_timer(b_srp_init_tmr); - del_timer_sync(&lnw->hsm_timer); - - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - langwell_otg_chrg_vbus(0); - set_host_mode(); - langwell_otg_phy_low_power(1); - - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.b_sess_vld) { - langwell_otg_del_timer(b_srp_init_tmr); - del_timer_sync(&lnw->hsm_timer); - iotg->hsm.b_sess_end = 0; - iotg->hsm.a_bus_suspend = 0; - langwell_otg_chrg_vbus(0); - - if (lnw->iotg.start_peripheral) { - lnw->iotg.start_peripheral(&lnw->iotg); - iotg->otg.state = OTG_STATE_B_PERIPHERAL; - } else - dev_dbg(lnw->dev, "client driver not loaded\n"); - - } else if (iotg->hsm.b_srp_init_tmout) { - iotg->hsm.b_srp_init_tmout = 0; - dev_warn(lnw->dev, "SRP init timeout\n"); - } else if (iotg->hsm.b_srp_fail_tmout) { - iotg->hsm.b_srp_fail_tmout = 0; - iotg->hsm.b_bus_req = 0; - - /* No silence failure */ - langwell_otg_nsf_msg(6); - } else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) { - del_timer_sync(&lnw->hsm_timer); - /* workaround for b_se0_srp detection */ - retval = langwell_otg_check_se0_srp(0); - if (retval) { - iotg->hsm.b_bus_req = 0; - dev_dbg(lnw->dev, "LS isn't SE0, try later\n"); - } else { - /* clear the PHCD before start srp */ - langwell_otg_phy_low_power(0); - - /* Start SRP */ - langwell_otg_add_timer(b_srp_init_tmr); - iotg->otg.start_srp(&iotg->otg); - langwell_otg_del_timer(b_srp_init_tmr); - langwell_otg_add_ktimer(TB_SRP_FAIL_TMR); - - /* reset PHY low power mode here */ - langwell_otg_phy_low_power_wait(1); - } - } - break; - case OTG_STATE_B_SRP_INIT: - if (!iotg->hsm.id) { - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_chrg_vbus(0); - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.b_sess_vld) { - langwell_otg_chrg_vbus(0); - if (lnw->iotg.start_peripheral) { - lnw->iotg.start_peripheral(&lnw->iotg); - iotg->otg.state = OTG_STATE_B_PERIPHERAL; - } else - dev_dbg(lnw->dev, "client driver not loaded\n"); - } - break; - case OTG_STATE_B_PERIPHERAL: - if (!iotg->hsm.id) { - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - langwell_otg_chrg_vbus(0); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.b_sess_vld) { - iotg->hsm.b_hnp_enable = 0; - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - iotg->otg.state = OTG_STATE_B_IDLE; - } else if (iotg->hsm.b_bus_req && iotg->otg.gadget && - iotg->otg.gadget->b_hnp_enable && - iotg->hsm.a_bus_suspend) { - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - langwell_otg_HAAR(1); - iotg->hsm.a_conn = 0; - - if (lnw->iotg.start_host) { - lnw->iotg.start_host(&lnw->iotg); - iotg->otg.state = OTG_STATE_B_WAIT_ACON; - } else - dev_dbg(lnw->dev, - "host driver not loaded.\n"); - - iotg->hsm.a_bus_resume = 0; - langwell_otg_add_ktimer(TB_ASE0_BRST_TMR); - } - break; - - case OTG_STATE_B_WAIT_ACON: - if (!iotg->hsm.id) { - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - langwell_otg_chrg_vbus(0); - - langwell_otg_HAAR(0); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.b_sess_vld) { - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - iotg->hsm.b_hnp_enable = 0; - iotg->hsm.b_bus_req = 0; - - langwell_otg_chrg_vbus(0); - langwell_otg_HAAR(0); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - } else if (iotg->hsm.a_conn) { - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - langwell_otg_HAAR(0); - iotg->otg.state = OTG_STATE_B_HOST; - langwell_update_transceiver(); - } else if (iotg->hsm.a_bus_resume || - iotg->hsm.b_ase0_brst_tmout) { - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - langwell_otg_HAAR(0); - langwell_otg_nsf_msg(7); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - iotg->hsm.a_bus_suspend = 0; - iotg->hsm.b_bus_req = 0; - - if (lnw->iotg.start_peripheral) - lnw->iotg.start_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver not loaded.\n"); - - iotg->otg.state = OTG_STATE_B_PERIPHERAL; - } - break; - - case OTG_STATE_B_HOST: - if (!iotg->hsm.id) { - iotg->otg.default_a = 1; - iotg->hsm.a_srp_det = 0; - - langwell_otg_chrg_vbus(0); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.b_sess_vld) { - iotg->hsm.b_hnp_enable = 0; - iotg->hsm.b_bus_req = 0; - - langwell_otg_chrg_vbus(0); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - } else if ((!iotg->hsm.b_bus_req) || - (!iotg->hsm.a_conn)) { - iotg->hsm.b_bus_req = 0; - langwell_otg_loc_sof(0); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - iotg->hsm.a_bus_suspend = 0; - - if (lnw->iotg.start_peripheral) - lnw->iotg.start_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver not loaded.\n"); - - iotg->otg.state = OTG_STATE_B_PERIPHERAL; - } - break; - - case OTG_STATE_A_IDLE: - iotg->otg.default_a = 1; - if (iotg->hsm.id) { - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - iotg->hsm.vbus_srp_up = 0; - - langwell_otg_chrg_vbus(0); - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_bus_drop && - (iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) { - langwell_otg_phy_low_power(0); - - /* Turn on VBus */ - iotg->otg.set_vbus(&iotg->otg, true); - - iotg->hsm.vbus_srp_up = 0; - iotg->hsm.a_wait_vrise_tmout = 0; - langwell_otg_add_timer(a_wait_vrise_tmr); - iotg->otg.state = OTG_STATE_A_WAIT_VRISE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) { - iotg->hsm.vbus_srp_up = 1; - } else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) { - msleep(10); - langwell_otg_phy_low_power(0); - - /* Turn on VBus */ - iotg->otg.set_vbus(&iotg->otg, true); - iotg->hsm.a_srp_det = 1; - iotg->hsm.vbus_srp_up = 0; - iotg->hsm.a_wait_vrise_tmout = 0; - langwell_otg_add_timer(a_wait_vrise_tmr); - iotg->otg.state = OTG_STATE_A_WAIT_VRISE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_sess_vld && - !iotg->hsm.vbus_srp_up) { - langwell_otg_phy_low_power(1); - } - break; - case OTG_STATE_A_WAIT_VRISE: - if (iotg->hsm.id) { - langwell_otg_del_timer(a_wait_vrise_tmr); - iotg->hsm.b_bus_req = 0; - iotg->otg.default_a = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_B_IDLE; - } else if (iotg->hsm.a_vbus_vld) { - langwell_otg_del_timer(a_wait_vrise_tmr); - iotg->hsm.b_conn = 0; - if (lnw->iotg.start_host) - lnw->iotg.start_host(&lnw->iotg); - else { - dev_dbg(lnw->dev, "host driver not loaded.\n"); - break; - } - - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } else if (iotg->hsm.a_wait_vrise_tmout) { - iotg->hsm.b_conn = 0; - if (iotg->hsm.a_vbus_vld) { - if (lnw->iotg.start_host) - lnw->iotg.start_host(&lnw->iotg); - else { - dev_dbg(lnw->dev, - "host driver not loaded.\n"); - break; - } - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } else { - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } - } - break; - case OTG_STATE_A_WAIT_BCON: - if (iotg->hsm.id) { - /* delete hsm timer for a_wait_bcon_tmr */ - del_timer_sync(&lnw->hsm_timer); - - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_vbus_vld) { - /* delete hsm timer for a_wait_bcon_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } else if (iotg->hsm.a_bus_drop || - (iotg->hsm.a_wait_bcon_tmout && - !iotg->hsm.a_bus_req)) { - /* delete hsm timer for a_wait_bcon_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (iotg->hsm.b_conn) { - /* delete hsm timer for a_wait_bcon_tmr */ - del_timer_sync(&lnw->hsm_timer); - - iotg->hsm.a_suspend_req = 0; - iotg->otg.state = OTG_STATE_A_HOST; - if (iotg->hsm.a_srp_det && iotg->otg.host && - !iotg->otg.host->b_hnp_enable) { - /* SRP capable peripheral-only device */ - iotg->hsm.a_bus_req = 1; - iotg->hsm.a_srp_det = 0; - } else if (!iotg->hsm.a_bus_req && iotg->otg.host && - iotg->otg.host->b_hnp_enable) { - /* It is not safe enough to do a fast - * transition from A_WAIT_BCON to - * A_SUSPEND */ - msleep(10000); - if (iotg->hsm.a_bus_req) - break; - - if (request_irq(pdev->irq, - otg_dummy_irq, IRQF_SHARED, - driver_name, iotg->base) != 0) { - dev_dbg(lnw->dev, - "request interrupt %d fail\n", - pdev->irq); - } - - langwell_otg_HABA(1); - iotg->hsm.b_bus_resume = 0; - iotg->hsm.a_aidl_bdis_tmout = 0; - - langwell_otg_loc_sof(0); - /* clear PHCD to enable HW timer */ - langwell_otg_phy_low_power(0); - langwell_otg_add_timer(a_aidl_bdis_tmr); - iotg->otg.state = OTG_STATE_A_SUSPEND; - } else if (!iotg->hsm.a_bus_req && iotg->otg.host && - !iotg->otg.host->b_hnp_enable) { - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } - } - break; - case OTG_STATE_A_HOST: - if (iotg->hsm.id) { - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.a_bus_drop || - (iotg->otg.host && - !iotg->otg.host->b_hnp_enable && - !iotg->hsm.a_bus_req)) { - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (!iotg->hsm.a_vbus_vld) { - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } else if (iotg->otg.host && - iotg->otg.host->b_hnp_enable && - !iotg->hsm.a_bus_req) { - /* Set HABA to enable hardware assistance to signal - * A-connect after receiver B-disconnect. Hardware - * will then set client mode and enable URE, SLE and - * PCE after the assistance. otg_dummy_irq is used to - * clean these ints when client driver is not resumed. - */ - if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED, - driver_name, iotg->base) != 0) { - dev_dbg(lnw->dev, - "request interrupt %d failed\n", - pdev->irq); - } - - /* set HABA */ - langwell_otg_HABA(1); - iotg->hsm.b_bus_resume = 0; - iotg->hsm.a_aidl_bdis_tmout = 0; - langwell_otg_loc_sof(0); - /* clear PHCD to enable HW timer */ - langwell_otg_phy_low_power(0); - langwell_otg_add_timer(a_aidl_bdis_tmr); - iotg->otg.state = OTG_STATE_A_SUSPEND; - } else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) { - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } - break; - case OTG_STATE_A_SUSPEND: - if (iotg->hsm.id) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.a_bus_req || - iotg->hsm.b_bus_resume) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - iotg->hsm.a_suspend_req = 0; - langwell_otg_loc_sof(1); - iotg->otg.state = OTG_STATE_A_HOST; - } else if (iotg->hsm.a_aidl_bdis_tmout || - iotg->hsm.a_bus_drop) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (!iotg->hsm.b_conn && iotg->otg.host && - iotg->otg.host->b_hnp_enable) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - iotg->hsm.b_bus_suspend = 0; - iotg->hsm.b_bus_suspend_vld = 0; - - /* msleep(200); */ - if (lnw->iotg.start_peripheral) - lnw->iotg.start_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver not loaded.\n"); - - langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR); - iotg->otg.state = OTG_STATE_A_PERIPHERAL; - break; - } else if (!iotg->hsm.a_vbus_vld) { - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - free_irq(pdev->irq, iotg->base); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } - break; - case OTG_STATE_A_PERIPHERAL: - if (iotg->hsm.id) { - /* delete hsm timer for b_bus_suspend_tmr */ - del_timer_sync(&lnw->hsm_timer); - iotg->otg.default_a = 0; - iotg->hsm.b_bus_req = 0; - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - set_client_mode(); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (!iotg->hsm.a_vbus_vld) { - /* delete hsm timer for b_bus_suspend_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - langwell_otg_phy_low_power_wait(1); - iotg->otg.state = OTG_STATE_A_VBUS_ERR; - } else if (iotg->hsm.a_bus_drop) { - /* delete hsm timer for b_bus_suspend_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_WAIT_VFALL; - } else if (iotg->hsm.b_bus_suspend) { - /* delete hsm timer for b_bus_suspend_tmr */ - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - if (lnw->iotg.start_host) - lnw->iotg.start_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver not loaded.\n"); - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } else if (iotg->hsm.b_bus_suspend_tmout) { - u32 val; - val = readl(lnw->iotg.base + CI_PORTSC1); - if (!(val & PORTSC_SUSP)) - break; - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(lnw->dev, - "client driver has been removed.\n"); - - if (lnw->iotg.start_host) - lnw->iotg.start_host(&lnw->iotg); - else - dev_dbg(lnw->dev, - "host driver not loaded.\n"); - langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); - iotg->otg.state = OTG_STATE_A_WAIT_BCON; - } - break; - case OTG_STATE_A_VBUS_ERR: - if (iotg->hsm.id) { - iotg->otg.default_a = 0; - iotg->hsm.a_clr_err = 0; - iotg->hsm.a_srp_det = 0; - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.a_clr_err) { - iotg->hsm.a_clr_err = 0; - iotg->hsm.a_srp_det = 0; - reset_otg(); - init_hsm(); - if (iotg->otg.state == OTG_STATE_A_IDLE) - langwell_update_transceiver(); - } else { - /* FW will clear PHCD bit when any VBus - * event detected. Reset PHCD to 1 again */ - langwell_otg_phy_low_power(1); - } - break; - case OTG_STATE_A_WAIT_VFALL: - if (iotg->hsm.id) { - iotg->otg.default_a = 0; - set_client_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_B_IDLE; - langwell_update_transceiver(); - } else if (iotg->hsm.a_bus_req) { - - /* Turn on VBus */ - iotg->otg.set_vbus(&iotg->otg, true); - iotg->hsm.a_wait_vrise_tmout = 0; - langwell_otg_add_timer(a_wait_vrise_tmr); - iotg->otg.state = OTG_STATE_A_WAIT_VRISE; - } else if (!iotg->hsm.a_sess_vld) { - iotg->hsm.a_srp_det = 0; - set_host_mode(); - langwell_otg_phy_low_power(1); - iotg->otg.state = OTG_STATE_A_IDLE; - } - break; - default: - ; - } - - dev_dbg(lnw->dev, "%s: new state = %s\n", __func__, - otg_state_string(iotg->otg.state)); -} - -static ssize_t -show_registers(struct device *_dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - t = scnprintf(next, size, - "\n" - "USBCMD = 0x%08x\n" - "USBSTS = 0x%08x\n" - "USBINTR = 0x%08x\n" - "ASYNCLISTADDR = 0x%08x\n" - "PORTSC1 = 0x%08x\n" - "HOSTPC1 = 0x%08x\n" - "OTGSC = 0x%08x\n" - "USBMODE = 0x%08x\n", - readl(lnw->iotg.base + 0x30), - readl(lnw->iotg.base + 0x34), - readl(lnw->iotg.base + 0x38), - readl(lnw->iotg.base + 0x48), - readl(lnw->iotg.base + 0x74), - readl(lnw->iotg.base + 0xb4), - readl(lnw->iotg.base + 0xf4), - readl(lnw->iotg.base + 0xf8) - ); - size -= t; - next += t; - - return PAGE_SIZE - size; -} -static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); - -static ssize_t -show_hsm(struct device *_dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - if (iotg->otg.host) - iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable; - - if (iotg->otg.gadget) - iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable; - - t = scnprintf(next, size, - "\n" - "current state = %s\n" - "a_bus_resume = \t%d\n" - "a_bus_suspend = \t%d\n" - "a_conn = \t%d\n" - "a_sess_vld = \t%d\n" - "a_srp_det = \t%d\n" - "a_vbus_vld = \t%d\n" - "b_bus_resume = \t%d\n" - "b_bus_suspend = \t%d\n" - "b_conn = \t%d\n" - "b_se0_srp = \t%d\n" - "b_sess_end = \t%d\n" - "b_sess_vld = \t%d\n" - "id = \t%d\n" - "a_set_b_hnp_en = \t%d\n" - "b_srp_done = \t%d\n" - "b_hnp_enable = \t%d\n" - "a_wait_vrise_tmout = \t%d\n" - "a_wait_bcon_tmout = \t%d\n" - "a_aidl_bdis_tmout = \t%d\n" - "b_ase0_brst_tmout = \t%d\n" - "a_bus_drop = \t%d\n" - "a_bus_req = \t%d\n" - "a_clr_err = \t%d\n" - "a_suspend_req = \t%d\n" - "b_bus_req = \t%d\n" - "b_bus_suspend_tmout = \t%d\n" - "b_bus_suspend_vld = \t%d\n", - otg_state_string(iotg->otg.state), - iotg->hsm.a_bus_resume, - iotg->hsm.a_bus_suspend, - iotg->hsm.a_conn, - iotg->hsm.a_sess_vld, - iotg->hsm.a_srp_det, - iotg->hsm.a_vbus_vld, - iotg->hsm.b_bus_resume, - iotg->hsm.b_bus_suspend, - iotg->hsm.b_conn, - iotg->hsm.b_se0_srp, - iotg->hsm.b_sess_end, - iotg->hsm.b_sess_vld, - iotg->hsm.id, - iotg->hsm.a_set_b_hnp_en, - iotg->hsm.b_srp_done, - iotg->hsm.b_hnp_enable, - iotg->hsm.a_wait_vrise_tmout, - iotg->hsm.a_wait_bcon_tmout, - iotg->hsm.a_aidl_bdis_tmout, - iotg->hsm.b_ase0_brst_tmout, - iotg->hsm.a_bus_drop, - iotg->hsm.a_bus_req, - iotg->hsm.a_clr_err, - iotg->hsm.a_suspend_req, - iotg->hsm.b_bus_req, - iotg->hsm.b_bus_suspend_tmout, - iotg->hsm.b_bus_suspend_vld - ); - size -= t; - next += t; - - return PAGE_SIZE - size; -} -static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL); - -static ssize_t -get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req); - size -= t; - next += t; - - return PAGE_SIZE - size; -} - -static ssize_t -set_a_bus_req(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - - if (!iotg->otg.default_a) - return -1; - if (count > 2) - return -1; - - if (buf[0] == '0') { - iotg->hsm.a_bus_req = 0; - dev_dbg(lnw->dev, "User request: a_bus_req = 0\n"); - } else if (buf[0] == '1') { - /* If a_bus_drop is TRUE, a_bus_req can't be set */ - if (iotg->hsm.a_bus_drop) - return -1; - iotg->hsm.a_bus_req = 1; - dev_dbg(lnw->dev, "User request: a_bus_req = 1\n"); - } - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - return count; -} -static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req); - -static ssize_t -get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop); - size -= t; - next += t; - - return PAGE_SIZE - size; -} - -static ssize_t -set_a_bus_drop(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - - if (!iotg->otg.default_a) - return -1; - if (count > 2) - return -1; - - if (buf[0] == '0') { - iotg->hsm.a_bus_drop = 0; - dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n"); - } else if (buf[0] == '1') { - iotg->hsm.a_bus_drop = 1; - iotg->hsm.a_bus_req = 0; - dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n"); - dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n"); - } - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - return count; -} -static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop, set_a_bus_drop); - -static ssize_t -get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct langwell_otg *lnw = the_transceiver; - char *next; - unsigned size, t; - - next = buf; - size = PAGE_SIZE; - - t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req); - size -= t; - next += t; - - return PAGE_SIZE - size; -} - -static ssize_t -set_b_bus_req(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - - if (iotg->otg.default_a) - return -1; - - if (count > 2) - return -1; - - if (buf[0] == '0') { - iotg->hsm.b_bus_req = 0; - dev_dbg(lnw->dev, "User request: b_bus_req = 0\n"); - } else if (buf[0] == '1') { - iotg->hsm.b_bus_req = 1; - dev_dbg(lnw->dev, "User request: b_bus_req = 1\n"); - } - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - return count; -} -static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req); - -static ssize_t -set_a_clr_err(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - - if (!iotg->otg.default_a) - return -1; - if (count > 2) - return -1; - - if (buf[0] == '1') { - iotg->hsm.a_clr_err = 1; - dev_dbg(lnw->dev, "User request: a_clr_err = 1\n"); - } - if (spin_trylock(&lnw->wq_lock)) { - langwell_update_transceiver(); - spin_unlock(&lnw->wq_lock); - } - return count; -} -static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err); - -static struct attribute *inputs_attrs[] = { - &dev_attr_a_bus_req.attr, - &dev_attr_a_bus_drop.attr, - &dev_attr_b_bus_req.attr, - &dev_attr_a_clr_err.attr, - NULL, -}; - -static struct attribute_group debug_dev_attr_group = { - .name = "inputs", - .attrs = inputs_attrs, -}; - -static int langwell_otg_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - unsigned long resource, len; - void __iomem *base = NULL; - int retval; - u32 val32; - struct langwell_otg *lnw; - char qname[] = "langwell_otg_queue"; - - retval = 0; - dev_dbg(&pdev->dev, "\notg controller is detected.\n"); - if (pci_enable_device(pdev) < 0) { - retval = -ENODEV; - goto done; - } - - lnw = kzalloc(sizeof *lnw, GFP_KERNEL); - if (lnw == NULL) { - retval = -ENOMEM; - goto done; - } - the_transceiver = lnw; - - /* control register: BAR 0 */ - resource = pci_resource_start(pdev, 0); - len = pci_resource_len(pdev, 0); - if (!request_mem_region(resource, len, driver_name)) { - retval = -EBUSY; - goto err; - } - lnw->region = 1; - - base = ioremap_nocache(resource, len); - if (base == NULL) { - retval = -EFAULT; - goto err; - } - lnw->iotg.base = base; - - if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) { - retval = -EBUSY; - goto err; - } - lnw->cfg_region = 1; - - /* For the SCCB.USBCFG register */ - base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN); - if (base == NULL) { - retval = -EFAULT; - goto err; - } - lnw->usbcfg = base; - - if (!pdev->irq) { - dev_dbg(&pdev->dev, "No IRQ.\n"); - retval = -ENODEV; - goto err; - } - - lnw->qwork = create_singlethread_workqueue(qname); - if (!lnw->qwork) { - dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname); - retval = -ENOMEM; - goto err; - } - INIT_WORK(&lnw->work, langwell_otg_work); - - /* OTG common part */ - lnw->dev = &pdev->dev; - lnw->iotg.otg.dev = lnw->dev; - lnw->iotg.otg.label = driver_name; - lnw->iotg.otg.set_host = langwell_otg_set_host; - lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral; - lnw->iotg.otg.set_power = langwell_otg_set_power; - lnw->iotg.otg.set_vbus = langwell_otg_set_vbus; - lnw->iotg.otg.start_srp = langwell_otg_start_srp; - lnw->iotg.otg.state = OTG_STATE_UNDEFINED; - - if (otg_set_transceiver(&lnw->iotg.otg)) { - dev_dbg(lnw->dev, "can't set transceiver\n"); - retval = -EBUSY; - goto err; - } - - reset_otg(); - init_hsm(); - - spin_lock_init(&lnw->lock); - spin_lock_init(&lnw->wq_lock); - INIT_LIST_HEAD(&active_timers); - retval = langwell_otg_init_timers(&lnw->iotg.hsm); - if (retval) { - dev_dbg(&pdev->dev, "Failed to init timers\n"); - goto err; - } - - init_timer(&lnw->hsm_timer); - ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier); - - lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify; - - retval = intel_mid_otg_register_notifier(&lnw->iotg, - &lnw->iotg_notifier); - if (retval) { - dev_dbg(lnw->dev, "Failed to register notifier\n"); - goto err; - } - - if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, - driver_name, lnw) != 0) { - dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq); - retval = -EBUSY; - goto err; - } - - /* enable OTGSC int */ - val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE | - OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU; - writel(val32, lnw->iotg.base + CI_OTGSC); - - retval = device_create_file(&pdev->dev, &dev_attr_registers); - if (retval < 0) { - dev_dbg(lnw->dev, - "Can't register sysfs attribute: %d\n", retval); - goto err; - } - - retval = device_create_file(&pdev->dev, &dev_attr_hsm); - if (retval < 0) { - dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval); - goto err; - } - - retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group); - if (retval < 0) { - dev_dbg(lnw->dev, - "Can't register sysfs attr group: %d\n", retval); - goto err; - } - - if (lnw->iotg.otg.state == OTG_STATE_A_IDLE) - langwell_update_transceiver(); - - return 0; - -err: - if (the_transceiver) - langwell_otg_remove(pdev); -done: - return retval; -} - -static void langwell_otg_remove(struct pci_dev *pdev) -{ - struct langwell_otg *lnw = the_transceiver; - - if (lnw->qwork) { - flush_workqueue(lnw->qwork); - destroy_workqueue(lnw->qwork); - } - intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier); - langwell_otg_free_timers(); - - /* disable OTGSC interrupt as OTGSC doesn't change in reset */ - writel(0, lnw->iotg.base + CI_OTGSC); - - if (pdev->irq) - free_irq(pdev->irq, lnw); - if (lnw->usbcfg) - iounmap(lnw->usbcfg); - if (lnw->cfg_region) - release_mem_region(USBCFG_ADDR, USBCFG_LEN); - if (lnw->iotg.base) - iounmap(lnw->iotg.base); - if (lnw->region) - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - - otg_set_transceiver(NULL); - pci_disable_device(pdev); - sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group); - device_remove_file(&pdev->dev, &dev_attr_hsm); - device_remove_file(&pdev->dev, &dev_attr_registers); - kfree(lnw); - lnw = NULL; -} - -static void transceiver_suspend(struct pci_dev *pdev) -{ - pci_save_state(pdev); - pci_set_power_state(pdev, PCI_D3hot); - langwell_otg_phy_low_power(1); -} - -static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message) -{ - struct langwell_otg *lnw = the_transceiver; - struct intel_mid_otg_xceiv *iotg = &lnw->iotg; - int ret = 0; - - /* Disbale OTG interrupts */ - langwell_otg_intr(0); - - if (pdev->irq) - free_irq(pdev->irq, lnw); - - /* Prevent more otg_work */ - flush_workqueue(lnw->qwork); - destroy_workqueue(lnw->qwork); - lnw->qwork = NULL; - - /* start actions */ - switch (iotg->otg.state) { - case OTG_STATE_A_WAIT_VFALL: - iotg->otg.state = OTG_STATE_A_IDLE; - case OTG_STATE_A_IDLE: - case OTG_STATE_B_IDLE: - case OTG_STATE_A_VBUS_ERR: - transceiver_suspend(pdev); - break; - case OTG_STATE_A_WAIT_VRISE: - langwell_otg_del_timer(a_wait_vrise_tmr); - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_A_WAIT_BCON: - del_timer_sync(&lnw->hsm_timer); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_A_HOST: - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_A_SUSPEND: - langwell_otg_del_timer(a_aidl_bdis_tmr); - langwell_otg_HABA(0); - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(lnw->dev, "host driver has been removed.\n"); - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_A_PERIPHERAL: - del_timer_sync(&lnw->hsm_timer); - - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(&pdev->dev, - "client driver has been removed.\n"); - iotg->hsm.a_srp_det = 0; - - /* Turn off VBus */ - iotg->otg.set_vbus(&iotg->otg, false); - iotg->otg.state = OTG_STATE_A_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_B_HOST: - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - iotg->hsm.b_bus_req = 0; - iotg->otg.state = OTG_STATE_B_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_B_PERIPHERAL: - if (lnw->iotg.stop_peripheral) - lnw->iotg.stop_peripheral(&lnw->iotg); - else - dev_dbg(&pdev->dev, - "client driver has been removed.\n"); - iotg->otg.state = OTG_STATE_B_IDLE; - transceiver_suspend(pdev); - break; - case OTG_STATE_B_WAIT_ACON: - /* delete hsm timer for b_ase0_brst_tmr */ - del_timer_sync(&lnw->hsm_timer); - - langwell_otg_HAAR(0); - - if (lnw->iotg.stop_host) - lnw->iotg.stop_host(&lnw->iotg); - else - dev_dbg(&pdev->dev, "host driver has been removed.\n"); - iotg->hsm.b_bus_req = 0; - iotg->otg.state = OTG_STATE_B_IDLE; - transceiver_suspend(pdev); - break; - default: - dev_dbg(lnw->dev, "error state before suspend\n"); - break; - } - - return ret; -} - -static void transceiver_resume(struct pci_dev *pdev) -{ - pci_restore_state(pdev); - pci_set_power_state(pdev, PCI_D0); -} - -static int langwell_otg_resume(struct pci_dev *pdev) -{ - struct langwell_otg *lnw = the_transceiver; - int ret = 0; - - transceiver_resume(pdev); - - lnw->qwork = create_singlethread_workqueue("langwell_otg_queue"); - if (!lnw->qwork) { - dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen"); - ret = -ENOMEM; - goto error; - } - - if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, - driver_name, lnw) != 0) { - dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq); - ret = -EBUSY; - goto error; - } - - /* enable OTG interrupts */ - langwell_otg_intr(1); - - update_hsm(); - - langwell_update_transceiver(); - - return ret; -error: - langwell_otg_intr(0); - transceiver_suspend(pdev); - return ret; -} - -static int __init langwell_otg_init(void) -{ - return pci_register_driver(&otg_pci_driver); -} -module_init(langwell_otg_init); - -static void __exit langwell_otg_cleanup(void) -{ - pci_unregister_driver(&otg_pci_driver); -} -module_exit(langwell_otg_cleanup); diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c index db0d4fcdc8e2..b5fbe1452ab0 100644 --- a/drivers/usb/otg/mv_otg.c +++ b/drivers/usb/otg/mv_otg.c @@ -202,6 +202,7 @@ static void mv_otg_init_irq(struct mv_otg *mvotg) static void mv_otg_start_host(struct mv_otg *mvotg, int on) { +#ifdef CONFIG_USB struct otg_transceiver *otg = &mvotg->otg; struct usb_hcd *hcd; @@ -216,6 +217,7 @@ static void mv_otg_start_host(struct mv_otg *mvotg, int on) usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); else usb_remove_hcd(hcd); +#endif /* CONFIG_USB */ } static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 528691d5f3e2..7542aa94a462 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -425,7 +425,7 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv, struct usbhs_pipe *pipe; int recip = ctrl->bRequestType & USB_RECIP_MASK; int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK; - int ret; + int ret = 0; int (*func)(struct usbhs_priv *priv, struct usbhsg_uep *uep, struct usb_ctrlrequest *ctrl); char *msg; diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index fba1147ed916..8dbf51a43c45 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -39,6 +39,8 @@ static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *port); static void cp210x_get_termios_port(struct usb_serial_port *port, unsigned int *cflagp, unsigned int *baudp); +static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *, + struct ktermios *); static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *, struct ktermios*); static int cp210x_tiocmget(struct tty_struct *); @@ -138,6 +140,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ + { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */ { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { } /* Terminating Entry */ }; @@ -201,6 +204,8 @@ static struct usb_serial_driver cp210x_device = { #define CP210X_EMBED_EVENTS 0x15 #define CP210X_GET_EVENTSTATE 0x16 #define CP210X_SET_CHARS 0x19 +#define CP210X_GET_BAUDRATE 0x1D +#define CP210X_SET_BAUDRATE 0x1E /* CP210X_IFC_ENABLE */ #define UART_ENABLE 0x0001 @@ -360,8 +365,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port, * Quantises the baud rate as per AN205 Table 1 */ static unsigned int cp210x_quantise_baudrate(unsigned int baud) { - if (baud <= 56) baud = 0; - else if (baud <= 300) baud = 300; + if (baud <= 300) + baud = 300; else if (baud <= 600) baud = 600; else if (baud <= 1200) baud = 1200; else if (baud <= 1800) baud = 1800; @@ -389,10 +394,10 @@ static unsigned int cp210x_quantise_baudrate(unsigned int baud) { else if (baud <= 491520) baud = 460800; else if (baud <= 567138) baud = 500000; else if (baud <= 670254) baud = 576000; - else if (baud <= 1053257) baud = 921600; - else if (baud <= 1474560) baud = 1228800; - else if (baud <= 2457600) baud = 1843200; - else baud = 3686400; + else if (baud < 1000000) + baud = 921600; + else if (baud > 2000000) + baud = 2000000; return baud; } @@ -409,13 +414,14 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port) return result; } - result = usb_serial_generic_open(tty, port); - if (result) - return result; - /* Configure the termios structure */ cp210x_get_termios(tty, port); - return 0; + + /* The baud rate must be initialised on cp2104 */ + if (tty) + cp210x_change_speed(tty, port, NULL); + + return usb_serial_generic_open(tty, port); } static void cp210x_close(struct usb_serial_port *port) @@ -467,10 +473,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, dbg("%s - port %d", __func__, port->number); - cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2); - /* Convert to baudrate */ - if (baud) - baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); + cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4); dbg("%s - baud rate = %d", __func__, baud); *baudp = baud; @@ -579,11 +582,64 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, *cflagp = cflag; } +/* + * CP2101 supports the following baud rates: + * + * 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800, + * 38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600 + * + * CP2102 and CP2103 support the following additional rates: + * + * 4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000, + * 576000 + * + * The device will map a requested rate to a supported one, but the result + * of requests for rates greater than 1053257 is undefined (see AN205). + * + * CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud, + * respectively, with an error less than 1%. The actual rates are determined + * by + * + * div = round(freq / (2 x prescale x request)) + * actual = freq / (2 x prescale x div) + * + * For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps + * or 1 otherwise. + * For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1 + * otherwise. + */ +static void cp210x_change_speed(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) +{ + u32 baud; + + baud = tty->termios->c_ospeed; + + /* This maps the requested rate to a rate valid on cp2102 or cp2103, + * or to an arbitrary rate in [1M,2M]. + * + * NOTE: B0 is not implemented. + */ + baud = cp210x_quantise_baudrate(baud); + + dbg("%s - setting baud rate to %u", __func__, baud); + if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud, + sizeof(baud))) { + dev_warn(&port->dev, "failed to set baud rate to %u\n", baud); + if (old_termios) + baud = old_termios->c_ospeed; + else + baud = 9600; + } + + tty_encode_baud_rate(tty, baud, baud); +} + static void cp210x_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { unsigned int cflag, old_cflag; - unsigned int baud = 0, bits; + unsigned int bits; unsigned int modem_ctl[4]; dbg("%s - port %d", __func__, port->number); @@ -593,20 +649,9 @@ static void cp210x_set_termios(struct tty_struct *tty, cflag = tty->termios->c_cflag; old_cflag = old_termios->c_cflag; - baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty)); - - /* If the baud rate is to be updated*/ - if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { - dbg("%s - Setting baud rate to %d baud", __func__, - baud); - if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV, - ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { - dbg("Baud rate requested not supported by device"); - baud = tty_termios_baud_rate(old_termios); - } - } - /* Report back the resulting baud rate */ - tty_encode_baud_rate(tty, baud, baud); + + if (tty->termios->c_ospeed != old_termios->c_ospeed) + cp210x_change_speed(tty, port, old_termios); /* If the number of data bits is to be updated */ if ((cflag & CSIZE) != (old_cflag & CSIZE)) { diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 01b6404df395..ad654f8208ef 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -797,6 +797,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, @@ -805,6 +806,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, TI_XDS100V2_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) }, { USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) }, { USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) }, @@ -841,6 +844,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ST_VID, ST_STMCLT1030_PID), .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_RF_R106) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -1333,8 +1337,7 @@ static int set_serial_info(struct tty_struct *tty, goto check_and_exit; } - if ((new_serial.baud_base != priv->baud_base) && - (new_serial.baud_base < 9600)) { + if (new_serial.baud_base != priv->baud_base) { mutex_unlock(&priv->cfg_lock); return -EINVAL; } @@ -1824,6 +1827,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) { + struct ktermios dummy; struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); int result; @@ -1842,8 +1846,10 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) This is same behaviour as serial.c/rs_open() - Kuba */ /* ftdi_set_termios will send usb control messages */ - if (tty) - ftdi_set_termios(tty, port, tty->termios); + if (tty) { + memset(&dummy, 0, sizeof(dummy)); + ftdi_set_termios(tty, port, &dummy); + } /* Start reading from the device */ result = usb_serial_generic_open(tty, port); diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index df1d7da933ec..f994503df2dd 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -39,6 +39,13 @@ /* www.candapter.com Ewert Energy Systems CANdapter device */ #define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */ +/* + * Texas Instruments XDS100v2 JTAG / BeagleBone A3 + * http://processors.wiki.ti.com/index.php/XDS100 + * http://beagleboard.org/bone + */ +#define TI_XDS100V2_PID 0xa6d0 + #define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ /* US Interface Navigator (http://www.usinterface.com/) */ @@ -525,6 +532,12 @@ #define ADI_GNICEPLUS_PID 0xF001 /* + * Hornby Elite + */ +#define HORNBY_VID 0x04D8 +#define HORNBY_ELITE_PID 0x000A + +/* * RATOC REX-USB60F */ #define RATOC_VENDOR_ID 0x0584 @@ -1168,3 +1181,9 @@ */ /* TagTracer MIFARE*/ #define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID 0xF7C0 + +/* + * Rainforest Automation + */ +/* ZigBee controller */ +#define FTDI_RF_R106 0x8A28 diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 65bf06aa591a..5818bfc3261e 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2657,15 +2657,7 @@ cleanup: static void edge_disconnect(struct usb_serial *serial) { - int i; - struct edgeport_port *edge_port; - dbg("%s", __func__); - - for (i = 0; i < serial->num_ports; ++i) { - edge_port = usb_get_serial_port_data(serial->port[i]); - edge_remove_sysfs_attrs(edge_port->port); - } } static void edge_release(struct usb_serial *serial) @@ -2744,6 +2736,7 @@ static struct usb_serial_driver edgeport_1port_device = { .disconnect = edge_disconnect, .release = edge_release, .port_probe = edge_create_sysfs_attrs, + .port_remove = edge_remove_sysfs_attrs, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -2775,6 +2768,7 @@ static struct usb_serial_driver edgeport_2port_device = { .disconnect = edge_disconnect, .release = edge_release, .port_probe = edge_create_sysfs_attrs, + .port_remove = edge_remove_sysfs_attrs, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 5d3beeeb5fd9..a92a3efb507b 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -38,7 +38,7 @@ #include <linux/ioctl.h> #include "kobil_sct.h" -static int debug; +static bool debug; /* Version Information */ #define DRIVER_VERSION "21/05/2004" diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 420d9857394a..ea126a4490cd 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -480,6 +480,10 @@ static void option_instat_callback(struct urb *urb); #define ZD_VENDOR_ID 0x0685 #define ZD_PRODUCT_7000 0x7000 +/* LG products */ +#define LG_VENDOR_ID 0x1004 +#define LG_PRODUCT_L02C 0x618f + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -1183,6 +1187,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) }, { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) }, + { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index 30b73e68a904..a34819884c1a 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -36,6 +36,7 @@ #define UTSTARCOM_PRODUCT_UM175_V1 0x3712 #define UTSTARCOM_PRODUCT_UM175_V2 0x3714 #define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715 +#define PANTECH_PRODUCT_UML190_VZW 0x3716 #define PANTECH_PRODUCT_UML290_VZW 0x3718 /* CMOTECH devices */ @@ -67,7 +68,11 @@ static struct usb_device_id id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */ + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) }, /* WMC */ + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, /* DIAG */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 1f62723ef1a8..d32f72061c09 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -789,7 +789,7 @@ static void rts51x_suspend_timer_fn(unsigned long data) rts51x_set_stat(chip, RTS51X_STAT_SS); /* ignore mass storage interface's children */ pm_suspend_ignore_children(&us->pusb_intf->dev, true); - usb_autopm_put_interface(us->pusb_intf); + usb_autopm_put_interface_async(us->pusb_intf); US_DEBUGP("%s: RTS51X_STAT_SS 01," "intf->pm_usage_cnt:%d, power.usage:%d\n", __func__, diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 8efeae24764f..b4a71679c933 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -27,8 +27,6 @@ #define USB_SKEL_VENDOR_ID 0xfff0 #define USB_SKEL_PRODUCT_ID 0xfff0 -static DEFINE_MUTEX(skel_mutex); - /* table of devices that work with this driver */ static const struct usb_device_id skel_table[] = { { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, @@ -101,25 +99,18 @@ static int skel_open(struct inode *inode, struct file *file) goto exit; } - mutex_lock(&skel_mutex); dev = usb_get_intfdata(interface); if (!dev) { - mutex_unlock(&skel_mutex); retval = -ENODEV; goto exit; } /* increment our usage count for the device */ kref_get(&dev->kref); - mutex_unlock(&skel_mutex); /* lock the device to allow correctly handling errors * in resumption */ mutex_lock(&dev->io_mutex); - if (!dev->interface) { - retval = -ENODEV; - goto out_err; - } retval = usb_autopm_get_interface(interface); if (retval) @@ -127,11 +118,7 @@ static int skel_open(struct inode *inode, struct file *file) /* save our object in the file's private structure */ file->private_data = dev; - -out_err: mutex_unlock(&dev->io_mutex); - if (retval) - kref_put(&dev->kref, skel_delete); exit: return retval; @@ -611,6 +598,7 @@ static void skel_disconnect(struct usb_interface *interface) int minor = interface->minor; dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); /* give back our minor */ usb_deregister_dev(interface, &skel_class); @@ -622,12 +610,8 @@ static void skel_disconnect(struct usb_interface *interface) usb_kill_anchored_urbs(&dev->submitted); - mutex_lock(&skel_mutex); - usb_set_intfdata(interface, NULL); - /* decrement our usage count */ kref_put(&dev->kref, skel_delete); - mutex_unlock(&skel_mutex); dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor); } diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig index 0ead8826ec79..f29fdd7f6d75 100644 --- a/drivers/usb/wusbcore/Kconfig +++ b/drivers/usb/wusbcore/Kconfig @@ -6,7 +6,7 @@ config USB_WUSB depends on EXPERIMENTAL depends on USB depends on PCI - select UWB + depends on UWB select CRYPTO select CRYPTO_BLKCIPHER select CRYPTO_CBC diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 43207cc6cc19..fe01add3700e 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -592,12 +592,12 @@ static int __init macfb_init(void) if (!fb_info.screen_base) return -ENODEV; - printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n", - macfb_fix.smem_start, fb_info.screen_base, - macfb_fix.smem_len / 1024); - printk("macfb: mode is %dx%dx%d, linelength=%d\n", - macfb_defined.xres, macfb_defined.yres, - macfb_defined.bits_per_pixel, macfb_fix.line_length); + pr_info("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n", + macfb_fix.smem_start, fb_info.screen_base, + macfb_fix.smem_len / 1024); + pr_info("macfb: mode is %dx%dx%d, linelength=%d\n", + macfb_defined.xres, macfb_defined.yres, + macfb_defined.bits_per_pixel, macfb_fix.line_length); /* Fill in the available video resolution */ macfb_defined.xres_virtual = macfb_defined.xres; @@ -613,14 +613,10 @@ static int __init macfb_init(void) switch (macfb_defined.bits_per_pixel) { case 1: - /* - * XXX: I think this will catch any program that tries - * to do FBIO_PUTCMAP when the visual is monochrome. - */ macfb_defined.red.length = macfb_defined.bits_per_pixel; macfb_defined.green.length = macfb_defined.bits_per_pixel; macfb_defined.blue.length = macfb_defined.bits_per_pixel; - video_cmap_len = 0; + video_cmap_len = 2; macfb_fix.visual = FB_VISUAL_MONO01; break; case 2: @@ -660,11 +656,10 @@ static int __init macfb_init(void) macfb_fix.visual = FB_VISUAL_TRUECOLOR; break; default: - video_cmap_len = 0; - macfb_fix.visual = FB_VISUAL_MONO01; - printk("macfb: unknown or unsupported bit depth: %d\n", + pr_err("macfb: unknown or unsupported bit depth: %d\n", macfb_defined.bits_per_pixel); - break; + err = -EINVAL; + goto fail_unmap; } /* @@ -734,8 +729,8 @@ static int __init macfb_init(void) case MAC_MODEL_Q950: strcpy(macfb_fix.id, "DAFB"); macfb_setpalette = dafb_setpalette; - macfb_defined.activate = FB_ACTIVATE_NOW; dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000); + macfb_defined.activate = FB_ACTIVATE_NOW; break; /* @@ -744,8 +739,8 @@ static int __init macfb_init(void) case MAC_MODEL_LCII: strcpy(macfb_fix.id, "V8"); macfb_setpalette = v8_brazil_setpalette; - macfb_defined.activate = FB_ACTIVATE_NOW; v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); + macfb_defined.activate = FB_ACTIVATE_NOW; break; /* @@ -758,8 +753,8 @@ static int __init macfb_init(void) case MAC_MODEL_P600: strcpy(macfb_fix.id, "Brazil"); macfb_setpalette = v8_brazil_setpalette; - macfb_defined.activate = FB_ACTIVATE_NOW; v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); + macfb_defined.activate = FB_ACTIVATE_NOW; break; /* @@ -773,10 +768,10 @@ static int __init macfb_init(void) case MAC_MODEL_P520: case MAC_MODEL_P550: case MAC_MODEL_P460: - macfb_setpalette = v8_brazil_setpalette; - macfb_defined.activate = FB_ACTIVATE_NOW; strcpy(macfb_fix.id, "Sonora"); + macfb_setpalette = v8_brazil_setpalette; v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); + macfb_defined.activate = FB_ACTIVATE_NOW; break; /* @@ -786,10 +781,10 @@ static int __init macfb_init(void) */ case MAC_MODEL_IICI: case MAC_MODEL_IISI: - macfb_setpalette = rbv_setpalette; - macfb_defined.activate = FB_ACTIVATE_NOW; strcpy(macfb_fix.id, "RBV"); + macfb_setpalette = rbv_setpalette; rbv_cmap_regs = ioremap(DAC_BASE, 0x1000); + macfb_defined.activate = FB_ACTIVATE_NOW; break; /* @@ -797,10 +792,10 @@ static int __init macfb_init(void) */ case MAC_MODEL_Q840: case MAC_MODEL_C660: - macfb_setpalette = civic_setpalette; - macfb_defined.activate = FB_ACTIVATE_NOW; strcpy(macfb_fix.id, "Civic"); + macfb_setpalette = civic_setpalette; civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000); + macfb_defined.activate = FB_ACTIVATE_NOW; break; @@ -809,26 +804,26 @@ static int __init macfb_init(void) * We think this may be like the LC II */ case MAC_MODEL_LC: + strcpy(macfb_fix.id, "LC"); if (vidtest) { macfb_setpalette = v8_brazil_setpalette; - macfb_defined.activate = FB_ACTIVATE_NOW; v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); + macfb_defined.activate = FB_ACTIVATE_NOW; } - strcpy(macfb_fix.id, "LC"); break; /* * We think this may be like the LC II */ case MAC_MODEL_CCL: + strcpy(macfb_fix.id, "Color Classic"); if (vidtest) { macfb_setpalette = v8_brazil_setpalette; - macfb_defined.activate = FB_ACTIVATE_NOW; v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); + macfb_defined.activate = FB_ACTIVATE_NOW; } - strcpy(macfb_fix.id, "Color Classic"); break; /* @@ -893,10 +888,10 @@ static int __init macfb_init(void) case MAC_MODEL_PB270C: case MAC_MODEL_PB280: case MAC_MODEL_PB280C: - macfb_setpalette = csc_setpalette; - macfb_defined.activate = FB_ACTIVATE_NOW; strcpy(macfb_fix.id, "CSC"); + macfb_setpalette = csc_setpalette; csc_cmap_regs = ioremap(CSC_BASE, 0x1000); + macfb_defined.activate = FB_ACTIVATE_NOW; break; default: @@ -918,8 +913,9 @@ static int __init macfb_init(void) if (err) goto fail_dealloc; - printk("fb%d: %s frame buffer device\n", - fb_info.node, fb_info.fix.id); + pr_info("fb%d: %s frame buffer device\n", + fb_info.node, fb_info.fix.id); + return 0; fail_dealloc: diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 79e1b292c030..5aa43c3392a2 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -35,7 +35,7 @@ #define virtio_rmb(vq) \ do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0) #define virtio_wmb(vq) \ - do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0) + do { if ((vq)->weak_barriers) smp_wmb(); else wmb(); } while(0) #else /* We must force memory ordering even if guest is UP since host could be * running on another CPU, but SMP barriers are defined to barrier() in that @@ -308,9 +308,9 @@ bool virtqueue_kick_prepare(struct virtqueue *_vq) bool needs_kick; START_USE(vq); - /* Descriptors and available array need to be set before we expose the - * new available array entries. */ - virtio_wmb(vq); + /* We need to expose available array entries before checking avail + * event. */ + virtio_mb(vq); old = vq->vring.avail->idx - vq->num_added; new = vq->vring.avail->idx; diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index 1b0e3dd81c1a..63d7b58f1c7d 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -300,11 +300,7 @@ static int __devinit dw_wdt_drv_probe(struct platform_device *pdev) if (!mem) return -EINVAL; - if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), - "dw_wdt")) - return -ENOMEM; - - dw_wdt.regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); + dw_wdt.regs = devm_request_and_ioremap(&pdev->dev, mem); if (!dw_wdt.regs) return -ENOMEM; diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 99796c5d913d..bdf401b240b5 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -36,6 +36,7 @@ * document number TBD : Patsburg (PBG) * document number TBD : DH89xxCC * document number TBD : Panther Point + * document number TBD : Lynx Point */ /* @@ -126,6 +127,7 @@ enum iTCO_chipsets { TCO_PBG, /* Patsburg */ TCO_DH89XXCC, /* DH89xxCC */ TCO_PPT, /* Panther Point */ + TCO_LPT, /* Lynx Point */ }; static struct { @@ -189,6 +191,7 @@ static struct { {"Patsburg", 2}, {"DH89xxCC", 2}, {"Panther Point", 2}, + {"Lynx Point", 2}, {NULL, 0} }; @@ -331,6 +334,38 @@ static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = { { PCI_VDEVICE(INTEL, 0x1e5d), TCO_PPT}, { PCI_VDEVICE(INTEL, 0x1e5e), TCO_PPT}, { PCI_VDEVICE(INTEL, 0x1e5f), TCO_PPT}, + { PCI_VDEVICE(INTEL, 0x8c40), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c41), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c42), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c43), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c44), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c45), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c46), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c47), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c48), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c49), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4a), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4b), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4c), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4d), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4e), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4f), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c50), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c51), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c52), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c53), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c54), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c55), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c56), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c57), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c58), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c59), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5a), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5b), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5c), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5d), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5e), TCO_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5f), TCO_LPT}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index b8ef2c6dca7c..c44c3334003a 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -247,7 +247,6 @@ static struct miscdevice imx2_wdt_miscdev = { static int __init imx2_wdt_probe(struct platform_device *pdev) { int ret; - int res_size; struct resource *res; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -256,15 +255,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) return -ENODEV; } - res_size = resource_size(res); - if (!devm_request_mem_region(&pdev->dev, res->start, res_size, - res->name)) { - dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n", - res_size, res->start); - return -ENOMEM; - } - - imx2_wdt.base = devm_ioremap_nocache(&pdev->dev, res->start, res_size); + imx2_wdt.base = devm_request_and_ioremap(&pdev->dev, res); if (!imx2_wdt.base) { dev_err(&pdev->dev, "ioremap failed\n"); return -ENOMEM; diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c index 50359bad9177..529085b8b8fb 100644 --- a/drivers/watchdog/nuc900_wdt.c +++ b/drivers/watchdog/nuc900_wdt.c @@ -72,7 +72,7 @@ struct nuc900_wdt { }; static unsigned long nuc900wdt_busy; -struct nuc900_wdt *nuc900_wdt; +static struct nuc900_wdt *nuc900_wdt; static inline void nuc900_wdt_keepalive(void) { @@ -287,7 +287,8 @@ static int __devinit nuc900wdt_probe(struct platform_device *pdev) setup_timer(&nuc900_wdt->timer, nuc900_wdt_timer_ping, 0); - if (misc_register(&nuc900wdt_miscdev)) { + ret = misc_register(&nuc900wdt_miscdev); + if (ret) { dev_err(&pdev->dev, "err register miscdev on minor=%d (%d)\n", WATCHDOG_MINOR, ret); goto err_clk; diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 4b33e3fd726b..d19ff5145e82 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -339,6 +339,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) return 0; err_misc: + pm_runtime_disable(wdev->dev); platform_set_drvdata(pdev, NULL); iounmap(wdev->base); @@ -371,6 +372,7 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev) struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pm_runtime_disable(wdev->dev); if (!res) return -ENOENT; diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index bd143c9dd3e6..8e210aafdfd0 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -226,7 +226,7 @@ static long pnx4008_wdt_ioctl(struct file *file, unsigned int cmd, static int pnx4008_wdt_release(struct inode *inode, struct file *file) { if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status)) - printk(KERN_WARNING "WATCHDOG: Device closed unexpectdly\n"); + printk(KERN_WARNING "WATCHDOG: Device closed unexpectedly\n"); wdt_disable(); clk_disable(wdt_clk); diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c index 4c2a4e8698f9..e37d81178b9e 100644 --- a/drivers/watchdog/stmp3xxx_wdt.c +++ b/drivers/watchdog/stmp3xxx_wdt.c @@ -174,7 +174,7 @@ static int stmp3xxx_wdt_release(struct inode *inode, struct file *file) if (!nowayout) { if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { wdt_ping(); - pr_debug("%s: Device closed unexpectdly\n", __func__); + pr_debug("%s: Device closed unexpectedly\n", __func__); ret = -EINVAL; } else { wdt_disable(); diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c index 026b4bbfa0aa..8f07dd4bd94a 100644 --- a/drivers/watchdog/via_wdt.c +++ b/drivers/watchdog/via_wdt.c @@ -124,8 +124,6 @@ static int wdt_stop(struct watchdog_device *wdd) static int wdt_set_timeout(struct watchdog_device *wdd, unsigned int new_timeout) { - if (new_timeout < 1 || new_timeout > WDT_TIMEOUT_MAX) - return -EINVAL; writel(new_timeout, wdt_mem + VIA_WDT_COUNT); timeout = new_timeout; return 0; @@ -150,6 +148,8 @@ static const struct watchdog_ops wdt_ops = { static struct watchdog_device wdt_dev = { .info = &wdt_info, .ops = &wdt_ops, + .min_timeout = 1, + .max_timeout = WDT_TIMEOUT_MAX, }; static int __devinit wdt_probe(struct pci_dev *pdev, @@ -233,7 +233,7 @@ static void __devexit wdt_remove(struct pci_dev *pdev) pci_disable_device(pdev); } -DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = { +static DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700) }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800) }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) }, diff --git a/drivers/watchdog/wafer5823wdt.c b/drivers/watchdog/wafer5823wdt.c index 42e940c23891..c3c3188c34d7 100644 --- a/drivers/watchdog/wafer5823wdt.c +++ b/drivers/watchdog/wafer5823wdt.c @@ -152,12 +152,12 @@ static long wafwdt_ioctl(struct file *file, unsigned int cmd, return -EFAULT; if (options & WDIOS_DISABLECARD) { - wafwdt_start(); + wafwdt_stop(); retval = 0; } if (options & WDIOS_ENABLECARD) { - wafwdt_stop(); + wafwdt_start(); retval = 0; } diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c index 909c78650d3e..5d7113c7e501 100644 --- a/drivers/watchdog/wm8350_wdt.c +++ b/drivers/watchdog/wm8350_wdt.c @@ -212,10 +212,10 @@ static long wm8350_wdt_ioctl(struct file *file, unsigned int cmd, /* Setting both simultaneously means at least one must fail */ if (options == WDIOS_DISABLECARD) - ret = wm8350_wdt_start(wm8350); + ret = wm8350_wdt_stop(wm8350); if (options == WDIOS_ENABLECARD) - ret = wm8350_wdt_stop(wm8350); + ret = wm8350_wdt_start(wm8350); break; } diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 1cd94daa71db..b4d4eac761db 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -948,9 +948,12 @@ static void gnttab_request_version(void) int rc; struct gnttab_set_version gsv; - gsv.version = 2; + if (xen_hvm_domain()) + gsv.version = 1; + else + gsv.version = 2; rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); - if (rc == 0) { + if (rc == 0 && gsv.version == 2) { grant_table_version = 2; gnttab_interface = &gnttab_v2_ops; } else if (grant_table_version == 2) { diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index b9a843226de8..633c701a287d 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -297,7 +297,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, struct btrfs_delayed_extent_op *extent_op = head->extent_op; struct rb_node *n = &head->node.rb_node; int sgn; - int ret; + int ret = 0; if (extent_op && extent_op->update_key) btrfs_disk_key_to_cpu(info_key, &extent_op->key); @@ -392,7 +392,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, struct btrfs_key *info_key, int *info_level, struct list_head *prefs) { - int ret; + int ret = 0; int slot; struct extent_buffer *leaf; struct btrfs_key key; diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index ad0b3ba735b7..b669a7d8e499 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -1662,7 +1662,7 @@ static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state, block = btrfsic_block_hashtable_lookup(bdev, dev_bytenr, &state->block_hashtable); if (NULL != block) { - u64 bytenr; + u64 bytenr = 0; struct list_head *elem_ref_to; struct list_head *tmp_ref_to; @@ -2777,9 +2777,10 @@ int btrfsic_submit_bh(int rw, struct buffer_head *bh) printk(KERN_INFO "submit_bh(rw=0x%x, blocknr=%lu (bytenr %llu)," " size=%lu, data=%p, bdev=%p)\n", - rw, bh->b_blocknr, - (unsigned long long)dev_bytenr, bh->b_size, - bh->b_data, bh->b_bdev); + rw, (unsigned long)bh->b_blocknr, + (unsigned long long)dev_bytenr, + (unsigned long)bh->b_size, bh->b_data, + bh->b_bdev); btrfsic_process_written_block(dev_state, dev_bytenr, bh->b_data, bh->b_size, NULL, NULL, bh, rw); @@ -2844,7 +2845,7 @@ void btrfsic_submit_bio(int rw, struct bio *bio) printk(KERN_INFO "submit_bio(rw=0x%x, bi_vcnt=%u," " bi_sector=%lu (bytenr %llu), bi_bdev=%p)\n", - rw, bio->bi_vcnt, bio->bi_sector, + rw, bio->bi_vcnt, (unsigned long)bio->bi_sector, (unsigned long long)dev_bytenr, bio->bi_bdev); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 7aa9cd36bf1b..811d9f918b1c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -962,6 +962,13 @@ static int btree_releasepage(struct page *page, gfp_t gfp_flags) tree = &BTRFS_I(page->mapping->host)->io_tree; map = &BTRFS_I(page->mapping->host)->extent_tree; + /* + * We need to mask out eg. __GFP_HIGHMEM and __GFP_DMA32 as we're doing + * slab allocation from alloc_extent_state down the callchain where + * it'd hit a BUG_ON as those flags are not allowed. + */ + gfp_flags &= ~GFP_SLAB_BUG_MASK; + ret = try_release_extent_state(map, tree, page, gfp_flags); if (!ret) return 0; diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 700879ed64cf..283af7a676a3 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -34,23 +34,24 @@ #include "locking.h" #include "free-space-cache.h" -/* control flags for do_chunk_alloc's force field +/* + * control flags for do_chunk_alloc's force field * CHUNK_ALLOC_NO_FORCE means to only allocate a chunk * if we really need one. * - * CHUNK_ALLOC_FORCE means it must try to allocate one - * * CHUNK_ALLOC_LIMITED means to only try and allocate one * if we have very few chunks already allocated. This is * used as part of the clustering code to help make sure * we have a good pool of storage to cluster in, without * filling the FS with empty chunks * + * CHUNK_ALLOC_FORCE means it must try to allocate one + * */ enum { CHUNK_ALLOC_NO_FORCE = 0, - CHUNK_ALLOC_FORCE = 1, - CHUNK_ALLOC_LIMITED = 2, + CHUNK_ALLOC_LIMITED = 1, + CHUNK_ALLOC_FORCE = 2, }; /* @@ -3414,7 +3415,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, again: spin_lock(&space_info->lock); - if (space_info->force_alloc) + if (force < space_info->force_alloc) force = space_info->force_alloc; if (space_info->full) { spin_unlock(&space_info->lock); @@ -5794,6 +5795,7 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans, u64 search_end, struct btrfs_key *ins, u64 data) { + bool final_tried = false; int ret; u64 search_start = 0; @@ -5813,22 +5815,25 @@ again: search_start, search_end, hint_byte, ins, data); - if (ret == -ENOSPC && num_bytes > min_alloc_size) { - num_bytes = num_bytes >> 1; - num_bytes = num_bytes & ~(root->sectorsize - 1); - num_bytes = max(num_bytes, min_alloc_size); - do_chunk_alloc(trans, root->fs_info->extent_root, - num_bytes, data, CHUNK_ALLOC_FORCE); - goto again; - } - if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) { - struct btrfs_space_info *sinfo; - - sinfo = __find_space_info(root->fs_info, data); - printk(KERN_ERR "btrfs allocation failed flags %llu, " - "wanted %llu\n", (unsigned long long)data, - (unsigned long long)num_bytes); - dump_space_info(sinfo, num_bytes, 1); + if (ret == -ENOSPC) { + if (!final_tried) { + num_bytes = num_bytes >> 1; + num_bytes = num_bytes & ~(root->sectorsize - 1); + num_bytes = max(num_bytes, min_alloc_size); + do_chunk_alloc(trans, root->fs_info->extent_root, + num_bytes, data, CHUNK_ALLOC_FORCE); + if (num_bytes == min_alloc_size) + final_tried = true; + goto again; + } else if (btrfs_test_opt(root, ENOSPC_DEBUG)) { + struct btrfs_space_info *sinfo; + + sinfo = __find_space_info(root->fs_info, data); + printk(KERN_ERR "btrfs allocation failed flags %llu, " + "wanted %llu\n", (unsigned long long)data, + (unsigned long long)num_bytes); + dump_space_info(sinfo, num_bytes, 1); + } } trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset); diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 9d09a4f81875..fcf77e1ded40 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3909,6 +3909,8 @@ int extent_range_uptodate(struct extent_io_tree *tree, while (start <= end) { index = start >> PAGE_CACHE_SHIFT; page = find_get_page(tree->mapping, index); + if (!page) + return 1; uptodate = PageUptodate(page); page_cache_release(page); if (!uptodate) { diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index d20ff87ca603..c2f20594c9f7 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2242,7 +2242,7 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, if (entry->bitmap) { ret = btrfs_alloc_from_bitmap(block_group, cluster, entry, bytes, - min_start); + cluster->window_start); if (ret == 0) { node = rb_next(&entry->offset_index); if (!node) @@ -2251,6 +2251,7 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, offset_index); continue; } + cluster->window_start += bytes; } else { ret = entry->offset; @@ -2475,7 +2476,7 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, } list_for_each_entry(entry, bitmaps, list) { - if (entry->bytes < min_bytes) + if (entry->bytes < bytes) continue; ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset, bytes, cont1_bytes, min_bytes); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 0da19a0ea00d..32214fe0f7e3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6401,18 +6401,23 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) unsigned long zero_start; loff_t size; int ret; + int reserved = 0; u64 page_start; u64 page_end; ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); - if (!ret) + if (!ret) { ret = btrfs_update_time(vma->vm_file); + reserved = 1; + } if (ret) { if (ret == -ENOMEM) ret = VM_FAULT_OOM; else /* -ENOSPC, -EIO, etc */ ret = VM_FAULT_SIGBUS; - goto out; + if (reserved) + goto out; + goto out_noreserve; } ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */ @@ -6495,6 +6500,7 @@ out_unlock: unlock_page(page); out: btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE); +out_noreserve: return ret; } diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index ab620014bcc3..03bb62a9ee24 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1065,7 +1065,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, i = range->start >> PAGE_CACHE_SHIFT; } if (!max_to_defrag) - max_to_defrag = last_index; + max_to_defrag = last_index + 1; /* * make writeback starts from i, so the defrag range can be diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index cb877e0886a7..966cc74f5d6c 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -1957,7 +1957,8 @@ static int wait_log_commit(struct btrfs_trans_handle *trans, finish_wait(&root->log_commit_wait[index], &wait); mutex_lock(&root->log_mutex); - } while (root->log_transid < transid + 2 && + } while (root->fs_info->last_trans_log_full_commit != + trans->transid && root->log_transid < transid + 2 && atomic_read(&root->log_commit[index])); return 0; } @@ -1966,7 +1967,8 @@ static int wait_for_writer(struct btrfs_trans_handle *trans, struct btrfs_root *root) { DEFINE_WAIT(wait); - while (atomic_read(&root->log_writers)) { + while (root->fs_info->last_trans_log_full_commit != + trans->transid && atomic_read(&root->log_writers)) { prepare_to_wait(&root->log_writer_wait, &wait, TASK_UNINTERRUPTIBLE); mutex_unlock(&root->log_mutex); diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index b60fc8bfb3e9..620daad201db 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -641,10 +641,10 @@ static int __cap_is_valid(struct ceph_cap *cap) unsigned long ttl; u32 gen; - spin_lock(&cap->session->s_cap_lock); + spin_lock(&cap->session->s_gen_ttl_lock); gen = cap->session->s_cap_gen; ttl = cap->session->s_cap_ttl; - spin_unlock(&cap->session->s_cap_lock); + spin_unlock(&cap->session->s_gen_ttl_lock); if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) { dout("__cap_is_valid %p cap %p issued %s " diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 618246bc2196..3e8094be4604 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -975,10 +975,10 @@ static int dentry_lease_is_valid(struct dentry *dentry) di = ceph_dentry(dentry); if (di->lease_session) { s = di->lease_session; - spin_lock(&s->s_cap_lock); + spin_lock(&s->s_gen_ttl_lock); gen = s->s_cap_gen; ttl = s->s_cap_ttl; - spin_unlock(&s->s_cap_lock); + spin_unlock(&s->s_gen_ttl_lock); if (di->lease_gen == gen && time_before(jiffies, dentry->d_time) && diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 23ab6a3f1825..866e8d7ca37d 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -262,6 +262,7 @@ static int parse_reply_info(struct ceph_msg *msg, /* trace */ ceph_decode_32_safe(&p, end, len, bad); if (len > 0) { + ceph_decode_need(&p, end, len, bad); err = parse_reply_info_trace(&p, p+len, info, features); if (err < 0) goto out_bad; @@ -270,6 +271,7 @@ static int parse_reply_info(struct ceph_msg *msg, /* extra */ ceph_decode_32_safe(&p, end, len, bad); if (len > 0) { + ceph_decode_need(&p, end, len, bad); err = parse_reply_info_extra(&p, p+len, info, features); if (err < 0) goto out_bad; @@ -398,9 +400,11 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS; s->s_con.peer_name.num = cpu_to_le64(mds); - spin_lock_init(&s->s_cap_lock); + spin_lock_init(&s->s_gen_ttl_lock); s->s_cap_gen = 0; s->s_cap_ttl = 0; + + spin_lock_init(&s->s_cap_lock); s->s_renew_requested = 0; s->s_renew_seq = 0; INIT_LIST_HEAD(&s->s_caps); @@ -2326,10 +2330,10 @@ static void handle_session(struct ceph_mds_session *session, case CEPH_SESSION_STALE: pr_info("mds%d caps went stale, renewing\n", session->s_mds); - spin_lock(&session->s_cap_lock); + spin_lock(&session->s_gen_ttl_lock); session->s_cap_gen++; session->s_cap_ttl = 0; - spin_unlock(&session->s_cap_lock); + spin_unlock(&session->s_gen_ttl_lock); send_renew_caps(mdsc, session); break; diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index a50ca0e39475..8c7c04ebb595 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -117,10 +117,13 @@ struct ceph_mds_session { void *s_authorizer_buf, *s_authorizer_reply_buf; size_t s_authorizer_buf_len, s_authorizer_reply_buf_len; - /* protected by s_cap_lock */ - spinlock_t s_cap_lock; + /* protected by s_gen_ttl_lock */ + spinlock_t s_gen_ttl_lock; u32 s_cap_gen; /* inc each time we get mds stale msg */ unsigned long s_cap_ttl; /* when session caps expire */ + + /* protected by s_cap_lock */ + spinlock_t s_cap_lock; struct list_head s_caps; /* all caps issued by this session */ int s_nr_caps, s_trim_caps; int s_num_cap_releases; diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 857214ae8c08..a76f697303d9 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -111,8 +111,10 @@ static size_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val, } static struct ceph_vxattr_cb ceph_file_vxattrs[] = { + { true, "ceph.file.layout", ceph_vxattrcb_layout}, + /* The following extended attribute name is deprecated */ { true, "ceph.layout", ceph_vxattrcb_layout}, - { NULL, NULL } + { true, NULL, NULL } }; static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 2a834255c75d..63ab24510649 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -417,17 +417,6 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page, (unsigned long long)(extent_base + extent_offset), rc); goto out; } - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, "Encrypting extent " - "with iv:\n"); - ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes); - ecryptfs_printk(KERN_DEBUG, "First 8 bytes before " - "encryption:\n"); - ecryptfs_dump_hex((char *) - (page_address(page) - + (extent_offset * crypt_stat->extent_size)), - 8); - } rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0, page, (extent_offset * crypt_stat->extent_size), @@ -440,14 +429,6 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page, goto out; } rc = 0; - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16llx]; " - "rc = [%d]\n", - (unsigned long long)(extent_base + extent_offset), rc); - ecryptfs_printk(KERN_DEBUG, "First 8 bytes after " - "encryption:\n"); - ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8); - } out: return rc; } @@ -543,17 +524,6 @@ static int ecryptfs_decrypt_extent(struct page *page, (unsigned long long)(extent_base + extent_offset), rc); goto out; } - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, "Decrypting extent " - "with iv:\n"); - ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes); - ecryptfs_printk(KERN_DEBUG, "First 8 bytes before " - "decryption:\n"); - ecryptfs_dump_hex((char *) - (page_address(enc_extent_page) - + (extent_offset * crypt_stat->extent_size)), - 8); - } rc = ecryptfs_decrypt_page_offset(crypt_stat, page, (extent_offset * crypt_stat->extent_size), @@ -567,16 +537,6 @@ static int ecryptfs_decrypt_extent(struct page *page, goto out; } rc = 0; - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, "Decrypt extent [0x%.16llx]; " - "rc = [%d]\n", - (unsigned long long)(extent_base + extent_offset), rc); - ecryptfs_printk(KERN_DEBUG, "First 8 bytes after " - "decryption:\n"); - ecryptfs_dump_hex((char *)(page_address(page) - + (extent_offset - * crypt_stat->extent_size)), 8); - } out: return rc; } @@ -1590,8 +1550,8 @@ int ecryptfs_read_and_validate_xattr_region(struct dentry *dentry, */ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) { - int rc = 0; - char *page_virt = NULL; + int rc; + char *page_virt; struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode; struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; @@ -1616,11 +1576,13 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) ecryptfs_dentry, ECRYPTFS_VALIDATE_HEADER_SIZE); if (rc) { + /* metadata is not in the file header, so try xattrs */ memset(page_virt, 0, PAGE_CACHE_SIZE); rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode); if (rc) { printk(KERN_DEBUG "Valid eCryptfs headers not found in " - "file header region or xattr region\n"); + "file header region or xattr region, inode %lu\n", + ecryptfs_inode->i_ino); rc = -EINVAL; goto out; } @@ -1629,7 +1591,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) ECRYPTFS_DONT_VALIDATE_HEADER_SIZE); if (rc) { printk(KERN_DEBUG "Valid eCryptfs headers not found in " - "file xattr region either\n"); + "file xattr region either, inode %lu\n", + ecryptfs_inode->i_ino); rc = -EINVAL; } if (crypt_stat->mount_crypt_stat->flags @@ -1640,7 +1603,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) "crypto metadata only in the extended attribute " "region, but eCryptfs was mounted without " "xattr support enabled. eCryptfs will not treat " - "this like an encrypted file.\n"); + "this like an encrypted file, inode %lu\n", + ecryptfs_inode->i_ino); rc = -EINVAL; } } diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index a9f29b12fbf2..a2362df58ae8 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -151,6 +151,11 @@ ecryptfs_get_key_payload_data(struct key *key) * dentry name */ #define ECRYPTFS_TAG_73_PACKET_TYPE 0x49 /* FEK-encrypted filename as * metadata */ +#define ECRYPTFS_MIN_PKT_LEN_SIZE 1 /* Min size to specify packet length */ +#define ECRYPTFS_MAX_PKT_LEN_SIZE 2 /* Pass at least this many bytes to + * ecryptfs_parse_packet_length() and + * ecryptfs_write_packet_length() + */ /* Constraint: ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES >= * ECRYPTFS_MAX_IV_BYTES */ #define ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES 16 diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 19a8ca4ab1dd..19892d7d2ed1 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -822,18 +822,6 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, size_t num_zeros = (PAGE_CACHE_SIZE - (ia->ia_size & ~PAGE_CACHE_MASK)); - - /* - * XXX(truncate) this should really happen at the begginning - * of ->setattr. But the code is too messy to that as part - * of a larger patch. ecryptfs is also totally missing out - * on the inode_change_ok check at the beginning of - * ->setattr while would include this. - */ - rc = inode_newsize_ok(inode, ia->ia_size); - if (rc) - goto out; - if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { truncate_setsize(inode, ia->ia_size); lower_ia->ia_size = ia->ia_size; @@ -883,6 +871,28 @@ out: return rc; } +static int ecryptfs_inode_newsize_ok(struct inode *inode, loff_t offset) +{ + struct ecryptfs_crypt_stat *crypt_stat; + loff_t lower_oldsize, lower_newsize; + + crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; + lower_oldsize = upper_size_to_lower_size(crypt_stat, + i_size_read(inode)); + lower_newsize = upper_size_to_lower_size(crypt_stat, offset); + if (lower_newsize > lower_oldsize) { + /* + * The eCryptfs inode and the new *lower* size are mixed here + * because we may not have the lower i_mutex held and/or it may + * not be appropriate to call inode_newsize_ok() with inodes + * from other filesystems. + */ + return inode_newsize_ok(inode, lower_newsize); + } + + return 0; +} + /** * ecryptfs_truncate * @dentry: The ecryptfs layer dentry @@ -899,6 +909,10 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) struct iattr lower_ia = { .ia_valid = 0 }; int rc; + rc = ecryptfs_inode_newsize_ok(dentry->d_inode, new_length); + if (rc) + return rc; + rc = truncate_upper(dentry, &ia, &lower_ia); if (!rc && lower_ia.ia_valid & ATTR_SIZE) { struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); @@ -978,6 +992,16 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) } } mutex_unlock(&crypt_stat->cs_mutex); + + rc = inode_change_ok(inode, ia); + if (rc) + goto out; + if (ia->ia_valid & ATTR_SIZE) { + rc = ecryptfs_inode_newsize_ok(inode, ia->ia_size); + if (rc) + goto out; + } + if (S_ISREG(inode->i_mode)) { rc = filemap_write_and_wait(inode->i_mapping); if (rc) diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index ac1ad48c2376..8e3b943e330f 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -109,7 +109,7 @@ int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, (*size) += ((unsigned char)(data[1]) + 192); (*length_size) = 2; } else if (data[0] == 255) { - /* Five-byte length; we're not supposed to see this */ + /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */ ecryptfs_printk(KERN_ERR, "Five-byte packet length not " "supported\n"); rc = -EINVAL; @@ -126,7 +126,7 @@ out: /** * ecryptfs_write_packet_length * @dest: The byte array target into which to write the length. Must - * have at least 5 bytes allocated. + * have at least ECRYPTFS_MAX_PKT_LEN_SIZE bytes allocated. * @size: The length to write. * @packet_size_length: The number of bytes used to encode the packet * length is written to this address. @@ -146,6 +146,7 @@ int ecryptfs_write_packet_length(char *dest, size_t size, dest[1] = ((size - 192) % 256); (*packet_size_length) = 2; } else { + /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */ rc = -EINVAL; ecryptfs_printk(KERN_WARNING, "Unsupported packet size: [%zd]\n", size); diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index 940a82e63dc3..349209dc6a91 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c @@ -218,6 +218,29 @@ out_unlock: return rc; } +/* + * miscdevfs packet format: + * Octet 0: Type + * Octets 1-4: network byte order msg_ctx->counter + * Octets 5-N0: Size of struct ecryptfs_message to follow + * Octets N0-N1: struct ecryptfs_message (including data) + * + * Octets 5-N1 not written if the packet type does not include a message + */ +#define PKT_TYPE_SIZE 1 +#define PKT_CTR_SIZE 4 +#define MIN_NON_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE) +#define MIN_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \ + + ECRYPTFS_MIN_PKT_LEN_SIZE) +/* 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES comes from tag 65 packet format */ +#define MAX_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \ + + ECRYPTFS_MAX_PKT_LEN_SIZE \ + + sizeof(struct ecryptfs_message) \ + + 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) +#define PKT_TYPE_OFFSET 0 +#define PKT_CTR_OFFSET PKT_TYPE_SIZE +#define PKT_LEN_OFFSET (PKT_TYPE_SIZE + PKT_CTR_SIZE) + /** * ecryptfs_miscdev_read - format and send message from queue * @file: fs/ecryptfs/euid miscdevfs handle (ignored) @@ -237,7 +260,7 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, struct ecryptfs_daemon *daemon; struct ecryptfs_msg_ctx *msg_ctx; size_t packet_length_size; - char packet_length[3]; + char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE]; size_t i; size_t total_length; uid_t euid = current_euid(); @@ -305,15 +328,8 @@ check_list: packet_length_size = 0; msg_ctx->msg_size = 0; } - /* miscdevfs packet format: - * Octet 0: Type - * Octets 1-4: network byte order msg_ctx->counter - * Octets 5-N0: Size of struct ecryptfs_message to follow - * Octets N0-N1: struct ecryptfs_message (including data) - * - * Octets 5-N1 not written if the packet type does not - * include a message */ - total_length = (1 + 4 + packet_length_size + msg_ctx->msg_size); + total_length = (PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_length_size + + msg_ctx->msg_size); if (count < total_length) { rc = 0; printk(KERN_WARNING "%s: Only given user buffer of " @@ -324,9 +340,10 @@ check_list: rc = -EFAULT; if (put_user(msg_ctx->type, buf)) goto out_unlock_msg_ctx; - if (put_user(cpu_to_be32(msg_ctx->counter), (__be32 __user *)(buf + 1))) + if (put_user(cpu_to_be32(msg_ctx->counter), + (__be32 __user *)(&buf[PKT_CTR_OFFSET]))) goto out_unlock_msg_ctx; - i = 5; + i = PKT_TYPE_SIZE + PKT_CTR_SIZE; if (msg_ctx->msg) { if (copy_to_user(&buf[i], packet_length, packet_length_size)) goto out_unlock_msg_ctx; @@ -391,12 +408,6 @@ out: * @count: Amount of data in @buf * @ppos: Pointer to offset in file (ignored) * - * miscdevfs packet format: - * Octet 0: Type - * Octets 1-4: network byte order msg_ctx->counter (0's for non-response) - * Octets 5-N0: Size of struct ecryptfs_message to follow - * Octets N0-N1: struct ecryptfs_message (including data) - * * Returns the number of bytes read from @buf */ static ssize_t @@ -405,60 +416,78 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf, { __be32 counter_nbo; u32 seq; - size_t packet_size, packet_size_length, i; - ssize_t sz = 0; + size_t packet_size, packet_size_length; char *data; uid_t euid = current_euid(); - int rc; + unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE]; + ssize_t rc; - if (count == 0) - goto out; + if (count == 0) { + return 0; + } else if (count == MIN_NON_MSG_PKT_SIZE) { + /* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */ + goto memdup; + } else if (count < MIN_MSG_PKT_SIZE || count > MAX_MSG_PKT_SIZE) { + printk(KERN_WARNING "%s: Acceptable packet size range is " + "[%d-%lu], but amount of data written is [%zu].", + __func__, MIN_MSG_PKT_SIZE, MAX_MSG_PKT_SIZE, count); + return -EINVAL; + } + + if (copy_from_user(packet_size_peek, &buf[PKT_LEN_OFFSET], + sizeof(packet_size_peek))) { + printk(KERN_WARNING "%s: Error while inspecting packet size\n", + __func__); + return -EFAULT; + } + rc = ecryptfs_parse_packet_length(packet_size_peek, &packet_size, + &packet_size_length); + if (rc) { + printk(KERN_WARNING "%s: Error parsing packet length; " + "rc = [%zd]\n", __func__, rc); + return rc; + } + + if ((PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_size_length + packet_size) + != count) { + printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__, + packet_size); + return -EINVAL; + } + +memdup: data = memdup_user(buf, count); if (IS_ERR(data)) { printk(KERN_ERR "%s: memdup_user returned error [%ld]\n", __func__, PTR_ERR(data)); - goto out; + return PTR_ERR(data); } - sz = count; - i = 0; - switch (data[i++]) { + switch (data[PKT_TYPE_OFFSET]) { case ECRYPTFS_MSG_RESPONSE: - if (count < (1 + 4 + 1 + sizeof(struct ecryptfs_message))) { + if (count < (MIN_MSG_PKT_SIZE + + sizeof(struct ecryptfs_message))) { printk(KERN_WARNING "%s: Minimum acceptable packet " "size is [%zd], but amount of data written is " "only [%zd]. Discarding response packet.\n", __func__, - (1 + 4 + 1 + sizeof(struct ecryptfs_message)), - count); + (MIN_MSG_PKT_SIZE + + sizeof(struct ecryptfs_message)), count); + rc = -EINVAL; goto out_free; } - memcpy(&counter_nbo, &data[i], 4); + memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE); seq = be32_to_cpu(counter_nbo); - i += 4; - rc = ecryptfs_parse_packet_length(&data[i], &packet_size, - &packet_size_length); + rc = ecryptfs_miscdev_response( + &data[PKT_LEN_OFFSET + packet_size_length], + packet_size, euid, current_user_ns(), + task_pid(current), seq); if (rc) { - printk(KERN_WARNING "%s: Error parsing packet length; " - "rc = [%d]\n", __func__, rc); - goto out_free; - } - i += packet_size_length; - if ((1 + 4 + packet_size_length + packet_size) != count) { - printk(KERN_WARNING "%s: (1 + packet_size_length([%zd])" - " + packet_size([%zd]))([%zd]) != " - "count([%zd]). Invalid packet format.\n", - __func__, packet_size_length, packet_size, - (1 + packet_size_length + packet_size), count); - goto out_free; - } - rc = ecryptfs_miscdev_response(&data[i], packet_size, - euid, current_user_ns(), - task_pid(current), seq); - if (rc) printk(KERN_WARNING "%s: Failed to deliver miscdev " - "response to requesting operation; rc = [%d]\n", + "response to requesting operation; rc = [%zd]\n", __func__, rc); + goto out_free; + } break; case ECRYPTFS_MSG_HELO: case ECRYPTFS_MSG_QUIT: @@ -467,12 +496,13 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf, ecryptfs_printk(KERN_WARNING, "Dropping miscdev " "message of unrecognized type [%d]\n", data[0]); - break; + rc = -EINVAL; + goto out_free; } + rc = count; out_free: kfree(data); -out: - return sz; + return rc; } diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 6a44148c5fb9..10ec695ccd68 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -57,6 +57,10 @@ struct page *ecryptfs_get_locked_page(struct inode *inode, loff_t index) * @page: Page that is locked before this call is made * * Returns zero on success; non-zero otherwise + * + * This is where we encrypt the data and pass the encrypted data to + * the lower filesystem. In OpenPGP-compatible mode, we operate on + * entire underlying packets. */ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) { @@ -481,10 +485,6 @@ int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode) * @copied: The amount of data copied * @page: The eCryptfs page * @fsdata: The fsdata (unused) - * - * This is where we encrypt the data and pass the encrypted data to - * the lower filesystem. In OpenPGP-compatible mode, we operate on - * entire underlying packets. */ static int ecryptfs_write_end(struct file *file, struct address_space *mapping, diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index 3745f7c2b9c2..5c0106f75775 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c @@ -130,13 +130,18 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); - size_t total_remaining_bytes = ((offset + size) - pos); + loff_t total_remaining_bytes = ((offset + size) - pos); + + if (fatal_signal_pending(current)) { + rc = -EINTR; + break; + } if (num_bytes > total_remaining_bytes) num_bytes = total_remaining_bytes; if (pos < offset) { /* remaining zeros to write, up to destination offset */ - size_t total_remaining_zeros = (offset - pos); + loff_t total_remaining_zeros = (offset - pos); if (num_bytes > total_remaining_zeros) num_bytes = total_remaining_zeros; @@ -193,15 +198,19 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, } pos += num_bytes; } - if ((offset + size) > ecryptfs_file_size) { - i_size_write(ecryptfs_inode, (offset + size)); + if (pos > ecryptfs_file_size) { + i_size_write(ecryptfs_inode, pos); if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) { - rc = ecryptfs_write_inode_size_to_metadata( + int rc2; + + rc2 = ecryptfs_write_inode_size_to_metadata( ecryptfs_inode); - if (rc) { + if (rc2) { printk(KERN_ERR "Problem with " "ecryptfs_write_inode_size_to_metadata; " - "rc = [%d]\n", rc); + "rc = [%d]\n", rc2); + if (!rc) + rc = rc2; goto out; } } @@ -273,76 +282,3 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, flush_dcache_page(page_for_ecryptfs); return rc; } - -#if 0 -/** - * ecryptfs_read - * @data: The virtual address into which to write the data read (and - * possibly decrypted) from the lower file - * @offset: The offset in the decrypted view of the file from which to - * read into @data - * @size: The number of bytes to read into @data - * @ecryptfs_file: The eCryptfs file from which to read - * - * Read an arbitrary amount of data from an arbitrary location in the - * eCryptfs page cache. This is done on an extent-by-extent basis; - * individual extents are decrypted and read from the lower page - * cache (via VFS reads). This function takes care of all the - * address translation to locations in the lower filesystem. - * - * Returns zero on success; non-zero otherwise - */ -int ecryptfs_read(char *data, loff_t offset, size_t size, - struct file *ecryptfs_file) -{ - struct inode *ecryptfs_inode = ecryptfs_file->f_dentry->d_inode; - struct page *ecryptfs_page; - char *ecryptfs_page_virt; - loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode); - loff_t data_offset = 0; - loff_t pos; - int rc = 0; - - if ((offset + size) > ecryptfs_file_size) { - rc = -EINVAL; - printk(KERN_ERR "%s: Attempt to read data past the end of the " - "file; offset = [%lld]; size = [%td]; " - "ecryptfs_file_size = [%lld]\n", - __func__, offset, size, ecryptfs_file_size); - goto out; - } - pos = offset; - while (pos < (offset + size)) { - pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT); - size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK); - size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page); - size_t total_remaining_bytes = ((offset + size) - pos); - - if (num_bytes > total_remaining_bytes) - num_bytes = total_remaining_bytes; - ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_inode, - ecryptfs_page_idx); - if (IS_ERR(ecryptfs_page)) { - rc = PTR_ERR(ecryptfs_page); - printk(KERN_ERR "%s: Error getting page at " - "index [%ld] from eCryptfs inode " - "mapping; rc = [%d]\n", __func__, - ecryptfs_page_idx, rc); - goto out; - } - ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); - memcpy((data + data_offset), - ((char *)ecryptfs_page_virt + start_offset_in_page), - num_bytes); - kunmap_atomic(ecryptfs_page_virt, KM_USER0); - flush_dcache_page(ecryptfs_page); - SetPageUptodate(ecryptfs_page); - unlock_page(ecryptfs_page); - page_cache_release(ecryptfs_page); - pos += num_bytes; - data_offset += num_bytes; - } -out: - return rc; -} -#endif /* 0 */ diff --git a/fs/exec.c b/fs/exec.c index aeb135c7ff5c..92ce83a11e90 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1071,6 +1071,21 @@ void set_task_comm(struct task_struct *tsk, char *buf) perf_event_comm(tsk); } +static void filename_to_taskname(char *tcomm, const char *fn, unsigned int len) +{ + int i, ch; + + /* Copies the binary name from after last slash */ + for (i = 0; (ch = *(fn++)) != '\0';) { + if (ch == '/') + i = 0; /* overwrite what we wrote */ + else + if (i < len - 1) + tcomm[i++] = ch; + } + tcomm[i] = '\0'; +} + int flush_old_exec(struct linux_binprm * bprm) { int retval; @@ -1085,6 +1100,7 @@ int flush_old_exec(struct linux_binprm * bprm) set_mm_exe_file(bprm->mm, bprm->file); + filename_to_taskname(bprm->tcomm, bprm->filename, sizeof(bprm->tcomm)); /* * Release all of the old mmap stuff */ @@ -1116,10 +1132,6 @@ EXPORT_SYMBOL(would_dump); void setup_new_exec(struct linux_binprm * bprm) { - int i, ch; - const char *name; - char tcomm[sizeof(current->comm)]; - arch_pick_mmap_layout(current->mm); /* This is the point of no return */ @@ -1130,18 +1142,7 @@ void setup_new_exec(struct linux_binprm * bprm) else set_dumpable(current->mm, suid_dumpable); - name = bprm->filename; - - /* Copies the binary name from after last slash */ - for (i=0; (ch = *(name++)) != '\0';) { - if (ch == '/') - i = 0; /* overwrite what we wrote */ - else - if (i < (sizeof(tcomm) - 1)) - tcomm[i++] = ch; - } - tcomm[i] = '\0'; - set_task_comm(current, tcomm); + set_task_comm(current, bprm->tcomm); /* Set the new mm task size. We have to do that late because it may * depend on TIF_32BIT which is only updated in flush_thread() on diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index 1089f760c847..2de655f5d625 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c @@ -77,10 +77,11 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) flags = flags & EXT2_FL_USER_MODIFIABLE; flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE; ei->i_flags = flags; - mutex_unlock(&inode->i_mutex); ext2_set_inode_flags(inode); inode->i_ctime = CURRENT_TIME_SEC; + mutex_unlock(&inode->i_mutex); + mark_inode_dirty(inode); setflags_out: mnt_drop_write_file(filp); @@ -88,20 +89,29 @@ setflags_out: } case EXT2_IOC_GETVERSION: return put_user(inode->i_generation, (int __user *) arg); - case EXT2_IOC_SETVERSION: + case EXT2_IOC_SETVERSION: { + __u32 generation; + if (!inode_owner_or_capable(inode)) return -EPERM; ret = mnt_want_write_file(filp); if (ret) return ret; - if (get_user(inode->i_generation, (int __user *) arg)) { + if (get_user(generation, (int __user *) arg)) { ret = -EFAULT; - } else { - inode->i_ctime = CURRENT_TIME_SEC; - mark_inode_dirty(inode); + goto setversion_out; } + + mutex_lock(&inode->i_mutex); + inode->i_ctime = CURRENT_TIME_SEC; + inode->i_generation = generation; + mutex_unlock(&inode->i_mutex); + + mark_inode_dirty(inode); +setversion_out: mnt_drop_write_file(filp); return ret; + } case EXT2_IOC_GETRSVSZ: if (test_opt(inode->i_sb, RESERVATION) && S_ISREG(inode->i_mode) diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 5d1a00a5041b..05f0754f2b46 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c @@ -453,8 +453,6 @@ out: * * Return <0 on error, 0 on success, 1 if there was nothing to clean up. * - * Called with the journal lock held. - * * This is the only part of the journaling code which really needs to be * aware of transaction aborts. Checkpointing involves writing to the * main filesystem area rather than to the journal, so it can proceed @@ -472,13 +470,14 @@ int cleanup_journal_tail(journal_t *journal) if (is_journal_aborted(journal)) return 1; - /* OK, work out the oldest transaction remaining in the log, and + /* + * OK, work out the oldest transaction remaining in the log, and * the log block it starts at. * * If the log is now empty, we need to work out which is the * next transaction ID we will write, and where it will - * start. */ - + * start. + */ spin_lock(&journal->j_state_lock); spin_lock(&journal->j_list_lock); transaction = journal->j_checkpoint_transactions; @@ -504,7 +503,25 @@ int cleanup_journal_tail(journal_t *journal) spin_unlock(&journal->j_state_lock); return 1; } + spin_unlock(&journal->j_state_lock); + + /* + * We need to make sure that any blocks that were recently written out + * --- perhaps by log_do_checkpoint() --- are flushed out before we + * drop the transactions from the journal. It's unlikely this will be + * necessary, especially with an appropriately sized journal, but we + * need this to guarantee correctness. Fortunately + * cleanup_journal_tail() doesn't get called all that often. + */ + if (journal->j_flags & JFS_BARRIER) + blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); + spin_lock(&journal->j_state_lock); + if (!tid_gt(first_tid, journal->j_tail_sequence)) { + spin_unlock(&journal->j_state_lock); + /* Someone else cleaned up journal so return 0 */ + return 0; + } /* OK, update the superblock to recover the freed space. * Physical blocks come first: have we wrapped beyond the end of * the log? */ diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c index 5b43e96788e6..008bf062fd26 100644 --- a/fs/jbd/recovery.c +++ b/fs/jbd/recovery.c @@ -20,6 +20,7 @@ #include <linux/fs.h> #include <linux/jbd.h> #include <linux/errno.h> +#include <linux/blkdev.h> #endif /* @@ -263,6 +264,9 @@ int journal_recover(journal_t *journal) err2 = sync_blockdev(journal->j_fs_dev); if (!err) err = err2; + /* Flush disk caches to get replayed data on the permanent storage */ + if (journal->j_flags & JFS_BARRIER) + blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); return err; } diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index a01cdad6aad1..eafb8d37a6fb 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -335,7 +335,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl void *ebuf; uint32_t ofs; size_t retlen; - int ret = -EIO; + int ret; unsigned long *wordebuf; ret = mtd_point(c->mtd, jeb->offset, c->sector_size, &retlen, diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c index e97404d611e0..9c501449450d 100644 --- a/fs/logfs/dev_mtd.c +++ b/fs/logfs/dev_mtd.c @@ -152,9 +152,6 @@ static struct page *logfs_mtd_find_first_sb(struct super_block *sb, u64 *ofs) filler_t *filler = logfs_mtd_readpage; struct mtd_info *mtd = super->s_mtd; - if (!mtd_can_have_bb(mtd)) - return NULL; - *ofs = 0; while (mtd_block_isbad(mtd, *ofs)) { *ofs += mtd->erasesize; @@ -172,9 +169,6 @@ static struct page *logfs_mtd_find_last_sb(struct super_block *sb, u64 *ofs) filler_t *filler = logfs_mtd_readpage; struct mtd_info *mtd = super->s_mtd; - if (!mtd_can_have_bb(mtd)) - return NULL; - *ofs = mtd->size - mtd->erasesize; while (mtd_block_isbad(mtd, *ofs)) { *ofs -= mtd->erasesize; diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index 501043e8966c..3de7a32cadbe 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c @@ -71,7 +71,7 @@ static int write_dir(struct inode *dir, struct logfs_disk_dentry *dd, static int write_inode(struct inode *inode) { - return __logfs_write_inode(inode, WF_LOCK); + return __logfs_write_inode(inode, NULL, WF_LOCK); } static s64 dir_seek_data(struct inode *inode, s64 pos) diff --git a/fs/logfs/file.c b/fs/logfs/file.c index b548c87a86f1..3886cded283c 100644 --- a/fs/logfs/file.c +++ b/fs/logfs/file.c @@ -230,7 +230,9 @@ int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) return ret; mutex_lock(&inode->i_mutex); + logfs_get_wblocks(sb, NULL, WF_LOCK); logfs_write_anchor(sb); + logfs_put_wblocks(sb, NULL, WF_LOCK); mutex_unlock(&inode->i_mutex); return 0; diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c index caa4419285dc..d4efb061bdc5 100644 --- a/fs/logfs/gc.c +++ b/fs/logfs/gc.c @@ -367,7 +367,7 @@ static struct gc_candidate *get_candidate(struct super_block *sb) int i, max_dist; struct gc_candidate *cand = NULL, *this; - max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS); + max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS - 1); for (i = max_dist; i >= 0; i--) { this = first_in_list(&super->s_low_list[i]); diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c index 388df1aa35e5..a422f42238b2 100644 --- a/fs/logfs/inode.c +++ b/fs/logfs/inode.c @@ -286,7 +286,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc) if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN) return 0; - ret = __logfs_write_inode(inode, flags); + ret = __logfs_write_inode(inode, NULL, flags); LOGFS_BUG_ON(ret, inode->i_sb); return ret; } @@ -363,7 +363,9 @@ static void logfs_init_once(void *_li) static int logfs_sync_fs(struct super_block *sb, int wait) { + logfs_get_wblocks(sb, NULL, WF_LOCK); logfs_write_anchor(sb); + logfs_put_wblocks(sb, NULL, WF_LOCK); return 0; } diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c index 9da29706f91c..1e1c369df22b 100644 --- a/fs/logfs/journal.c +++ b/fs/logfs/journal.c @@ -612,7 +612,6 @@ static size_t __logfs_write_je(struct super_block *sb, void *buf, u16 type, if (len == 0) return logfs_write_header(super, header, 0, type); - BUG_ON(len > sb->s_blocksize); compr_len = logfs_compress(buf, data, len, sb->s_blocksize); if (compr_len < 0 || type == JE_ANCHOR) { memcpy(data, buf, len); diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index 926373866a55..5f0937609465 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h @@ -528,7 +528,7 @@ void logfs_destroy_inode_cache(void); void logfs_set_blocks(struct inode *inode, u64 no); /* these logically belong into inode.c but actually reside in readwrite.c */ int logfs_read_inode(struct inode *inode); -int __logfs_write_inode(struct inode *inode, long flags); +int __logfs_write_inode(struct inode *inode, struct page *, long flags); void logfs_evict_inode(struct inode *inode); /* journal.c */ @@ -577,6 +577,8 @@ void initialize_block_counters(struct page *page, struct logfs_block *block, __be64 *array, int page_is_empty); int logfs_exist_block(struct inode *inode, u64 bix); int get_page_reserve(struct inode *inode, struct page *page); +void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock); +void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock); extern struct logfs_block_ops indirect_block_ops; /* segment.c */ @@ -594,6 +596,7 @@ int logfs_init_mapping(struct super_block *sb); void logfs_sync_area(struct logfs_area *area); void logfs_sync_segments(struct super_block *sb); void freeseg(struct super_block *sb, u32 segno); +void free_areas(struct super_block *sb); /* area handling */ int logfs_init_areas(struct super_block *sb); diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 2ac4217b7901..4153e65b0148 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c @@ -244,8 +244,7 @@ static void preunlock_page(struct super_block *sb, struct page *page, int lock) * is waiting for s_write_mutex. We annotate this fact by setting PG_pre_locked * in addition to PG_locked. */ -static void logfs_get_wblocks(struct super_block *sb, struct page *page, - int lock) +void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock) { struct logfs_super *super = logfs_super(sb); @@ -260,8 +259,7 @@ static void logfs_get_wblocks(struct super_block *sb, struct page *page, } } -static void logfs_put_wblocks(struct super_block *sb, struct page *page, - int lock) +void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock) { struct logfs_super *super = logfs_super(sb); @@ -424,7 +422,7 @@ static void inode_write_block(struct logfs_block *block) if (inode->i_ino == LOGFS_INO_MASTER) logfs_write_anchor(inode->i_sb); else { - ret = __logfs_write_inode(inode, 0); + ret = __logfs_write_inode(inode, NULL, 0); /* see indirect_write_block comment */ BUG_ON(ret); } @@ -560,8 +558,13 @@ static void inode_free_block(struct super_block *sb, struct logfs_block *block) static void indirect_free_block(struct super_block *sb, struct logfs_block *block) { - ClearPagePrivate(block->page); - block->page->private = 0; + struct page *page = block->page; + + if (PagePrivate(page)) { + ClearPagePrivate(page); + page_cache_release(page); + set_page_private(page, 0); + } __free_block(sb, block); } @@ -650,8 +653,11 @@ static void alloc_data_block(struct inode *inode, struct page *page) logfs_unpack_index(page->index, &bix, &level); block = __alloc_block(inode->i_sb, inode->i_ino, bix, level); block->page = page; + SetPagePrivate(page); - page->private = (unsigned long)block; + page_cache_get(page); + set_page_private(page, (unsigned long) block); + block->ops = &indirect_block_ops; } @@ -1570,11 +1576,15 @@ int logfs_write_buf(struct inode *inode, struct page *page, long flags) static int __logfs_delete(struct inode *inode, struct page *page) { long flags = WF_DELETE; + int err; inode->i_ctime = inode->i_mtime = CURRENT_TIME; if (page->index < I0_BLOCKS) return logfs_write_direct(inode, page, flags); + err = grow_inode(inode, page->index, 0); + if (err) + return err; return logfs_write_rec(inode, page, page->index, 0, flags); } @@ -1623,7 +1633,7 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs, if (inode->i_ino == LOGFS_INO_MASTER) logfs_write_anchor(inode->i_sb); else { - err = __logfs_write_inode(inode, flags); + err = __logfs_write_inode(inode, page, flags); } } } @@ -1873,7 +1883,7 @@ int logfs_truncate(struct inode *inode, u64 target) logfs_get_wblocks(sb, NULL, 1); err = __logfs_truncate(inode, size); if (!err) - err = __logfs_write_inode(inode, 0); + err = __logfs_write_inode(inode, NULL, 0); logfs_put_wblocks(sb, NULL, 1); } @@ -1901,8 +1911,11 @@ static void move_page_to_inode(struct inode *inode, struct page *page) li->li_block = block; block->page = NULL; - page->private = 0; - ClearPagePrivate(page); + if (PagePrivate(page)) { + ClearPagePrivate(page); + page_cache_release(page); + set_page_private(page, 0); + } } static void move_inode_to_page(struct page *page, struct inode *inode) @@ -1918,8 +1931,12 @@ static void move_inode_to_page(struct page *page, struct inode *inode) BUG_ON(PagePrivate(page)); block->ops = &indirect_block_ops; block->page = page; - page->private = (unsigned long)block; - SetPagePrivate(page); + + if (!PagePrivate(page)) { + SetPagePrivate(page); + page_cache_get(page); + set_page_private(page, (unsigned long) block); + } block->inode = NULL; li->li_block = NULL; @@ -2106,14 +2123,14 @@ void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec) ec_level); } -int __logfs_write_inode(struct inode *inode, long flags) +int __logfs_write_inode(struct inode *inode, struct page *page, long flags) { struct super_block *sb = inode->i_sb; int ret; - logfs_get_wblocks(sb, NULL, flags & WF_LOCK); + logfs_get_wblocks(sb, page, flags & WF_LOCK); ret = do_write_inode(inode); - logfs_put_wblocks(sb, NULL, flags & WF_LOCK); + logfs_put_wblocks(sb, page, flags & WF_LOCK); return ret; } diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c index 9d5187353255..ab798ed1cc88 100644 --- a/fs/logfs/segment.c +++ b/fs/logfs/segment.c @@ -86,7 +86,11 @@ int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, BUG_ON(!page); /* FIXME: reserve a pool */ SetPageUptodate(page); memcpy(page_address(page) + offset, buf, copylen); - SetPagePrivate(page); + + if (!PagePrivate(page)) { + SetPagePrivate(page); + page_cache_get(page); + } page_cache_release(page); buf += copylen; @@ -110,7 +114,10 @@ static void pad_partial_page(struct logfs_area *area) page = get_mapping_page(sb, index, 0); BUG_ON(!page); /* FIXME: reserve a pool */ memset(page_address(page) + offset, 0xff, len); - SetPagePrivate(page); + if (!PagePrivate(page)) { + SetPagePrivate(page); + page_cache_get(page); + } page_cache_release(page); } } @@ -130,7 +137,10 @@ static void pad_full_pages(struct logfs_area *area) BUG_ON(!page); /* FIXME: reserve a pool */ SetPageUptodate(page); memset(page_address(page), 0xff, PAGE_CACHE_SIZE); - SetPagePrivate(page); + if (!PagePrivate(page)) { + SetPagePrivate(page); + page_cache_get(page); + } page_cache_release(page); index++; no_indizes--; @@ -485,8 +495,12 @@ static void move_btree_to_page(struct inode *inode, struct page *page, mempool_free(item, super->s_alias_pool); } block->page = page; - SetPagePrivate(page); - page->private = (unsigned long)block; + + if (!PagePrivate(page)) { + SetPagePrivate(page); + page_cache_get(page); + set_page_private(page, (unsigned long) block); + } block->ops = &indirect_block_ops; initialize_block_counters(page, block, data, 0); } @@ -536,8 +550,12 @@ void move_page_to_btree(struct page *page) list_add(&item->list, &block->item_list); } block->page = NULL; - ClearPagePrivate(page); - page->private = 0; + + if (PagePrivate(page)) { + ClearPagePrivate(page); + page_cache_release(page); + set_page_private(page, 0); + } block->ops = &btree_block_ops; err = alias_tree_insert(block->sb, block->ino, block->bix, block->level, block); @@ -702,7 +720,10 @@ void freeseg(struct super_block *sb, u32 segno) page = find_get_page(mapping, ofs >> PAGE_SHIFT); if (!page) continue; - ClearPagePrivate(page); + if (PagePrivate(page)) { + ClearPagePrivate(page); + page_cache_release(page); + } page_cache_release(page); } } @@ -841,6 +862,16 @@ static void free_area(struct logfs_area *area) kfree(area); } +void free_areas(struct super_block *sb) +{ + struct logfs_super *super = logfs_super(sb); + int i; + + for_each_area(i) + free_area(super->s_area[i]); + free_area(super->s_journal_area); +} + static struct logfs_area *alloc_area(struct super_block *sb) { struct logfs_area *area; @@ -923,10 +954,6 @@ err: void logfs_cleanup_areas(struct super_block *sb) { struct logfs_super *super = logfs_super(sb); - int i; btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias); - for_each_area(i) - free_area(super->s_area[i]); - free_area(super->s_journal_area); } diff --git a/fs/logfs/super.c b/fs/logfs/super.c index e795c234ea33..c9ee7f5d1caf 100644 --- a/fs/logfs/super.c +++ b/fs/logfs/super.c @@ -486,14 +486,15 @@ static void logfs_kill_sb(struct super_block *sb) /* Alias entries slow down mount, so evict as many as possible */ sync_filesystem(sb); logfs_write_anchor(sb); + free_areas(sb); /* * From this point on alias entries are simply dropped - and any * writes to the object store are considered bugs. */ - super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN; log_super("LogFS: Now in shutdown\n"); generic_shutdown_super(sb); + super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN; BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes); diff --git a/fs/proc/base.c b/fs/proc/base.c index 9cde9edf9c4d..d4548dd49b02 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -198,26 +198,6 @@ static int proc_root_link(struct dentry *dentry, struct path *path) return result; } -static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) -{ - struct mm_struct *mm; - int err; - - err = mutex_lock_killable(&task->signal->cred_guard_mutex); - if (err) - return ERR_PTR(err); - - mm = get_task_mm(task); - if (mm && mm != current->mm && - !ptrace_may_access(task, mode)) { - mmput(mm); - mm = ERR_PTR(-EACCES); - } - mutex_unlock(&task->signal->cred_guard_mutex); - - return mm; -} - struct mm_struct *mm_for_maps(struct task_struct *task) { return mm_access(task, PTRACE_MODE_READ); @@ -711,6 +691,13 @@ static int mem_open(struct inode* inode, struct file* file) if (IS_ERR(mm)) return PTR_ERR(mm); + if (mm) { + /* ensure this mm_struct can't be freed */ + atomic_inc(&mm->mm_count); + /* but do not pin its memory */ + mmput(mm); + } + /* OK to pass negative loff_t, we can catch out-of-range */ file->f_mode |= FMODE_UNSIGNED_OFFSET; file->private_data = mm; @@ -718,57 +705,13 @@ static int mem_open(struct inode* inode, struct file* file) return 0; } -static ssize_t mem_read(struct file * file, char __user * buf, - size_t count, loff_t *ppos) +static ssize_t mem_rw(struct file *file, char __user *buf, + size_t count, loff_t *ppos, int write) { - int ret; - char *page; - unsigned long src = *ppos; struct mm_struct *mm = file->private_data; - - if (!mm) - return 0; - - page = (char *)__get_free_page(GFP_TEMPORARY); - if (!page) - return -ENOMEM; - - ret = 0; - - while (count > 0) { - int this_len, retval; - - this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; - retval = access_remote_vm(mm, src, page, this_len, 0); - if (!retval) { - if (!ret) - ret = -EIO; - break; - } - - if (copy_to_user(buf, page, retval)) { - ret = -EFAULT; - break; - } - - ret += retval; - src += retval; - buf += retval; - count -= retval; - } - *ppos = src; - - free_page((unsigned long) page); - return ret; -} - -static ssize_t mem_write(struct file * file, const char __user *buf, - size_t count, loff_t *ppos) -{ - int copied; + unsigned long addr = *ppos; + ssize_t copied; char *page; - unsigned long dst = *ppos; - struct mm_struct *mm = file->private_data; if (!mm) return 0; @@ -778,31 +721,54 @@ static ssize_t mem_write(struct file * file, const char __user *buf, return -ENOMEM; copied = 0; + if (!atomic_inc_not_zero(&mm->mm_users)) + goto free; + while (count > 0) { - int this_len, retval; + int this_len = min_t(int, count, PAGE_SIZE); - this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; - if (copy_from_user(page, buf, this_len)) { + if (write && copy_from_user(page, buf, this_len)) { copied = -EFAULT; break; } - retval = access_remote_vm(mm, dst, page, this_len, 1); - if (!retval) { + + this_len = access_remote_vm(mm, addr, page, this_len, write); + if (!this_len) { if (!copied) copied = -EIO; break; } - copied += retval; - buf += retval; - dst += retval; - count -= retval; + + if (!write && copy_to_user(buf, page, this_len)) { + copied = -EFAULT; + break; + } + + buf += this_len; + addr += this_len; + copied += this_len; + count -= this_len; } - *ppos = dst; + *ppos = addr; + mmput(mm); +free: free_page((unsigned long) page); return copied; } +static ssize_t mem_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + return mem_rw(file, buf, count, ppos, 0); +} + +static ssize_t mem_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + return mem_rw(file, (char __user*)buf, count, ppos, 1); +} + loff_t mem_lseek(struct file *file, loff_t offset, int orig) { switch (orig) { @@ -822,8 +788,8 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig) static int mem_release(struct inode *inode, struct file *file) { struct mm_struct *mm = file->private_data; - - mmput(mm); + if (mm) + mmdrop(mm); return 0; } diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 5ec59b20cf76..46741970371b 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -2125,6 +2125,8 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, mutex_unlock(&dqopt->dqio_mutex); goto out_file_init; } + if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) + dqopt->info[type].dqi_flags |= DQF_SYS_FILE; mutex_unlock(&dqopt->dqio_mutex); spin_lock(&dq_state_lock); dqopt->flags |= dquot_state_flag(flags, type); @@ -2464,7 +2466,7 @@ int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) spin_lock(&dq_data_lock); ii->dqi_bgrace = mi->dqi_bgrace; ii->dqi_igrace = mi->dqi_igrace; - ii->dqi_flags = mi->dqi_flags & DQF_MASK; + ii->dqi_flags = mi->dqi_flags & DQF_GETINFO_MASK; ii->dqi_valid = IIF_ALL; spin_unlock(&dq_data_lock); mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); @@ -2490,8 +2492,8 @@ int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii) if (ii->dqi_valid & IIF_IGRACE) mi->dqi_igrace = ii->dqi_igrace; if (ii->dqi_valid & IIF_FLAGS) - mi->dqi_flags = (mi->dqi_flags & ~DQF_MASK) | - (ii->dqi_flags & DQF_MASK); + mi->dqi_flags = (mi->dqi_flags & ~DQF_SETINFO_MASK) | + (ii->dqi_flags & DQF_SETINFO_MASK); spin_unlock(&dq_data_lock); mark_info_dirty(sb, type); /* Force write to disk */ diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 62f4fb37789e..00012e31829d 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -493,6 +493,12 @@ int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr, const void *ns = NULL; int err; + if (!dir_sd) { + WARN(1, KERN_ERR "sysfs: kobject %s without dirent\n", + kobject_name(kobj)); + return -ENOENT; + } + err = 0; if (!sysfs_ns_type(dir_sd)) goto out; diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 4a802b4a9056..85eb81683a29 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -318,8 +318,11 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const cha struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; - if (!dir_sd) + if (!dir_sd) { + WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n", + name); return -ENOENT; + } sysfs_addrm_start(&acxt, dir_sd); diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 0cf52da9d246..ebdb88840a47 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -131,7 +131,8 @@ xfs_readlink( __func__, (unsigned long long) ip->i_ino, (long long) pathlen); ASSERT(0); - return XFS_ERROR(EFSCORRUPTED); + error = XFS_ERROR(EFSCORRUPTED); + goto out; } diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 2fe8639b3ae7..7c9aebe8a7aa 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -218,9 +218,13 @@ acpi_status acpi_os_write_port(acpi_io_address address, u32 value, u32 width); */ acpi_status acpi_os_read_memory(acpi_physical_address address, u32 * value, u32 width); +acpi_status +acpi_os_read_memory64(acpi_physical_address address, u64 *value, u32 width); acpi_status acpi_os_write_memory(acpi_physical_address address, u32 value, u32 width); +acpi_status +acpi_os_write_memory64(acpi_physical_address address, u64 value, u32 width); /* * Platform and hardware-independent PCI configuration space access diff --git a/include/acpi/atomicio.h b/include/acpi/atomicio.h deleted file mode 100644 index 8b9fb4b0b9ce..000000000000 --- a/include/acpi/atomicio.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef ACPI_ATOMIC_IO_H -#define ACPI_ATOMIC_IO_H - -int acpi_pre_map_gar(struct acpi_generic_address *reg); -int acpi_post_unmap_gar(struct acpi_generic_address *reg); - -int acpi_atomic_read(u64 *val, struct acpi_generic_address *reg); -int acpi_atomic_write(u64 val, struct acpi_generic_address *reg); - -#endif diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 610f6fb1bbc2..8cf7e98a2c7b 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -195,6 +195,7 @@ struct acpi_processor_flags { u8 has_cst:1; u8 power_setup_done:1; u8 bm_rld_set:1; + u8 need_hotplug_init:1; }; struct acpi_processor { diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 76caa67c22e2..92f0981b5fb8 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1328,6 +1328,7 @@ extern int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_authmagic(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic); /* Cache management (drm_cache.c) */ void drm_clflush_pages(struct page *pages[], unsigned long num_pages); diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index fd88a3945aa1..0092102db2de 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -18,7 +18,7 @@ struct pt_regs; #define BINPRM_BUF_SIZE 128 #ifdef __KERNEL__ -#include <linux/list.h> +#include <linux/sched.h> #define CORENAME_MAX_SIZE 128 @@ -58,6 +58,7 @@ struct linux_binprm { unsigned interp_flags; unsigned interp_data; unsigned long loader, exec; + char tcomm[TASK_COMM_LEN]; }; #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0 diff --git a/include/linux/freezer.h b/include/linux/freezer.h index 0ab54e16a91f..d09af4b67cf1 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h @@ -39,6 +39,7 @@ extern bool __refrigerator(bool check_kthr_stop); extern int freeze_processes(void); extern int freeze_kernel_threads(void); extern void thaw_processes(void); +extern void thaw_kernel_threads(void); static inline bool try_to_freeze(void) { @@ -174,6 +175,7 @@ static inline bool __refrigerator(bool check_kthr_stop) { return false; } static inline int freeze_processes(void) { return -ENOSYS; } static inline int freeze_kernel_threads(void) { return -ENOSYS; } static inline void thaw_processes(void) {} +static inline void thaw_kernel_threads(void) {} static inline bool try_to_freeze(void) { return false; } diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h index b5ca4b2c08ec..004ff33ab38e 100644 --- a/include/linux/gpio_keys.h +++ b/include/linux/gpio_keys.h @@ -1,6 +1,8 @@ #ifndef _GPIO_KEYS_H #define _GPIO_KEYS_H +struct device; + struct gpio_keys_button { /* Configuration parameters */ unsigned int code; /* input event code (KEY_*, SW_*) */ diff --git a/include/linux/if_team.h b/include/linux/if_team.h index 828181fbad5d..58404b0c5010 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -46,6 +46,10 @@ struct team_port { u32 speed; u8 duplex; + /* Custom gennetlink interface related flags */ + bool changed; + bool removed; + struct rcu_head rcu; }; @@ -72,6 +76,10 @@ struct team_option { enum team_option_type type; int (*getter)(struct team *team, void *arg); int (*setter)(struct team *team, void *arg); + + /* Custom gennetlink interface related flags */ + bool changed; + bool removed; }; struct team_mode { @@ -207,6 +215,7 @@ enum { TEAM_ATTR_OPTION_CHANGED, /* flag */ TEAM_ATTR_OPTION_TYPE, /* u8 */ TEAM_ATTR_OPTION_DATA, /* dynamic */ + TEAM_ATTR_OPTION_REMOVED, /* flag */ __TEAM_ATTR_OPTION_MAX, TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1, @@ -227,6 +236,7 @@ enum { TEAM_ATTR_PORT_LINKUP, /* flag */ TEAM_ATTR_PORT_SPEED, /* u32 */ TEAM_ATTR_PORT_DUPLEX, /* u8 */ + TEAM_ATTR_PORT_REMOVED, /* flag */ __TEAM_ATTR_PORT_MAX, TEAM_ATTR_PORT_MAX = __TEAM_ATTR_PORT_MAX - 1, diff --git a/include/linux/lp8727.h b/include/linux/lp8727.h index d21fa2865bf4..d21fa2865bf4 100755..100644 --- a/include/linux/lp8727.h +++ b/include/linux/lp8727.h diff --git a/include/linux/mfd/mcp.h b/include/linux/mfd/mcp.h index 1515e64e3663..f88c1cc0cb0f 100644 --- a/include/linux/mfd/mcp.h +++ b/include/linux/mfd/mcp.h @@ -10,7 +10,6 @@ #ifndef MCP_H #define MCP_H -#include <linux/mod_devicetable.h> #include <mach/dma.h> struct mcp_ops; @@ -27,7 +26,7 @@ struct mcp { dma_device_t dma_telco_rd; dma_device_t dma_telco_wr; struct device attached_device; - const char *codec; + int gpio_base; }; struct mcp_ops { @@ -45,11 +44,10 @@ void mcp_reg_write(struct mcp *, unsigned int, unsigned int); unsigned int mcp_reg_read(struct mcp *, unsigned int); void mcp_enable(struct mcp *); void mcp_disable(struct mcp *); -const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp); #define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate) struct mcp *mcp_host_alloc(struct device *, size_t); -int mcp_host_register(struct mcp *, void *); +int mcp_host_register(struct mcp *); void mcp_host_unregister(struct mcp *); struct mcp_driver { @@ -58,7 +56,6 @@ struct mcp_driver { void (*remove)(struct mcp *); int (*suspend)(struct mcp *, pm_message_t); int (*resume)(struct mcp *); - const struct mcp_device_id *id_table; }; int mcp_driver_register(struct mcp_driver *); @@ -67,6 +64,9 @@ void mcp_driver_unregister(struct mcp_driver *); #define mcp_get_drvdata(mcp) dev_get_drvdata(&(mcp)->attached_device) #define mcp_set_drvdata(mcp,d) dev_set_drvdata(&(mcp)->attached_device, d) -#define mcp_priv(mcp) ((void *)((mcp)+1)) +static inline void *mcp_priv(struct mcp *mcp) +{ + return mcp + 1; +} #endif diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 2463c2619596..9bc9ac651dad 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h @@ -187,8 +187,10 @@ struct twl6040 { int rev; u8 vibra_ctrl_cache[2]; + /* PLL configuration */ int pll; unsigned int sysclk; + unsigned int mclk; unsigned int irq; unsigned int irq_base; diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h index bc19e5fb7ea8..4321f044d1e4 100644 --- a/include/linux/mfd/ucb1x00.h +++ b/include/linux/mfd/ucb1x00.h @@ -104,9 +104,6 @@ #define UCB_MODE_DYN_VFLAG_ENA (1 << 12) #define UCB_MODE_AUD_OFF_CAN (1 << 13) -struct ucb1x00_plat_data { - int gpio_base; -}; struct ucb1x00_irq { void *devid; @@ -119,7 +116,7 @@ struct ucb1x00 { unsigned int irq; struct semaphore adc_sem; spinlock_t io_lock; - const struct mcp_device_id *id; + u16 id; u16 io_dir; u16 io_out; u16 adc_cr; diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 5c4fe8e5bfe5..aea61905499b 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -621,6 +621,7 @@ void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac); int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac); int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn); void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn); +void mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap); int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx); int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index b29e7f6f8fa5..83ac0713ed0a 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -436,17 +436,6 @@ struct spi_device_id { __attribute__((aligned(sizeof(kernel_ulong_t)))); }; -/* mcp */ - -#define MCP_NAME_SIZE 20 -#define MCP_MODULE_PREFIX "mcp:" - -struct mcp_device_id { - char name[MCP_NAME_SIZE]; - kernel_ulong_t driver_data /* Data private to the driver */ - __attribute__((aligned(sizeof(kernel_ulong_t)))); -}; - /* dmi */ enum dmi_field { DMI_NONE, diff --git a/include/linux/mpi.h b/include/linux/mpi.h index 06f88994ccaa..d02cca6cc8ce 100644 --- a/include/linux/mpi.h +++ b/include/linux/mpi.h @@ -57,8 +57,6 @@ struct gcry_mpi { typedef struct gcry_mpi *MPI; -#define MPI_NULL NULL - #define mpi_get_nlimbs(a) ((a)->nlimbs) #define mpi_is_neg(a) ((a)->sign) diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 1a81fde8f333..d43dc25af82e 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -427,9 +427,7 @@ static inline int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) static inline int mtd_suspend(struct mtd_info *mtd) { - if (!mtd->suspend) - return -EOPNOTSUPP; - return mtd->suspend(mtd); + return mtd->suspend ? mtd->suspend(mtd) : 0; } static inline void mtd_resume(struct mtd_info *mtd) @@ -441,7 +439,7 @@ static inline void mtd_resume(struct mtd_info *mtd) static inline int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) { if (!mtd->block_isbad) - return -EOPNOTSUPP; + return 0; return mtd->block_isbad(mtd, ofs); } diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 08855613ceb3..abb2776be1ba 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -587,6 +587,7 @@ struct hw_perf_event { u64 sample_period; u64 last_period; local64_t period_left; + u64 interrupts_seq; u64 interrupts; u64 freq_time_stamp; diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index e5bbcbaa6f57..4d99e4e6ef83 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h @@ -110,7 +110,19 @@ static inline void pm_qos_remove_request(struct pm_qos_request *req) { return; } static inline int pm_qos_request(int pm_qos_class) - { return 0; } +{ + switch (pm_qos_class) { + case PM_QOS_CPU_DMA_LATENCY: + return PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; + case PM_QOS_NETWORK_LATENCY: + return PM_QOS_NETWORK_LAT_DEFAULT_VALUE; + case PM_QOS_NETWORK_THROUGHPUT: + return PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE; + default: + return PM_QOS_DEFAULT_VALUE; + } +} + static inline int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier) { return 0; } diff --git a/include/linux/quota.h b/include/linux/quota.h index cb7855699037..c09fa042b5ea 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -230,7 +230,11 @@ struct mem_dqinfo { struct super_block; #define DQF_MASK 0xffff /* Mask for format specific flags */ -#define DQF_INFO_DIRTY_B 16 +#define DQF_GETINFO_MASK 0x1ffff /* Mask for flags passed to userspace */ +#define DQF_SETINFO_MASK 0xffff /* Mask for flags modifiable from userspace */ +#define DQF_SYS_FILE_B 16 +#define DQF_SYS_FILE (1 << DQF_SYS_FILE_B) /* Quota file stored as system file */ +#define DQF_INFO_DIRTY_B 31 #define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */ extern void mark_info_dirty(struct super_block *sb, int type); diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h index c9d625ca659e..da81af086eaf 100644 --- a/include/linux/res_counter.h +++ b/include/linux/res_counter.h @@ -109,12 +109,18 @@ void res_counter_init(struct res_counter *counter, struct res_counter *parent); * * returns 0 on success and <0 if the counter->usage will exceed the * counter->limit _locked call expects the counter->lock to be taken + * + * charge_nofail works the same, except that it charges the resource + * counter unconditionally, and returns < 0 if the after the current + * charge we are over limit. */ int __must_check res_counter_charge_locked(struct res_counter *counter, unsigned long val); int __must_check res_counter_charge(struct res_counter *counter, unsigned long val, struct res_counter **limit_fail_at); +int __must_check res_counter_charge_nofail(struct res_counter *counter, + unsigned long val, struct res_counter **limit_fail_at); /* * uncharge - tell that some portion of the resource is released @@ -142,7 +148,10 @@ static inline unsigned long long res_counter_margin(struct res_counter *cnt) unsigned long flags; spin_lock_irqsave(&cnt->lock, flags); - margin = cnt->limit - cnt->usage; + if (cnt->limit > cnt->usage) + margin = cnt->limit - cnt->usage; + else + margin = 0; spin_unlock_irqrestore(&cnt->lock, flags); return margin; } diff --git a/include/linux/sched.h b/include/linux/sched.h index 513f52459872..7d379a6bfd88 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2090,7 +2090,7 @@ extern struct task_struct *idle_task(int cpu); * is_idle_task - is the specified task an idle task? * @p: the task in question. */ -static inline bool is_idle_task(struct task_struct *p) +static inline bool is_idle_task(const struct task_struct *p) { return p->pid == 0; } @@ -2259,6 +2259,12 @@ static inline void mmdrop(struct mm_struct * mm) extern void mmput(struct mm_struct *); /* Grab a reference to a task's mm, if it is not already going away */ extern struct mm_struct *get_task_mm(struct task_struct *task); +/* + * Grab a reference to a task's mm, if it is not already going away + * and ptrace_may_access with the mode parameter passed to it + * succeeds. + */ +extern struct mm_struct *mm_access(struct task_struct *task, unsigned int mode); /* Remove the current tasks stale references to the old mm_struct */ extern void mm_release(struct task_struct *, struct mm_struct *); /* Allocate a new mm structure and copy contents from tsk->mm */ diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index 8cd7fe59cf1a..425450b980b8 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h @@ -70,6 +70,7 @@ struct sh_dmae_pdata { unsigned int needs_tend_set:1; unsigned int no_dmars:1; unsigned int chclr_present:1; + unsigned int slave_only:1; }; /* DMA register */ diff --git a/include/linux/snmp.h b/include/linux/snmp.h index e16557a357e5..c1241c428179 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h @@ -192,7 +192,6 @@ enum LINUX_MIB_TCPPARTIALUNDO, /* TCPPartialUndo */ LINUX_MIB_TCPDSACKUNDO, /* TCPDSACKUndo */ LINUX_MIB_TCPLOSSUNDO, /* TCPLossUndo */ - LINUX_MIB_TCPLOSS, /* TCPLoss */ LINUX_MIB_TCPLOSTRETRANSMIT, /* TCPLostRetransmit */ LINUX_MIB_TCPRENOFAILURES, /* TCPRenoFailures */ LINUX_MIB_TCPSACKFAILURES, /* TCPSackFailures */ diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h deleted file mode 100644 index 20f63d3e6144..000000000000 --- a/include/linux/sysdev.h +++ /dev/null @@ -1,164 +0,0 @@ -/** - * System devices follow a slightly different driver model. - * They don't need to do dynammic driver binding, can't be probed, - * and don't reside on any type of peripheral bus. - * So, we represent and treat them a little differently. - * - * We still have a notion of a driver for a system device, because we still - * want to perform basic operations on these devices. - * - * We also support auxiliary drivers binding to devices of a certain class. - * - * This allows configurable drivers to register themselves for devices of - * a certain type. And, it allows class definitions to reside in generic - * code while arch-specific code can register specific drivers. - * - * Auxiliary drivers registered with a NULL cls are registered as drivers - * for all system devices, and get notification calls for each device. - */ - - -#ifndef _SYSDEV_H_ -#define _SYSDEV_H_ - -#include <linux/kobject.h> -#include <linux/pm.h> - - -struct sys_device; -struct sysdev_class_attribute; - -struct sysdev_class { - const char *name; - struct list_head drivers; - struct sysdev_class_attribute **attrs; - struct kset kset; -}; - -struct sysdev_class_attribute { - struct attribute attr; - ssize_t (*show)(struct sysdev_class *, struct sysdev_class_attribute *, - char *); - ssize_t (*store)(struct sysdev_class *, struct sysdev_class_attribute *, - const char *, size_t); -}; - -#define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \ -{ \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ - .show = _show, \ - .store = _store, \ -} - -#define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \ - struct sysdev_class_attribute attr_##_name = \ - _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) - - -extern int sysdev_class_register(struct sysdev_class *); -extern void sysdev_class_unregister(struct sysdev_class *); - -extern int sysdev_class_create_file(struct sysdev_class *, - struct sysdev_class_attribute *); -extern void sysdev_class_remove_file(struct sysdev_class *, - struct sysdev_class_attribute *); -/** - * Auxiliary system device drivers. - */ - -struct sysdev_driver { - struct list_head entry; - int (*add)(struct sys_device *); - int (*remove)(struct sys_device *); -}; - - -extern int sysdev_driver_register(struct sysdev_class *, struct sysdev_driver *); -extern void sysdev_driver_unregister(struct sysdev_class *, struct sysdev_driver *); - - -/** - * sys_devices can be simplified a lot from regular devices, because they're - * simply not as versatile. - */ - -struct sys_device { - u32 id; - struct sysdev_class * cls; - struct kobject kobj; -}; - -extern int sysdev_register(struct sys_device *); -extern void sysdev_unregister(struct sys_device *); - - -struct sysdev_attribute { - struct attribute attr; - ssize_t (*show)(struct sys_device *, struct sysdev_attribute *, char *); - ssize_t (*store)(struct sys_device *, struct sysdev_attribute *, - const char *, size_t); -}; - - -#define _SYSDEV_ATTR(_name, _mode, _show, _store) \ -{ \ - .attr = { .name = __stringify(_name), .mode = _mode }, \ - .show = _show, \ - .store = _store, \ -} - -#define SYSDEV_ATTR(_name, _mode, _show, _store) \ - struct sysdev_attribute attr_##_name = \ - _SYSDEV_ATTR(_name, _mode, _show, _store); - -extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *); -extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *); - -/* Create/remove NULL terminated attribute list */ -static inline int -sysdev_create_files(struct sys_device *d, struct sysdev_attribute **a) -{ - return sysfs_create_files(&d->kobj, (const struct attribute **)a); -} - -static inline void -sysdev_remove_files(struct sys_device *d, struct sysdev_attribute **a) -{ - return sysfs_remove_files(&d->kobj, (const struct attribute **)a); -} - -struct sysdev_ext_attribute { - struct sysdev_attribute attr; - void *var; -}; - -/* - * Support for simple variable sysdev attributes. - * The pointer to the variable is stored in a sysdev_ext_attribute - */ - -/* Add more types as needed */ - -extern ssize_t sysdev_show_ulong(struct sys_device *, struct sysdev_attribute *, - char *); -extern ssize_t sysdev_store_ulong(struct sys_device *, - struct sysdev_attribute *, const char *, size_t); -extern ssize_t sysdev_show_int(struct sys_device *, struct sysdev_attribute *, - char *); -extern ssize_t sysdev_store_int(struct sys_device *, - struct sysdev_attribute *, const char *, size_t); - -#define _SYSDEV_ULONG_ATTR(_name, _mode, _var) \ - { _SYSDEV_ATTR(_name, _mode, sysdev_show_ulong, sysdev_store_ulong), \ - &(_var) } -#define SYSDEV_ULONG_ATTR(_name, _mode, _var) \ - struct sysdev_ext_attribute attr_##_name = \ - _SYSDEV_ULONG_ATTR(_name, _mode, _var); -#define _SYSDEV_INT_ATTR(_name, _mode, _var) \ - { _SYSDEV_ATTR(_name, _mode, sysdev_show_int, sysdev_store_int), \ - &(_var) } -#define SYSDEV_INT_ATTR(_name, _mode, _var) \ - struct sysdev_ext_attribute attr_##_name = \ - _SYSDEV_INT_ATTR(_name, _mode, _var); - -#endif /* _SYSDEV_H_ */ diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 47b4a27e6e97..796f1ff0388c 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -152,9 +152,9 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *, void *, void thermal_cooling_device_unregister(struct thermal_cooling_device *); #ifdef CONFIG_NET -extern int generate_netlink_event(u32 orig, enum events event); +extern int thermal_generate_netlink_event(u32 orig, enum events event); #else -static inline int generate_netlink_event(u32 orig, enum events event) +static inline int thermal_generate_netlink_event(u32 orig, enum events event) { return 0; } diff --git a/include/linux/usb/langwell_otg.h b/include/linux/usb/langwell_otg.h deleted file mode 100644 index 51f17b16d312..000000000000 --- a/include/linux/usb/langwell_otg.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Intel Langwell USB OTG transceiver driver - * Copyright (C) 2008 - 2010, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef __LANGWELL_OTG_H -#define __LANGWELL_OTG_H - -#include <linux/usb/intel_mid_otg.h> - -#define CI_USBCMD 0x30 -# define USBCMD_RST BIT(1) -# define USBCMD_RS BIT(0) -#define CI_USBSTS 0x34 -# define USBSTS_SLI BIT(8) -# define USBSTS_URI BIT(6) -# define USBSTS_PCI BIT(2) -#define CI_PORTSC1 0x74 -# define PORTSC_PP BIT(12) -# define PORTSC_LS (BIT(11) | BIT(10)) -# define PORTSC_SUSP BIT(7) -# define PORTSC_CCS BIT(0) -#define CI_HOSTPC1 0xb4 -# define HOSTPC1_PHCD BIT(22) -#define CI_OTGSC 0xf4 -# define OTGSC_DPIE BIT(30) -# define OTGSC_1MSE BIT(29) -# define OTGSC_BSEIE BIT(28) -# define OTGSC_BSVIE BIT(27) -# define OTGSC_ASVIE BIT(26) -# define OTGSC_AVVIE BIT(25) -# define OTGSC_IDIE BIT(24) -# define OTGSC_DPIS BIT(22) -# define OTGSC_1MSS BIT(21) -# define OTGSC_BSEIS BIT(20) -# define OTGSC_BSVIS BIT(19) -# define OTGSC_ASVIS BIT(18) -# define OTGSC_AVVIS BIT(17) -# define OTGSC_IDIS BIT(16) -# define OTGSC_DPS BIT(14) -# define OTGSC_1MST BIT(13) -# define OTGSC_BSE BIT(12) -# define OTGSC_BSV BIT(11) -# define OTGSC_ASV BIT(10) -# define OTGSC_AVV BIT(9) -# define OTGSC_ID BIT(8) -# define OTGSC_HABA BIT(7) -# define OTGSC_HADP BIT(6) -# define OTGSC_IDPU BIT(5) -# define OTGSC_DP BIT(4) -# define OTGSC_OT BIT(3) -# define OTGSC_HAAR BIT(2) -# define OTGSC_VC BIT(1) -# define OTGSC_VD BIT(0) -# define OTGSC_INTEN_MASK (0x7f << 24) -# define OTGSC_INT_MASK (0x5f << 24) -# define OTGSC_INTSTS_MASK (0x7f << 16) -#define CI_USBMODE 0xf8 -# define USBMODE_CM (BIT(1) | BIT(0)) -# define USBMODE_IDLE 0 -# define USBMODE_DEVICE 0x2 -# define USBMODE_HOST 0x3 -#define USBCFG_ADDR 0xff10801c -#define USBCFG_LEN 4 -# define USBCFG_VBUSVAL BIT(14) -# define USBCFG_AVALID BIT(13) -# define USBCFG_BVALID BIT(12) -# define USBCFG_SESEND BIT(11) - -#define INTR_DUMMY_MASK (USBSTS_SLI | USBSTS_URI | USBSTS_PCI) - -enum langwell_otg_timer_type { - TA_WAIT_VRISE_TMR, - TA_WAIT_BCON_TMR, - TA_AIDL_BDIS_TMR, - TB_ASE0_BRST_TMR, - TB_SE0_SRP_TMR, - TB_SRP_INIT_TMR, - TB_SRP_FAIL_TMR, - TB_BUS_SUSPEND_TMR -}; - -#define TA_WAIT_VRISE 100 -#define TA_WAIT_BCON 30000 -#define TA_AIDL_BDIS 15000 -#define TB_ASE0_BRST 5000 -#define TB_SE0_SRP 2 -#define TB_SRP_INIT 100 -#define TB_SRP_FAIL 5500 -#define TB_BUS_SUSPEND 500 - -struct langwell_otg_timer { - unsigned long expires; /* Number of count increase to timeout */ - unsigned long count; /* Tick counter */ - void (*function)(unsigned long); /* Timeout function */ - unsigned long data; /* Data passed to function */ - struct list_head list; -}; - -struct langwell_otg { - struct intel_mid_otg_xceiv iotg; - struct device *dev; - - void __iomem *usbcfg; /* SCCBUSB config Reg */ - - unsigned region; - unsigned cfg_region; - - struct work_struct work; - struct workqueue_struct *qwork; - struct timer_list hsm_timer; - - spinlock_t lock; - spinlock_t wq_lock; - - struct notifier_block iotg_notifier; -}; - -static inline -struct langwell_otg *mid_xceiv_to_lnw(struct intel_mid_otg_xceiv *iotg) -{ - return container_of(iotg, struct langwell_otg, iotg); -} - -#endif /* __LANGWELL_OTG_H__ */ diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 5b2fed5eebf2..00596e816b4d 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1388,6 +1388,6 @@ struct hci_inquiry_req { }; #define IREQ_CACHE_FLUSH 0x0001 -extern int enable_hs; +extern bool enable_hs; #endif /* __HCI_H */ diff --git a/include/net/netns/generic.h b/include/net/netns/generic.h index 3419bf5cd154..d55f43443335 100644 --- a/include/net/netns/generic.h +++ b/include/net/netns/generic.h @@ -41,6 +41,7 @@ static inline void *net_generic(const struct net *net, int id) ptr = ng->ptr[id - 1]; rcu_read_unlock(); + BUG_ON(!ptr); return ptr; } #endif diff --git a/include/net/netprio_cgroup.h b/include/net/netprio_cgroup.h index e503b87c4c1b..7b2d43139c8e 100644 --- a/include/net/netprio_cgroup.h +++ b/include/net/netprio_cgroup.h @@ -13,7 +13,6 @@ #ifndef _NETPRIO_CGROUP_H #define _NETPRIO_CGROUP_H -#include <linux/module.h> #include <linux/cgroup.h> #include <linux/hardirq.h> #include <linux/rcupdate.h> diff --git a/include/net/sock.h b/include/net/sock.h index bb972d254dff..91c1c8baf020 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -55,6 +55,7 @@ #include <linux/uaccess.h> #include <linux/memcontrol.h> #include <linux/res_counter.h> +#include <linux/jump_label.h> #include <linux/filter.h> #include <linux/rculist_nulls.h> @@ -226,6 +227,7 @@ struct cg_proto; * @sk_ack_backlog: current listen backlog * @sk_max_ack_backlog: listen backlog set in listen() * @sk_priority: %SO_PRIORITY setting + * @sk_cgrp_prioidx: socket group's priority map index * @sk_type: socket type (%SOCK_STREAM, etc) * @sk_protocol: which protocol this socket belongs in this network family * @sk_peer_pid: &struct pid for this socket's peer @@ -921,7 +923,7 @@ inline void sk_refcnt_debug_release(const struct sock *sk) #define sk_refcnt_debug_release(sk) do { } while (0) #endif /* SOCK_REFCNT_DEBUG */ -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#if defined(CONFIG_CGROUP_MEM_RES_CTLR_KMEM) && defined(CONFIG_NET) extern struct jump_label_key memcg_socket_limit_enabled; static inline struct cg_proto *parent_cg_proto(struct proto *proto, struct cg_proto *cg_proto) @@ -1007,9 +1009,8 @@ static inline void memcg_memory_allocated_add(struct cg_proto *prot, struct res_counter *fail; int ret; - ret = res_counter_charge(prot->memory_allocated, - amt << PAGE_SHIFT, &fail); - + ret = res_counter_charge_nofail(prot->memory_allocated, + amt << PAGE_SHIFT, &fail); if (ret < 0) *parent_status = OVER_LIMIT; } @@ -1053,12 +1054,11 @@ sk_memory_allocated_add(struct sock *sk, int amt, int *parent_status) } static inline void -sk_memory_allocated_sub(struct sock *sk, int amt, int parent_status) +sk_memory_allocated_sub(struct sock *sk, int amt) { struct proto *prot = sk->sk_prot; - if (mem_cgroup_sockets_enabled && sk->sk_cgrp && - parent_status != OVER_LIMIT) /* Otherwise was uncharged already */ + if (mem_cgroup_sockets_enabled && sk->sk_cgrp) memcg_memory_allocated_sub(sk->sk_cgrp, amt); atomic_long_sub(amt, prot->memory_allocated); diff --git a/include/net/tcp.h b/include/net/tcp.h index 0118ea999f67..d49db0113a06 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -311,6 +311,8 @@ extern struct proto tcp_prot; #define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val) #define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val) +extern void tcp_init_mem(struct net *net); + extern void tcp_v4_err(struct sk_buff *skb, u32); extern void tcp_shutdown (struct sock *sk, int how); diff --git a/include/sound/core.h b/include/sound/core.h index 5ab255f196cc..cea1b5426dfa 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -417,6 +417,7 @@ static inline int __snd_bug_on(int cond) #define gameport_get_port_data(gp) (gp)->port_data #endif +#ifdef CONFIG_PCI /* PCI quirk list helper */ struct snd_pci_quirk { unsigned short subvendor; /* PCI subvendor ID */ @@ -456,5 +457,6 @@ snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list); const struct snd_pci_quirk * snd_pci_quirk_lookup_id(u16 vendor, u16 device, const struct snd_pci_quirk *list); +#endif #endif /* __SOUND_CORE_H */ diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c index 057e24b665cf..6581a040f399 100644 --- a/kernel/events/callchain.c +++ b/kernel/events/callchain.c @@ -115,8 +115,6 @@ int get_callchain_buffers(void) } err = alloc_callchain_buffers(); - if (err) - release_callchain_buffers(); exit: mutex_unlock(&callchain_mutex); diff --git a/kernel/events/core.c b/kernel/events/core.c index a8f4ac001a00..ba36013cfb21 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -815,7 +815,7 @@ static void update_event_times(struct perf_event *event) * here. */ if (is_cgroup_event(event)) - run_end = perf_event_time(event); + run_end = perf_cgroup_event_time(event); else if (ctx->is_active) run_end = ctx->time; else @@ -2300,6 +2300,9 @@ do { \ return div64_u64(dividend, divisor); } +static DEFINE_PER_CPU(int, perf_throttled_count); +static DEFINE_PER_CPU(u64, perf_throttled_seq); + static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count) { struct hw_perf_event *hwc = &event->hw; @@ -2325,16 +2328,29 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count) } } -static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period) +/* + * combine freq adjustment with unthrottling to avoid two passes over the + * events. At the same time, make sure, having freq events does not change + * the rate of unthrottling as that would introduce bias. + */ +static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx, + int needs_unthr) { struct perf_event *event; struct hw_perf_event *hwc; - u64 interrupts, now; + u64 now, period = TICK_NSEC; s64 delta; - if (!ctx->nr_freq) + /* + * only need to iterate over all events iff: + * - context have events in frequency mode (needs freq adjust) + * - there are events to unthrottle on this cpu + */ + if (!(ctx->nr_freq || needs_unthr)) return; + raw_spin_lock(&ctx->lock); + list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { if (event->state != PERF_EVENT_STATE_ACTIVE) continue; @@ -2344,13 +2360,8 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period) hwc = &event->hw; - interrupts = hwc->interrupts; - hwc->interrupts = 0; - - /* - * unthrottle events on the tick - */ - if (interrupts == MAX_INTERRUPTS) { + if (needs_unthr && hwc->interrupts == MAX_INTERRUPTS) { + hwc->interrupts = 0; perf_log_throttle(event, 1); event->pmu->start(event, 0); } @@ -2358,14 +2369,26 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period) if (!event->attr.freq || !event->attr.sample_freq) continue; - event->pmu->read(event); + /* + * stop the event and update event->count + */ + event->pmu->stop(event, PERF_EF_UPDATE); + now = local64_read(&event->count); delta = now - hwc->freq_count_stamp; hwc->freq_count_stamp = now; + /* + * restart the event + * reload only if value has changed + */ if (delta > 0) perf_adjust_period(event, period, delta); + + event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0); } + + raw_spin_unlock(&ctx->lock); } /* @@ -2388,16 +2411,13 @@ static void rotate_ctx(struct perf_event_context *ctx) */ static void perf_rotate_context(struct perf_cpu_context *cpuctx) { - u64 interval = (u64)cpuctx->jiffies_interval * TICK_NSEC; struct perf_event_context *ctx = NULL; - int rotate = 0, remove = 1, freq = 0; + int rotate = 0, remove = 1; if (cpuctx->ctx.nr_events) { remove = 0; if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active) rotate = 1; - if (cpuctx->ctx.nr_freq) - freq = 1; } ctx = cpuctx->task_ctx; @@ -2405,37 +2425,26 @@ static void perf_rotate_context(struct perf_cpu_context *cpuctx) remove = 0; if (ctx->nr_events != ctx->nr_active) rotate = 1; - if (ctx->nr_freq) - freq = 1; } - if (!rotate && !freq) + if (!rotate) goto done; perf_ctx_lock(cpuctx, cpuctx->task_ctx); perf_pmu_disable(cpuctx->ctx.pmu); - if (freq) { - perf_ctx_adjust_freq(&cpuctx->ctx, interval); - if (ctx) - perf_ctx_adjust_freq(ctx, interval); - } - - if (rotate) { - cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); - if (ctx) - ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE); + cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); + if (ctx) + ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE); - rotate_ctx(&cpuctx->ctx); - if (ctx) - rotate_ctx(ctx); + rotate_ctx(&cpuctx->ctx); + if (ctx) + rotate_ctx(ctx); - perf_event_sched_in(cpuctx, ctx, current); - } + perf_event_sched_in(cpuctx, ctx, current); perf_pmu_enable(cpuctx->ctx.pmu); perf_ctx_unlock(cpuctx, cpuctx->task_ctx); - done: if (remove) list_del_init(&cpuctx->rotation_list); @@ -2445,10 +2454,22 @@ void perf_event_task_tick(void) { struct list_head *head = &__get_cpu_var(rotation_list); struct perf_cpu_context *cpuctx, *tmp; + struct perf_event_context *ctx; + int throttled; WARN_ON(!irqs_disabled()); + __this_cpu_inc(perf_throttled_seq); + throttled = __this_cpu_xchg(perf_throttled_count, 0); + list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) { + ctx = &cpuctx->ctx; + perf_adjust_freq_unthr_context(ctx, throttled); + + ctx = cpuctx->task_ctx; + if (ctx) + perf_adjust_freq_unthr_context(ctx, throttled); + if (cpuctx->jiffies_interval == 1 || !(jiffies % cpuctx->jiffies_interval)) perf_rotate_context(cpuctx); @@ -4509,6 +4530,7 @@ static int __perf_event_overflow(struct perf_event *event, { int events = atomic_read(&event->event_limit); struct hw_perf_event *hwc = &event->hw; + u64 seq; int ret = 0; /* @@ -4518,14 +4540,20 @@ static int __perf_event_overflow(struct perf_event *event, if (unlikely(!is_sampling_event(event))) return 0; - if (unlikely(hwc->interrupts >= max_samples_per_tick)) { - if (throttle) { + seq = __this_cpu_read(perf_throttled_seq); + if (seq != hwc->interrupts_seq) { + hwc->interrupts_seq = seq; + hwc->interrupts = 1; + } else { + hwc->interrupts++; + if (unlikely(throttle + && hwc->interrupts >= max_samples_per_tick)) { + __this_cpu_inc(perf_throttled_count); hwc->interrupts = MAX_INTERRUPTS; perf_log_throttle(event, 0); ret = 1; } - } else - hwc->interrupts++; + } if (event->attr.freq) { u64 now = perf_clock(); diff --git a/kernel/exit.c b/kernel/exit.c index 294b1709170d..4b4042f9bc6a 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1038,6 +1038,22 @@ void do_exit(long code) if (tsk->nr_dirtied) __this_cpu_add(dirty_throttle_leaks, tsk->nr_dirtied); exit_rcu(); + + /* + * The setting of TASK_RUNNING by try_to_wake_up() may be delayed + * when the following two conditions become true. + * - There is race condition of mmap_sem (It is acquired by + * exit_mm()), and + * - SMI occurs before setting TASK_RUNINNG. + * (or hypervisor of virtual machine switches to other guest) + * As a result, we may become TASK_RUNNING after becoming TASK_DEAD + * + * To avoid it, we have to wait for releasing tsk->pi_lock which + * is held by try_to_wake_up() + */ + smp_mb(); + raw_spin_unlock_wait(&tsk->pi_lock); + /* causes final put_task_struct in finish_task_switch(). */ tsk->state = TASK_DEAD; tsk->flags |= PF_NOFREEZE; /* tell freezer to ignore us */ diff --git a/kernel/fork.c b/kernel/fork.c index 051f090d40c1..1b2ef3c23ae4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -647,6 +647,26 @@ struct mm_struct *get_task_mm(struct task_struct *task) } EXPORT_SYMBOL_GPL(get_task_mm); +struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) +{ + struct mm_struct *mm; + int err; + + err = mutex_lock_killable(&task->signal->cred_guard_mutex); + if (err) + return ERR_PTR(err); + + mm = get_task_mm(task); + if (mm && mm != current->mm && + !ptrace_may_access(task, mode)) { + mmput(mm); + mm = ERR_PTR(-EACCES); + } + mutex_unlock(&task->signal->cred_guard_mutex); + + return mm; +} + /* Please note the differences between mmput and mm_release. * mmput is called whenever we stop holding onto a mm_struct, * error success whatever. diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 29f5b65bee29..9788c0ec6f43 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1673,8 +1673,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p, ri->rp = rp; ri->task = current; - if (rp->entry_handler && rp->entry_handler(ri, regs)) + if (rp->entry_handler && rp->entry_handler(ri, regs)) { + raw_spin_lock_irqsave(&rp->lock, flags); + hlist_add_head(&ri->hlist, &rp->free_instances); + raw_spin_unlock_irqrestore(&rp->lock, flags); return 0; + } arch_prepare_kretprobe(ri, regs); diff --git a/kernel/power/power.h b/kernel/power/power.h index 0c4defe6d3b8..21724eee5206 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -231,8 +231,28 @@ extern int pm_test_level; #ifdef CONFIG_SUSPEND_FREEZER static inline int suspend_freeze_processes(void) { - int error = freeze_processes(); - return error ? : freeze_kernel_threads(); + int error; + + error = freeze_processes(); + + /* + * freeze_processes() automatically thaws every task if freezing + * fails. So we need not do anything extra upon error. + */ + if (error) + goto Finish; + + error = freeze_kernel_threads(); + + /* + * freeze_kernel_threads() thaws only kernel threads upon freezing + * failure. So we have to thaw the userspace tasks ourselves. + */ + if (error) + thaw_processes(); + + Finish: + return error; } static inline void suspend_thaw_processes(void) diff --git a/kernel/power/process.c b/kernel/power/process.c index 77274c9ba2f1..7e426459e60a 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -143,7 +143,10 @@ int freeze_processes(void) /** * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator. * - * On success, returns 0. On failure, -errno and system is fully thawed. + * On success, returns 0. On failure, -errno and only the kernel threads are + * thawed, so as to give a chance to the caller to do additional cleanups + * (if any) before thawing the userspace tasks. So, it is the responsibility + * of the caller to thaw the userspace tasks, when the time is right. */ int freeze_kernel_threads(void) { @@ -159,7 +162,7 @@ int freeze_kernel_threads(void) BUG_ON(in_atomic()); if (error) - thaw_processes(); + thaw_kernel_threads(); return error; } @@ -188,3 +191,22 @@ void thaw_processes(void) printk("done.\n"); } +void thaw_kernel_threads(void) +{ + struct task_struct *g, *p; + + pm_nosig_freezing = false; + printk("Restarting kernel threads ... "); + + thaw_workqueues(); + + read_lock(&tasklist_lock); + do_each_thread(g, p) { + if (p->flags & (PF_KTHREAD | PF_WQ_WORKER)) + __thaw_task(p); + } while_each_thread(g, p); + read_unlock(&tasklist_lock); + + schedule(); + printk("done.\n"); +} diff --git a/kernel/power/user.c b/kernel/power/user.c index 6b1ab7a88522..3e100075b13c 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -249,13 +249,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, } pm_restore_gfp_mask(); error = hibernation_snapshot(data->platform_support); - if (!error) { + if (error) { + thaw_kernel_threads(); + } else { error = put_user(in_suspend, (int __user *)arg); if (!error && !freezer_test_done) data->ready = 1; if (freezer_test_done) { freezer_test_done = false; - thaw_processes(); + thaw_kernel_threads(); } } break; @@ -274,6 +276,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, swsusp_free(); memset(&data->handle, 0, sizeof(struct snapshot_handle)); data->ready = 0; + /* + * It is necessary to thaw kernel threads here, because + * SNAPSHOT_CREATE_IMAGE may be invoked directly after + * SNAPSHOT_FREE. In that case, if kernel threads were not + * thawed, the preallocation of memory carried out by + * hibernation_snapshot() might run into problems (i.e. it + * might fail or even deadlock). + */ + thaw_kernel_threads(); break; case SNAPSHOT_PREF_IMAGE_SIZE: diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 88f17b8a3b1d..a58ac285fc69 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -56,8 +56,8 @@ static int nreaders = -1; /* # reader threads, defaults to 2*ncpus */ static int nfakewriters = 4; /* # fake writer threads */ static int stat_interval; /* Interval between stats, in seconds. */ /* Defaults to "only at end of test". */ -static int verbose; /* Print more debug info. */ -static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */ +static bool verbose; /* Print more debug info. */ +static bool test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */ static int shuffle_interval = 3; /* Interval between shuffles (in sec)*/ static int stutter = 5; /* Start/stop testing interval (in sec) */ static int irqreader = 1; /* RCU readers from irq (timers). */ @@ -1399,7 +1399,7 @@ rcu_torture_shutdown(void *arg) * Execute random CPU-hotplug operations at the interval specified * by the onoff_interval. */ -static int +static int __cpuinit rcu_torture_onoff(void *arg) { int cpu; @@ -1447,7 +1447,7 @@ rcu_torture_onoff(void *arg) return 0; } -static int +static int __cpuinit rcu_torture_onoff_init(void) { if (onoff_interval <= 0) diff --git a/kernel/res_counter.c b/kernel/res_counter.c index 6d269cce7aa1..d508363858b3 100644 --- a/kernel/res_counter.c +++ b/kernel/res_counter.c @@ -66,6 +66,31 @@ done: return ret; } +int res_counter_charge_nofail(struct res_counter *counter, unsigned long val, + struct res_counter **limit_fail_at) +{ + int ret, r; + unsigned long flags; + struct res_counter *c; + + r = ret = 0; + *limit_fail_at = NULL; + local_irq_save(flags); + for (c = counter; c != NULL; c = c->parent) { + spin_lock(&c->lock); + r = res_counter_charge_locked(c, val); + if (r) + c->usage += val; + spin_unlock(&c->lock); + if (r < 0 && ret == 0) { + *limit_fail_at = c; + ret = r; + } + } + local_irq_restore(flags); + + return ret; +} void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val) { if (WARN_ON(counter->usage < val)) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index df00cb09263e..5255c9d2e053 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -74,6 +74,7 @@ #include <asm/tlb.h> #include <asm/irq_regs.h> +#include <asm/mutex.h> #ifdef CONFIG_PARAVIRT #include <asm/paravirt.h> #endif @@ -723,9 +724,6 @@ static void dequeue_task(struct rq *rq, struct task_struct *p, int flags) p->sched_class->dequeue_task(rq, p, flags); } -/* - * activate_task - move a task to the runqueue. - */ void activate_task(struct rq *rq, struct task_struct *p, int flags) { if (task_contributes_to_load(p)) @@ -734,9 +732,6 @@ void activate_task(struct rq *rq, struct task_struct *p, int flags) enqueue_task(rq, p, flags); } -/* - * deactivate_task - remove a task from the runqueue. - */ void deactivate_task(struct rq *rq, struct task_struct *p, int flags) { if (task_contributes_to_load(p)) @@ -4134,7 +4129,7 @@ recheck: on_rq = p->on_rq; running = task_current(rq, p); if (on_rq) - deactivate_task(rq, p, 0); + dequeue_task(rq, p, 0); if (running) p->sched_class->put_prev_task(rq, p); @@ -4147,7 +4142,7 @@ recheck: if (running) p->sched_class->set_curr_task(rq); if (on_rq) - activate_task(rq, p, 0); + enqueue_task(rq, p, 0); check_class_changed(rq, p, prev_class, oldprio); task_rq_unlock(rq, p, &flags); @@ -4998,9 +4993,9 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) * placed properly. */ if (p->on_rq) { - deactivate_task(rq_src, p, 0); + dequeue_task(rq_src, p, 0); set_task_cpu(p, dest_cpu); - activate_task(rq_dest, p, 0); + enqueue_task(rq_dest, p, 0); check_preempt_curr(rq_dest, p, 0); } done: @@ -7032,10 +7027,10 @@ static void normalize_task(struct rq *rq, struct task_struct *p) on_rq = p->on_rq; if (on_rq) - deactivate_task(rq, p, 0); + dequeue_task(rq, p, 0); __setscheduler(rq, p, SCHED_NORMAL, 0); if (on_rq) { - activate_task(rq, p, 0); + enqueue_task(rq, p, 0); resched_task(rq->curr); } diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 84adb2d66cbd..7c6414fc669d 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4866,6 +4866,15 @@ static void nohz_balancer_kick(int cpu) return; } +static inline void clear_nohz_tick_stopped(int cpu) +{ + if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) { + cpumask_clear_cpu(cpu, nohz.idle_cpus_mask); + atomic_dec(&nohz.nr_cpus); + clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); + } +} + static inline void set_cpu_sd_state_busy(void) { struct sched_domain *sd; @@ -4904,6 +4913,12 @@ void select_nohz_load_balancer(int stop_tick) { int cpu = smp_processor_id(); + /* + * If this cpu is going down, then nothing needs to be done. + */ + if (!cpu_active(cpu)) + return; + if (stop_tick) { if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu))) return; @@ -4914,6 +4929,18 @@ void select_nohz_load_balancer(int stop_tick) } return; } + +static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_DYING: + clear_nohz_tick_stopped(smp_processor_id()); + return NOTIFY_OK; + default: + return NOTIFY_DONE; + } +} #endif static DEFINE_SPINLOCK(balancing); @@ -5070,11 +5097,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu) * busy tick after returning from idle, we will update the busy stats. */ set_cpu_sd_state_busy(); - if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) { - clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); - cpumask_clear_cpu(cpu, nohz.idle_cpus_mask); - atomic_dec(&nohz.nr_cpus); - } + clear_nohz_tick_stopped(cpu); /* * None are in tickless mode and hence no need for NOHZ idle load @@ -5590,6 +5613,7 @@ __init void init_sched_fair_class(void) #ifdef CONFIG_NO_HZ zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT); + cpu_notifier(sched_ilb_notifier, 0); #endif #endif /* SMP */ diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 3640ebbb466b..f42ae7fb5ec5 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1587,6 +1587,11 @@ static int push_rt_task(struct rq *rq) if (!next_task) return 0; +#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW + if (unlikely(task_running(rq, next_task))) + return 0; +#endif + retry: if (unlikely(next_task == rq->curr)) { WARN_ON(1); diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 1d7bca7f4f52..d117262deba3 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -296,7 +296,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) if (__this_cpu_read(soft_watchdog_warn) == true) return HRTIMER_RESTART; - printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", + printk(KERN_EMERG "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", smp_processor_id(), duration, current->comm, task_pid_nr(current)); print_modules(); diff --git a/lib/Kconfig b/lib/Kconfig index 169eb7c598e5..d69d321a0997 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -279,6 +279,9 @@ config AVERAGE If unsure, say N. +config CLZ_TAB + bool + config CORDIC tristate "CORDIC algorithm" help @@ -287,6 +290,7 @@ config CORDIC config MPILIB tristate + select CLZ_TAB help Multiprecision maths library from GnuPG. It is used to implement RSA digital signature verification, diff --git a/lib/Makefile b/lib/Makefile index d71aae1b01b3..18515f0267c4 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -121,6 +121,8 @@ obj-$(CONFIG_DQL) += dynamic_queue_limits.o obj-$(CONFIG_MPILIB) += mpi/ obj-$(CONFIG_SIGNATURE) += digsig.o +obj-$(CONFIG_CLZ_TAB) += clz_tab.o + hostprogs-y := gen_crc32table clean-files := crc32table.h diff --git a/lib/bug.c b/lib/bug.c index 19552096d16b..a28c1415357c 100644 --- a/lib/bug.c +++ b/lib/bug.c @@ -169,7 +169,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs) return BUG_TRAP_TYPE_WARN; } - printk(KERN_EMERG "------------[ cut here ]------------\n"); + printk(KERN_DEFAULT "------------[ cut here ]------------\n"); if (file) printk(KERN_CRIT "kernel BUG at %s:%u!\n", diff --git a/lib/clz_tab.c b/lib/clz_tab.c new file mode 100644 index 000000000000..7287b4a991a7 --- /dev/null +++ b/lib/clz_tab.c @@ -0,0 +1,18 @@ +const unsigned char __clz_tab[] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, +}; diff --git a/lib/digsig.c b/lib/digsig.c index fd2402f67f89..286d558033e2 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -34,14 +34,9 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg, unsigned long msglen, unsigned long modulus_bitlen, unsigned char *out, - unsigned long *outlen, - int *is_valid) + unsigned long *outlen) { unsigned long modulus_len, ps_len, i; - int result; - - /* default to invalid packet */ - *is_valid = 0; modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); @@ -50,39 +45,30 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg, return -EINVAL; /* separate encoded message */ - if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1)) { - result = -EINVAL; - goto bail; - } + if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1)) + return -EINVAL; for (i = 2; i < modulus_len - 1; i++) if (msg[i] != 0xFF) break; /* separator check */ - if (msg[i] != 0) { + if (msg[i] != 0) /* There was no octet with hexadecimal value 0x00 to separate ps from m. */ - result = -EINVAL; - goto bail; - } + return -EINVAL; ps_len = i - 2; if (*outlen < (msglen - (2 + ps_len + 1))) { *outlen = msglen - (2 + ps_len + 1); - result = -EOVERFLOW; - goto bail; + return -EOVERFLOW; } *outlen = (msglen - (2 + ps_len + 1)); memcpy(out, &msg[2 + ps_len + 1], *outlen); - /* valid packet */ - *is_valid = 1; - result = 0; -bail: - return result; + return 0; } /* @@ -96,7 +82,7 @@ static int digsig_verify_rsa(struct key *key, unsigned long len; unsigned long mlen, mblen; unsigned nret, l; - int valid, head, i; + int head, i; unsigned char *out1 = NULL, *out2 = NULL; MPI in = NULL, res = NULL, pkey[2]; uint8_t *p, *datap, *endp; @@ -105,6 +91,10 @@ static int digsig_verify_rsa(struct key *key, down_read(&key->sem); ukp = key->payload.data; + + if (ukp->datalen < sizeof(*pkh)) + goto err1; + pkh = (struct pubkey_hdr *)ukp->data; if (pkh->version != 1) @@ -117,18 +107,23 @@ static int digsig_verify_rsa(struct key *key, goto err1; datap = pkh->mpi; - endp = datap + ukp->datalen; + endp = ukp->data + ukp->datalen; + + err = -ENOMEM; for (i = 0; i < pkh->nmpi; i++) { unsigned int remaining = endp - datap; pkey[i] = mpi_read_from_buffer(datap, &remaining); + if (!pkey[i]) + goto err; datap += remaining; } mblen = mpi_get_nbits(pkey[0]); mlen = (mblen + 7)/8; - err = -ENOMEM; + if (mlen == 0) + goto err; out1 = kzalloc(mlen, GFP_KERNEL); if (!out1) @@ -167,10 +162,9 @@ static int digsig_verify_rsa(struct key *key, memset(out1, 0, head); memcpy(out1 + head, p, l); - err = -EINVAL; - pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len, &valid); + err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len); - if (valid && len == hlen) + if (!err && len == hlen) err = memcmp(out2, h, hlen); err: @@ -178,8 +172,8 @@ err: mpi_free(res); kfree(out1); kfree(out2); - mpi_free(pkey[0]); - mpi_free(pkey[1]); + while (--i >= 0) + mpi_free(pkey[i]); err1: up_read(&key->sem); diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h index b87487b40a8b..29f98624ef93 100644 --- a/lib/mpi/longlong.h +++ b/lib/mpi/longlong.h @@ -1200,18 +1200,40 @@ do { \ "r" ((USItype)(v)) \ : "%g1", "%g2" __AND_CLOBBER_CC) #define UMUL_TIME 39 /* 39 instructions */ -#endif -#ifndef udiv_qrnnd -#ifndef LONGLONG_STANDALONE +/* It's quite necessary to add this much assembler for the sparc. + The default udiv_qrnnd (in C) is more than 10 times slower! */ #define udiv_qrnnd(q, r, n1, n0, d) \ -do { USItype __r; \ - (q) = __udiv_qrnnd(&__r, (n1), (n0), (d)); \ - (r) = __r; \ -} while (0) - extern USItype __udiv_qrnnd(); -#define UDIV_TIME 140 -#endif /* LONGLONG_STANDALONE */ -#endif /* udiv_qrnnd */ + __asm__ ("! Inlined udiv_qrnnd\n\t" \ + "mov 32,%%g1\n\t" \ + "subcc %1,%2,%%g0\n\t" \ + "1: bcs 5f\n\t" \ + "addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \ + "sub %1,%2,%1 ! this kills msb of n\n\t" \ + "addx %1,%1,%1 ! so this can't give carry\n\t" \ + "subcc %%g1,1,%%g1\n\t" \ + "2: bne 1b\n\t" \ + "subcc %1,%2,%%g0\n\t" \ + "bcs 3f\n\t" \ + "addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \ + "b 3f\n\t" \ + "sub %1,%2,%1 ! this kills msb of n\n\t" \ + "4: sub %1,%2,%1\n\t" \ + "5: addxcc %1,%1,%1\n\t" \ + "bcc 2b\n\t" \ + "subcc %%g1,1,%%g1\n\t" \ + "! Got carry from n. Subtract next step to cancel this carry.\n\t" \ + "bne 4b\n\t" \ + "addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n\t" \ + "sub %1,%2,%1\n\t" \ + "3: xnor %0,0,%0\n\t" \ + "! End of inline udiv_qrnnd\n" \ + : "=&r" ((USItype)(q)), \ + "=&r" ((USItype)(r)) \ + : "r" ((USItype)(d)), \ + "1" ((USItype)(n1)), \ + "0" ((USItype)(n0)) : "%g1", "cc") +#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */ +#endif #endif /* __sparc__ */ /*************************************** diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c index 854c9c6da025..2f526627e4f5 100644 --- a/lib/mpi/mpi-bit.c +++ b/lib/mpi/mpi-bit.c @@ -21,25 +21,6 @@ #include "mpi-internal.h" #include "longlong.h" -const unsigned char __clz_tab[] = { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, -}; - #define A_LIMB_1 ((mpi_limb_t) 1) /**************** diff --git a/lib/mpi/mpi-div.c b/lib/mpi/mpi-div.c index c3087d1390ce..f68cbbb4d4a4 100644 --- a/lib/mpi/mpi-div.c +++ b/lib/mpi/mpi-div.c @@ -149,6 +149,9 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den) mpi_ptr_t marker[5]; int markidx = 0; + if (!dsize) + return -EINVAL; + memset(marker, 0, sizeof(marker)); /* Ensure space is enough for quotient and remainder. @@ -207,6 +210,8 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den) * numerator would be gradually overwritten by the quotient limbs. */ if (qp == np) { /* Copy NP object to temporary space. */ np = marker[markidx++] = mpi_alloc_limb_space(nsize); + if (!np) + goto nomem; MPN_COPY(np, qp, nsize); } } else /* Put quotient at top of remainder. */ diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c index b04a3cf80080..67f3e79af914 100644 --- a/lib/mpi/mpi-pow.c +++ b/lib/mpi/mpi-pow.c @@ -59,7 +59,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) ep = exp->d; if (!msize) - msize = 1 / msize; /* provoke a signal */ + return -EINVAL; if (!esize) { /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 716802b774ea..f26b41fcb48c 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -20,78 +20,15 @@ #include "mpi-internal.h" -#define DIM(v) (sizeof(v)/sizeof((v)[0])) #define MAX_EXTERN_MPI_BITS 16384 -static uint8_t asn[15] = /* Object ID is 1.3.14.3.2.26 */ -{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, - 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 -}; - -MPI do_encode_md(const void *sha_buffer, unsigned nbits) -{ - int nframe = (nbits + 7) / 8; - uint8_t *frame, *fr_pt; - int i = 0, n; - size_t asnlen = DIM(asn); - MPI a = MPI_NULL; - - if (SHA1_DIGEST_LENGTH + asnlen + 4 > nframe) - pr_info("MPI: can't encode a %d bit MD into a %d bits frame\n", - (int)(SHA1_DIGEST_LENGTH * 8), (int)nbits); - - /* We encode the MD in this way: - * - * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) - * - * PAD consists of FF bytes. - */ - frame = kmalloc(nframe, GFP_KERNEL); - if (!frame) - return MPI_NULL; - n = 0; - frame[n++] = 0; - frame[n++] = 1; /* block type */ - i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3; - - if (i <= 1) { - pr_info("MPI: message digest encoding failed\n"); - kfree(frame); - return a; - } - - memset(frame + n, 0xff, i); - n += i; - frame[n++] = 0; - memcpy(frame + n, &asn, asnlen); - n += asnlen; - memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH); - n += SHA1_DIGEST_LENGTH; - - i = nframe; - fr_pt = frame; - - if (n != nframe) { - printk - ("MPI: message digest encoding failed, frame length is wrong\n"); - kfree(frame); - return a; - } - - a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB); - mpi_set_buffer(a, frame, nframe, 0); - kfree(frame); - - return a; -} - MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) { const uint8_t *buffer = xbuffer; int i, j; unsigned nbits, nbytes, nlimbs, nread = 0; mpi_limb_t a; - MPI val = MPI_NULL; + MPI val = NULL; if (*ret_nread < 2) goto leave; @@ -108,7 +45,7 @@ MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; val = mpi_alloc(nlimbs); if (!val) - return MPI_NULL; + return NULL; i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; i %= BYTES_PER_MPI_LIMB; val->nbits = nbits; @@ -212,30 +149,6 @@ int mpi_fromstr(MPI val, const char *str) EXPORT_SYMBOL_GPL(mpi_fromstr); /**************** - * Special function to get the low 8 bytes from an mpi. - * This can be used as a keyid; KEYID is an 2 element array. - * Return the low 4 bytes. - */ -u32 mpi_get_keyid(const MPI a, u32 *keyid) -{ -#if BYTES_PER_MPI_LIMB == 4 - if (keyid) { - keyid[0] = a->nlimbs >= 2 ? a->d[1] : 0; - keyid[1] = a->nlimbs >= 1 ? a->d[0] : 0; - } - return a->nlimbs >= 1 ? a->d[0] : 0; -#elif BYTES_PER_MPI_LIMB == 8 - if (keyid) { - keyid[0] = a->nlimbs ? (u32) (a->d[0] >> 32) : 0; - keyid[1] = a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0; - } - return a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0; -#else -#error Make this function work with other LIMB sizes -#endif -} - -/**************** * Return an allocated buffer with the MPI (msb first). * NBYTES receives the length of this buffer. Caller must free the * return string (This function does return a 0 byte buffer with NBYTES diff --git a/lib/mpi/mpih-div.c b/lib/mpi/mpih-div.c index 87ede162dfab..cde1aaec18da 100644 --- a/lib/mpi/mpih-div.c +++ b/lib/mpi/mpih-div.c @@ -217,6 +217,10 @@ mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs, case 0: /* We are asked to divide by zero, so go ahead and do it! (To make the compiler not remove this statement, return the value.) */ + /* + * existing clients of this function have been modified + * not to call it with dsize == 0, so this should not happen + */ return 1 / dsize; case 1: diff --git a/lib/mpi/mpiutil.c b/lib/mpi/mpiutil.c index eefc55d6b7f5..26e4ed31e256 100644 --- a/lib/mpi/mpiutil.c +++ b/lib/mpi/mpiutil.c @@ -58,6 +58,9 @@ mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs) { size_t len = nlimbs * sizeof(mpi_limb_t); + if (!len) + return NULL; + return kmalloc(len, GFP_KERNEL); } @@ -135,7 +138,7 @@ int mpi_copy(MPI *copied, const MPI a) size_t i; MPI b; - *copied = MPI_NULL; + *copied = NULL; if (a) { b = mpi_alloc(a->nlimbs); diff --git a/mm/compaction.c b/mm/compaction.c index 71a58f67f481..bd939a574b84 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -313,6 +313,19 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, } else if (!locked) spin_lock_irq(&zone->lru_lock); + /* + * migrate_pfn does not necessarily start aligned to a + * pageblock. Ensure that pfn_valid is called when moving + * into a new MAX_ORDER_NR_PAGES range in case of large + * memory holes within the zone + */ + if ((low_pfn & (MAX_ORDER_NR_PAGES - 1)) == 0) { + if (!pfn_valid(low_pfn)) { + low_pfn += MAX_ORDER_NR_PAGES - 1; + continue; + } + } + if (!pfn_valid_within(low_pfn)) continue; nr_scanned++; diff --git a/mm/filemap.c b/mm/filemap.c index 97f49ed35bd2..b66275757c28 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1400,15 +1400,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long seg = 0; size_t count; loff_t *ppos = &iocb->ki_pos; - struct blk_plug plug; count = 0; retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); if (retval) return retval; - blk_start_plug(&plug); - /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ if (filp->f_flags & O_DIRECT) { loff_t size; @@ -1424,8 +1421,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, retval = filemap_write_and_wait_range(mapping, pos, pos + iov_length(iov, nr_segs) - 1); if (!retval) { + struct blk_plug plug; + + blk_start_plug(&plug); retval = mapping->a_ops->direct_IO(READ, iocb, iov, pos, nr_segs); + blk_finish_plug(&plug); } if (retval > 0) { *ppos = pos + retval; @@ -1481,7 +1482,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, break; } out: - blk_finish_plug(&plug); return retval; } EXPORT_SYMBOL(generic_file_aio_read); diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index f91b2f687343..a4eb31132229 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c @@ -263,7 +263,12 @@ found: xip_pfn); if (err == -ENOMEM) return VM_FAULT_OOM; - BUG_ON(err); + /* + * err == -EBUSY is fine, we've raced against another thread + * that faulted-in the same page + */ + if (err != -EBUSY) + BUG_ON(err); return VM_FAULT_NOPAGE; } else { int err, ret = VM_FAULT_OOM; diff --git a/mm/kmemleak.c b/mm/kmemleak.c index c833addd94d7..45eb6217bf38 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1036,7 +1036,7 @@ void __ref kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp) { pr_debug("%s(0x%p)\n", __func__, ptr); - if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr)) + if (atomic_read(&kmemleak_enabled) && ptr && size && !IS_ERR(ptr)) add_scan_area((unsigned long)ptr, size, gfp); else if (atomic_read(&kmemleak_early_log)) log_early(KMEMLEAK_SCAN_AREA, ptr, size, 0); @@ -1757,6 +1757,7 @@ void __init kmemleak_init(void) #ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF if (!kmemleak_skip_disable) { + atomic_set(&kmemleak_early_log, 0); kmemleak_disable(); return; } diff --git a/mm/memblock.c b/mm/memblock.c index 2f55f19b7c86..77b5f227e1d8 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -106,14 +106,17 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t start, if (end == MEMBLOCK_ALLOC_ACCESSIBLE) end = memblock.current_limit; - /* adjust @start to avoid underflow and allocating the first page */ - start = max3(start, size, (phys_addr_t)PAGE_SIZE); + /* avoid allocating the first page */ + start = max_t(phys_addr_t, start, PAGE_SIZE); end = max(start, end); for_each_free_mem_range_reverse(i, nid, &this_start, &this_end, NULL) { this_start = clamp(this_start, start, end); this_end = clamp(this_end, start, end); + if (this_end < size) + continue; + cand = round_down(this_end - size, align); if (cand >= this_start) return cand; diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 4baddbae94cc..6728a7ae6f2d 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -379,7 +379,7 @@ static void mem_cgroup_put(struct mem_cgroup *memcg); static bool mem_cgroup_is_root(struct mem_cgroup *memcg); void sock_update_memcg(struct sock *sk) { - if (static_branch(&memcg_socket_limit_enabled)) { + if (mem_cgroup_sockets_enabled) { struct mem_cgroup *memcg; BUG_ON(!sk->sk_prot->proto_cgroup); @@ -411,7 +411,7 @@ EXPORT_SYMBOL(sock_update_memcg); void sock_release_memcg(struct sock *sk) { - if (static_branch(&memcg_socket_limit_enabled) && sk->sk_cgrp) { + if (mem_cgroup_sockets_enabled && sk->sk_cgrp) { struct mem_cgroup *memcg; WARN_ON(!sk->sk_cgrp->memcg); memcg = sk->sk_cgrp->memcg; @@ -776,7 +776,8 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page) /* threshold event is triggered in finer grain than soft limit */ if (unlikely(mem_cgroup_event_ratelimit(memcg, MEM_CGROUP_TARGET_THRESH))) { - bool do_softlimit, do_numainfo; + bool do_softlimit; + bool do_numainfo __maybe_unused; do_softlimit = mem_cgroup_event_ratelimit(memcg, MEM_CGROUP_TARGET_SOFTLIMIT); diff --git a/mm/migrate.c b/mm/migrate.c index 9871a56d82c3..df141f60289e 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -445,7 +445,6 @@ void migrate_page_copy(struct page *newpage, struct page *page) ClearPageSwapCache(page); ClearPagePrivate(page); set_page_private(page, 0); - page->mapping = NULL; /* * If any waiters have accumulated on the new page then @@ -667,6 +666,7 @@ static int move_to_new_page(struct page *newpage, struct page *page, } else { if (remap_swapcache) remove_migration_ptes(page, newpage); + page->mapping = NULL; } unlock_page(newpage); diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index e920aa3ce104..c20ff48994c2 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c @@ -298,23 +298,18 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec, goto free_proc_pages; } - task_lock(task); - if (__ptrace_may_access(task, PTRACE_MODE_ATTACH)) { - task_unlock(task); - rc = -EPERM; - goto put_task_struct; - } - mm = task->mm; - - if (!mm || (task->flags & PF_KTHREAD)) { - task_unlock(task); - rc = -EINVAL; + mm = mm_access(task, PTRACE_MODE_ATTACH); + if (!mm || IS_ERR(mm)) { + rc = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH; + /* + * Explicitly map EACCES to EPERM as EPERM is a more a + * appropriate error code for process_vw_readv/writev + */ + if (rc == -EACCES) + rc = -EPERM; goto put_task_struct; } - atomic_inc(&mm->mm_users); - task_unlock(task); - for (i = 0; i < riovcnt && iov_l_curr_idx < liovcnt; i++) { rc = process_vm_rw_single_vec( (unsigned long)rvec[i].iov_base, rvec[i].iov_len, diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 845da3ee56a0..9de93714213a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -55,7 +55,7 @@ #define AUTO_OFF_TIMEOUT 2000 -int enable_hs; +bool enable_hs; static void hci_rx_work(struct work_struct *work); static void hci_cmd_work(struct work_struct *work); diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 673728add60b..82c57069415f 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -59,8 +59,6 @@ struct cfcnfg *get_cfcnfg(struct net *net) { struct caif_net *caifn; caifn = net_generic(net, caif_net_id); - if (!caifn) - return NULL; return caifn->cfg; } EXPORT_SYMBOL(get_cfcnfg); @@ -69,8 +67,6 @@ static struct caif_device_entry_list *caif_device_list(struct net *net) { struct caif_net *caifn; caifn = net_generic(net, caif_net_id); - if (!caifn) - return NULL; return &caifn->caifdevs; } @@ -99,8 +95,6 @@ static struct caif_device_entry *caif_device_alloc(struct net_device *dev) struct caif_device_entry *caifd; caifdevs = caif_device_list(dev_net(dev)); - if (!caifdevs) - return NULL; caifd = kzalloc(sizeof(*caifd), GFP_KERNEL); if (!caifd) @@ -120,8 +114,6 @@ static struct caif_device_entry *caif_get(struct net_device *dev) struct caif_device_entry_list *caifdevs = caif_device_list(dev_net(dev)); struct caif_device_entry *caifd; - if (!caifdevs) - return NULL; list_for_each_entry_rcu(caifd, &caifdevs->list, list) { if (caifd->netdev == dev) @@ -321,8 +313,6 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, struct caif_device_entry_list *caifdevs; caifdevs = caif_device_list(dev_net(dev)); - if (!cfg || !caifdevs) - return; caifd = caif_device_alloc(dev); if (!caifd) return; @@ -374,8 +364,6 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, cfg = get_cfcnfg(dev_net(dev)); caifdevs = caif_device_list(dev_net(dev)); - if (!cfg || !caifdevs) - return 0; caifd = caif_get(dev); if (caifd == NULL && dev->type != ARPHRD_CAIF) @@ -507,9 +495,6 @@ static struct notifier_block caif_device_notifier = { static int caif_init_net(struct net *net) { struct caif_net *caifn = net_generic(net, caif_net_id); - if (WARN_ON(!caifn)) - return -EINVAL; - INIT_LIST_HEAD(&caifn->caifdevs.list); mutex_init(&caifn->caifdevs.lock); @@ -527,9 +512,6 @@ static void caif_exit_net(struct net *net) caif_device_list(net); struct cfcnfg *cfg = get_cfcnfg(net); - if (!cfg || !caifdevs) - return; - rtnl_lock(); mutex_lock(&caifdevs->lock); @@ -569,7 +551,7 @@ static int __init caif_device_init(void) { int result; - result = register_pernet_device(&caif_net_ops); + result = register_pernet_subsys(&caif_net_ops); if (result) return result; @@ -582,7 +564,7 @@ static int __init caif_device_init(void) static void __exit caif_device_exit(void) { - unregister_pernet_device(&caif_net_ops); + unregister_pernet_subsys(&caif_net_ops); unregister_netdevice_notifier(&caif_device_notifier); dev_remove_pack(&caif_packet_type); } diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index 598aafb4cb51..ba9cfd47778a 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c @@ -309,7 +309,6 @@ int caif_connect_client(struct net *net, struct caif_connect_request *conn_req, int err; struct cfctrl_link_param param; struct cfcnfg *cfg = get_cfcnfg(net); - caif_assert(cfg != NULL); rcu_read_lock(); err = caif_connect_req_to_link_param(cfg, conn_req, ¶m); diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 97f70e50ad3b..761ad9d6cc3b 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -85,8 +85,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) } else { pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); memcpy(&client->fsid, fsid, sizeof(*fsid)); - ceph_debugfs_client_init(client); - client->have_fsid = true; } return 0; } diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 0b62deae42bd..1845cde26227 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -8,8 +8,8 @@ #include <linux/ceph/mon_client.h> #include <linux/ceph/libceph.h> +#include <linux/ceph/debugfs.h> #include <linux/ceph/decode.h> - #include <linux/ceph/auth.h> /* @@ -340,8 +340,19 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, client->monc.monmap = monmap; kfree(old); + if (!client->have_fsid) { + client->have_fsid = true; + mutex_unlock(&monc->mutex); + /* + * do debugfs initialization without mutex to avoid + * creating a locking dependency + */ + ceph_debugfs_client_init(client); + goto out_unlocked; + } out: mutex_unlock(&monc->mutex); +out_unlocked: wake_up_all(&client->auth_wq); } diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 921aa2b4b415..369b41894527 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1311,6 +1311,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_GRXCSUM: case ETHTOOL_GTXCSUM: case ETHTOOL_GSG: + case ETHTOOL_GSSET_INFO: case ETHTOOL_GSTRINGS: case ETHTOOL_GTSO: case ETHTOOL_GPERMADDR: diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 0985b9b14b80..a225089df5b6 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1,4 +1,5 @@ #include <linux/skbuff.h> +#include <linux/export.h> #include <linux/ip.h> #include <linux/ipv6.h> #include <linux/if_vlan.h> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index aefcd7acbffa..0e950fda9a0a 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -30,6 +30,20 @@ EXPORT_SYMBOL(init_net); #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ +static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS; + +static struct net_generic *net_alloc_generic(void) +{ + struct net_generic *ng; + size_t generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]); + + ng = kzalloc(generic_size, GFP_KERNEL); + if (ng) + ng->len = max_gen_ptrs; + + return ng; +} + static int net_assign_generic(struct net *net, int id, void *data) { struct net_generic *ng, *old_ng; @@ -43,8 +57,7 @@ static int net_assign_generic(struct net *net, int id, void *data) if (old_ng->len >= id) goto assign; - ng = kzalloc(sizeof(struct net_generic) + - id * sizeof(void *), GFP_KERNEL); + ng = net_alloc_generic(); if (ng == NULL) return -ENOMEM; @@ -59,7 +72,6 @@ static int net_assign_generic(struct net *net, int id, void *data) * the old copy for kfree after a grace period. */ - ng->len = id; memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*)); rcu_assign_pointer(net->gen, ng); @@ -161,18 +173,6 @@ out_undo: goto out; } -static struct net_generic *net_alloc_generic(void) -{ - struct net_generic *ng; - size_t generic_size = sizeof(struct net_generic) + - INITIAL_NET_GEN_PTRS * sizeof(void *); - - ng = kzalloc(generic_size, GFP_KERNEL); - if (ng) - ng->len = INITIAL_NET_GEN_PTRS; - - return ng; -} #ifdef CONFIG_NET_NS static struct kmem_cache *net_cachep; @@ -483,6 +483,7 @@ again: } return error; } + max_gen_ptrs = max_t(unsigned int, max_gen_ptrs, *ops->id); } error = __register_pernet_operations(list, ops); if (error) { diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 65f80c7b1656..4d8ce93cd503 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -767,8 +767,8 @@ done: return i; } -static unsigned long num_arg(const char __user * user_buffer, - unsigned long maxlen, unsigned long *num) +static long num_arg(const char __user *user_buffer, unsigned long maxlen, + unsigned long *num) { int i; *num = 0; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index f16444bc6cbb..65aebd450027 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1509,6 +1509,9 @@ errout: if (send_addr_notify) call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + min_ifinfo_dump_size = max_t(u16, if_nlmsg_size(dev), + min_ifinfo_dump_size); + return err; } diff --git a/net/core/sock.c b/net/core/sock.c index 5c5af9988f94..3e81fd2e3c75 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1827,7 +1827,7 @@ suppress_allocation: /* Alas. Undo changes. */ sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM; - sk_memory_allocated_sub(sk, amt, parent_status); + sk_memory_allocated_sub(sk, amt); return 0; } @@ -1840,7 +1840,7 @@ EXPORT_SYMBOL(__sk_mem_schedule); void __sk_mem_reclaim(struct sock *sk) { sk_memory_allocated_sub(sk, - sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT, 0); + sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT); sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1; if (sk_under_memory_pressure(sk) && diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 2e4e24476c4c..19d66cefd7d3 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -123,11 +123,14 @@ again: smallest_size = tb->num_owners; smallest_rover = rover; if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) { - spin_unlock(&head->lock); snum = smallest_rover; - goto have_snum; + goto tb_found; } } + if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) { + snum = rover; + goto tb_found; + } goto next; } break; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 2b53a1f7abf6..6b3ca5ba4450 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -422,6 +422,10 @@ static struct ip_tunnel *ipgre_tunnel_locate(struct net *net, if (register_netdevice(dev) < 0) goto failed_free; + /* Can use a lockless transmit, unless we generate output sequences */ + if (!(nt->parms.o_flags & GRE_SEQ)) + dev->features |= NETIF_F_LLTX; + dev_hold(dev); ipgre_tunnel_link(ign, nt); return nt; diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 3569d8ecaeac..6afc807ee2ad 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -216,7 +216,6 @@ static const struct snmp_mib snmp4_net_list[] = { SNMP_MIB_ITEM("TCPPartialUndo", LINUX_MIB_TCPPARTIALUNDO), SNMP_MIB_ITEM("TCPDSACKUndo", LINUX_MIB_TCPDSACKUNDO), SNMP_MIB_ITEM("TCPLossUndo", LINUX_MIB_TCPLOSSUNDO), - SNMP_MIB_ITEM("TCPLoss", LINUX_MIB_TCPLOSS), SNMP_MIB_ITEM("TCPLostRetransmit", LINUX_MIB_TCPLOSTRETRANSMIT), SNMP_MIB_ITEM("TCPRenoFailures", LINUX_MIB_TCPRENOFAILURES), SNMP_MIB_ITEM("TCPSackFailures", LINUX_MIB_TCPSACKFAILURES), diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 4aa7e9dc0cbb..4cb9cd2f2c39 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -814,6 +814,7 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) net->ipv4.sysctl_rt_cache_rebuild_count = 4; + tcp_init_mem(net); limit = nr_free_buffer_pages() / 8; limit = max(limit, 128UL); net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 9bcdec3ad772..06373b4a449a 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3216,6 +3216,16 @@ static int __init set_thash_entries(char *str) } __setup("thash_entries=", set_thash_entries); +void tcp_init_mem(struct net *net) +{ + /* Set per-socket limits to no more than 1/128 the pressure threshold */ + unsigned long limit = nr_free_buffer_pages() / 8; + limit = max(limit, 128UL); + net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3; + net->ipv4.sysctl_tcp_mem[1] = limit; + net->ipv4.sysctl_tcp_mem[2] = net->ipv4.sysctl_tcp_mem[0] * 2; +} + void __init tcp_init(void) { struct sk_buff *skb = NULL; @@ -3276,9 +3286,9 @@ void __init tcp_init(void) sysctl_tcp_max_orphans = cnt / 2; sysctl_max_syn_backlog = max(128, cnt / 256); - /* Set per-socket limits to no more than 1/128 the pressure threshold */ - limit = ((unsigned long)init_net.ipv4.sysctl_tcp_mem[1]) - << (PAGE_SHIFT - 7); + tcp_init_mem(&init_net); + limit = nr_free_buffer_pages() / 8; + limit = max(limit, 128UL); max_share = min(4UL*1024*1024, limit); sysctl_tcp_wmem[0] = SK_MEM_QUANTUM; diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c index 6187eb4d1dcf..f45e1c242440 100644 --- a/net/ipv4/tcp_bic.c +++ b/net/ipv4/tcp_bic.c @@ -63,7 +63,6 @@ static inline void bictcp_reset(struct bictcp *ca) { ca->cnt = 0; ca->last_max_cwnd = 0; - ca->loss_cwnd = 0; ca->last_cwnd = 0; ca->last_time = 0; ca->epoch_start = 0; @@ -72,7 +71,11 @@ static inline void bictcp_reset(struct bictcp *ca) static void bictcp_init(struct sock *sk) { - bictcp_reset(inet_csk_ca(sk)); + struct bictcp *ca = inet_csk_ca(sk); + + bictcp_reset(ca); + ca->loss_cwnd = 0; + if (initial_ssthresh) tcp_sk(sk)->snd_ssthresh = initial_ssthresh; } @@ -127,7 +130,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) } /* if in slow start or link utilization is very low */ - if (ca->loss_cwnd == 0) { + if (ca->last_max_cwnd == 0) { if (ca->cnt > 20) /* increase cwnd 5% per RTT */ ca->cnt = 20; } @@ -185,7 +188,7 @@ static u32 bictcp_undo_cwnd(struct sock *sk) { const struct tcp_sock *tp = tcp_sk(sk); const struct bictcp *ca = inet_csk_ca(sk); - return max(tp->snd_cwnd, ca->last_max_cwnd); + return max(tp->snd_cwnd, ca->loss_cwnd); } static void bictcp_state(struct sock *sk, u8 new_state) diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index f376b05cca81..a9077f441cb2 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -107,7 +107,6 @@ static inline void bictcp_reset(struct bictcp *ca) { ca->cnt = 0; ca->last_max_cwnd = 0; - ca->loss_cwnd = 0; ca->last_cwnd = 0; ca->last_time = 0; ca->bic_origin_point = 0; @@ -142,7 +141,10 @@ static inline void bictcp_hystart_reset(struct sock *sk) static void bictcp_init(struct sock *sk) { - bictcp_reset(inet_csk_ca(sk)); + struct bictcp *ca = inet_csk_ca(sk); + + bictcp_reset(ca); + ca->loss_cwnd = 0; if (hystart) bictcp_hystart_reset(sk); @@ -275,7 +277,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) * The initial growth of cubic function may be too conservative * when the available bandwidth is still unknown. */ - if (ca->loss_cwnd == 0 && ca->cnt > 20) + if (ca->last_max_cwnd == 0 && ca->cnt > 20) ca->cnt = 20; /* increase cwnd 5% per RTT */ /* TCP Friendly */ @@ -342,7 +344,7 @@ static u32 bictcp_undo_cwnd(struct sock *sk) { struct bictcp *ca = inet_csk_ca(sk); - return max(tcp_sk(sk)->snd_cwnd, ca->last_max_cwnd); + return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd); } static void bictcp_state(struct sock *sk, u8 new_state) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 2877c3e09587..976034f82320 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -105,7 +105,6 @@ int sysctl_tcp_abc __read_mostly; #define FLAG_SYN_ACKED 0x10 /* This ACK acknowledged SYN. */ #define FLAG_DATA_SACKED 0x20 /* New SACK. */ #define FLAG_ECE 0x40 /* ECE in this ACK */ -#define FLAG_DATA_LOST 0x80 /* SACK detected data lossage. */ #define FLAG_SLOWPATH 0x100 /* Do not skip RFC checks for window update.*/ #define FLAG_ONLY_ORIG_SACKED 0x200 /* SACKs only non-rexmit sent before RTO */ #define FLAG_SND_UNA_ADVANCED 0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */ @@ -1040,13 +1039,11 @@ static void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, * These 6 states form finite state machine, controlled by the following events: * 1. New ACK (+SACK) arrives. (tcp_sacktag_write_queue()) * 2. Retransmission. (tcp_retransmit_skb(), tcp_xmit_retransmit_queue()) - * 3. Loss detection event of one of three flavors: + * 3. Loss detection event of two flavors: * A. Scoreboard estimator decided the packet is lost. * A'. Reno "three dupacks" marks head of queue lost. - * A''. Its FACK modfication, head until snd.fack is lost. - * B. SACK arrives sacking data transmitted after never retransmitted - * hole was sent out. - * C. SACK arrives sacking SND.NXT at the moment, when the + * A''. Its FACK modification, head until snd.fack is lost. + * B. SACK arrives sacking SND.NXT at the moment, when the * segment was retransmitted. * 4. D-SACK added new rule: D-SACK changes any tag to S. * @@ -1153,7 +1150,7 @@ static int tcp_is_sackblock_valid(struct tcp_sock *tp, int is_dsack, } /* Check for lost retransmit. This superb idea is borrowed from "ratehalving". - * Event "C". Later note: FACK people cheated me again 8), we have to account + * Event "B". Later note: FACK people cheated me again 8), we have to account * for reordering! Ugly, but should help. * * Search retransmitted skbs from write_queue that were sent when snd_nxt was @@ -1844,10 +1841,6 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb, if (found_dup_sack && ((i + 1) == first_sack_index)) next_dup = &sp[i + 1]; - /* Event "B" in the comment above. */ - if (after(end_seq, tp->high_seq)) - state.flag |= FLAG_DATA_LOST; - /* Skip too early cached blocks */ while (tcp_sack_cache_ok(tp, cache) && !before(start_seq, cache->end_seq)) @@ -2515,8 +2508,11 @@ static void tcp_timeout_skbs(struct sock *sk) tcp_verify_left_out(tp); } -/* Mark head of queue up as lost. With RFC3517 SACK, the packets is - * is against sacked "cnt", otherwise it's against facked "cnt" +/* Detect loss in event "A" above by marking head of queue up as lost. + * For FACK or non-SACK(Reno) senders, the first "packets" number of segments + * are considered lost. For RFC3517 SACK, a segment is considered lost if it + * has at least tp->reordering SACKed seqments above it; "packets" refers to + * the maximum SACKed segments to pass before reaching this limit. */ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) { @@ -2525,6 +2521,8 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) int cnt, oldcnt; int err; unsigned int mss; + /* Use SACK to deduce losses of new sequences sent during recovery */ + const u32 loss_high = tcp_is_sack(tp) ? tp->snd_nxt : tp->high_seq; WARN_ON(packets > tp->packets_out); if (tp->lost_skb_hint) { @@ -2546,7 +2544,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) tp->lost_skb_hint = skb; tp->lost_cnt_hint = cnt; - if (after(TCP_SKB_CB(skb)->end_seq, tp->high_seq)) + if (after(TCP_SKB_CB(skb)->end_seq, loss_high)) break; oldcnt = cnt; @@ -3033,19 +3031,10 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, if (tcp_check_sack_reneging(sk, flag)) return; - /* C. Process data loss notification, provided it is valid. */ - if (tcp_is_fack(tp) && (flag & FLAG_DATA_LOST) && - before(tp->snd_una, tp->high_seq) && - icsk->icsk_ca_state != TCP_CA_Open && - tp->fackets_out > tp->reordering) { - tcp_mark_head_lost(sk, tp->fackets_out - tp->reordering, 0); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSS); - } - - /* D. Check consistency of the current state. */ + /* C. Check consistency of the current state. */ tcp_verify_left_out(tp); - /* E. Check state exit conditions. State can be terminated + /* D. Check state exit conditions. State can be terminated * when high_seq is ACKed. */ if (icsk->icsk_ca_state == TCP_CA_Open) { WARN_ON(tp->retrans_out != 0); @@ -3077,7 +3066,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, } } - /* F. Process state. */ + /* E. Process state. */ switch (icsk->icsk_ca_state) { case TCP_CA_Recovery: if (!(flag & FLAG_SND_UNA_ADVANCED)) { diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1eb4ad57670e..337ba4cca052 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -631,7 +631,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) arg.iov[0].iov_len = sizeof(rep.th); #ifdef CONFIG_TCP_MD5SIG - key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr) : NULL; + key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr) : NULL; if (key) { rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8c8de2780c7a..4ff3b6dc74fc 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1141,11 +1141,9 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) sk_mem_uncharge(sk, len); sock_set_flag(sk, SOCK_QUEUE_SHRUNK); - /* Any change of skb->len requires recalculation of tso - * factor and mss. - */ + /* Any change of skb->len requires recalculation of tso factor. */ if (tcp_skb_pcount(skb) > 1) - tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk)); + tcp_set_skb_tso_segs(sk, skb, tcp_skb_mss(skb)); return 0; } diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index a225d5ee3c2f..c02280a4d126 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -502,29 +502,31 @@ static void addrconf_forward_change(struct net *net, __s32 newf) rcu_read_unlock(); } -static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) +static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) { struct net *net; + int old; + + if (!rtnl_trylock()) + return restart_syscall(); net = (struct net *)table->extra2; - if (p == &net->ipv6.devconf_dflt->forwarding) - return 0; + old = *p; + *p = newf; - if (!rtnl_trylock()) { - /* Restore the original values before restarting */ - *p = old; - return restart_syscall(); + if (p == &net->ipv6.devconf_dflt->forwarding) { + rtnl_unlock(); + return 0; } if (p == &net->ipv6.devconf_all->forwarding) { - __s32 newf = net->ipv6.devconf_all->forwarding; net->ipv6.devconf_dflt->forwarding = newf; addrconf_forward_change(net, newf); - } else if ((!*p) ^ (!old)) + } else if ((!newf) ^ (!old)) dev_forward_change((struct inet6_dev *)table->extra1); rtnl_unlock(); - if (*p) + if (newf) rt6_purge_dflt_routers(net); return 1; } @@ -4260,9 +4262,17 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, int *valp = ctl->data; int val = *valp; loff_t pos = *ppos; + ctl_table lctl; int ret; - ret = proc_dointvec(ctl, write, buffer, lenp, ppos); + /* + * ctl->data points to idev->cnf.forwarding, we should + * not modify it until we get the rtnl lock. + */ + lctl = *ctl; + lctl.data = &val; + + ret = proc_dointvec(&lctl, write, buffer, lenp, ppos); if (write) ret = addrconf_fixup_forwarding(ctl, valp, val); @@ -4300,26 +4310,27 @@ static void addrconf_disable_change(struct net *net, __s32 newf) rcu_read_unlock(); } -static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) +static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf) { struct net *net; + int old; + + if (!rtnl_trylock()) + return restart_syscall(); net = (struct net *)table->extra2; + old = *p; + *p = newf; - if (p == &net->ipv6.devconf_dflt->disable_ipv6) + if (p == &net->ipv6.devconf_dflt->disable_ipv6) { + rtnl_unlock(); return 0; - - if (!rtnl_trylock()) { - /* Restore the original values before restarting */ - *p = old; - return restart_syscall(); } if (p == &net->ipv6.devconf_all->disable_ipv6) { - __s32 newf = net->ipv6.devconf_all->disable_ipv6; net->ipv6.devconf_dflt->disable_ipv6 = newf; addrconf_disable_change(net, newf); - } else if ((!*p) ^ (!old)) + } else if ((!newf) ^ (!old)) dev_disable_change((struct inet6_dev *)table->extra1); rtnl_unlock(); @@ -4333,9 +4344,17 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write, int *valp = ctl->data; int val = *valp; loff_t pos = *ppos; + ctl_table lctl; int ret; - ret = proc_dointvec(ctl, write, buffer, lenp, ppos); + /* + * ctl->data points to idev->cnf.disable_ipv6, we should + * not modify it until we get the rtnl lock. + */ + lctl = *ctl; + lctl.data = &val; + + ret = proc_dointvec(&lctl, write, buffer, lenp, ppos); if (write) ret = addrconf_disable_ipv6(ctl, valp, val); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 906c7ca43542..3edd05ae4388 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1083,7 +1083,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) #ifdef CONFIG_TCP_MD5SIG if (sk) - key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr); + key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr); #endif if (th->ack) diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index d21e7ebd91ca..55670ec3cd0f 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -393,11 +393,6 @@ static int l2tp_ip_backlog_recv(struct sock *sk, struct sk_buff *skb) { int rc; - if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) - goto drop; - - nf_reset(skb); - /* Charge it to the socket, dropping if the queue is full. */ rc = sock_queue_rcv_skb(sk, skb); if (rc < 0) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index a18e6c3d36e3..b9bef2c75026 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -713,6 +713,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb = NULL; struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); + unsigned long cpu_flags; size_t copied = 0; u32 peek_seq = 0; u32 *seq; @@ -838,7 +839,9 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, goto copy_uaddr; if (!(flags & MSG_PEEK)) { + spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags); sk_eat_skb(sk, skb, 0); + spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags); *seq = 0; } @@ -859,7 +862,9 @@ copy_uaddr: llc_cmsg_rcv(msg, skb); if (!(flags & MSG_PEEK)) { + spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags); sk_eat_skb(sk, skb, 0); + spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags); *seq = 0; } diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 38e6101190d9..59edcd95a58d 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -225,9 +225,9 @@ KEY_OPS(key); key, &key_##name##_ops); void ieee80211_debugfs_key_add(struct ieee80211_key *key) - { +{ static int keycount; - char buf[50]; + char buf[100]; struct sta_info *sta; if (!key->local->debugfs.keys) @@ -244,7 +244,8 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) sta = key->sta; if (sta) { - sprintf(buf, "../../stations/%pM", sta->sta.addr); + sprintf(buf, "../../netdev:%s/stations/%pM", + sta->sdata->name, sta->sta.addr); key->debugfs.stalink = debugfs_create_symlink("station", key->debugfs.dir, buf); } diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index b3d76b756cd5..a4643969a13b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -106,6 +106,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; + local->oper_channel = chan; channel_type = ifibss->channel_type; if (channel_type > NL80211_CHAN_HT20 && !cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index e47768cb8cb3..01a21c2f6ab3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1314,6 +1314,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) continue; } /* count everything else */ + sdata->vif.bss_conf.idle = false; count++; } diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 73abb7524b2c..54df1b2bafd2 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -119,12 +119,12 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) + sizeof(mgmt->u.action.u.mesh_action); - skb = dev_alloc_skb(local->hw.extra_tx_headroom + + skb = dev_alloc_skb(local->tx_headroom + hdr_len + 2 + 37); /* max HWMP IE */ if (!skb) return -1; - skb_reserve(skb, local->hw.extra_tx_headroom); + skb_reserve(skb, local->tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); memset(mgmt, 0, hdr_len); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | @@ -250,12 +250,12 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, if (time_before(jiffies, ifmsh->next_perr)) return -EAGAIN; - skb = dev_alloc_skb(local->hw.extra_tx_headroom + + skb = dev_alloc_skb(local->tx_headroom + hdr_len + 2 + 15 /* PERR IE */); if (!skb) return -1; - skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom); + skb_reserve(skb, local->tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); memset(mgmt, 0, hdr_len); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 41ef1b476442..a17251730b9e 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -172,7 +172,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) + sizeof(mgmt->u.action.u.self_prot); - skb = dev_alloc_skb(local->hw.extra_tx_headroom + + skb = dev_alloc_skb(local->tx_headroom + hdr_len + 2 + /* capability info */ 2 + /* AID */ @@ -186,7 +186,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, sdata->u.mesh.ie_len); if (!skb) return -1; - skb_reserve(skb, local->hw.extra_tx_headroom); + skb_reserve(skb, local->tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); memset(mgmt, 0, hdr_len); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ecb4c84c1bb3..295be92f7c77 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2750,7 +2750,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - struct ieee80211_work *wk; u8 bssid[ETH_ALEN]; bool assoc_bss = false; @@ -2763,30 +2762,47 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, assoc_bss = true; } else { bool not_auth_yet = false; + struct ieee80211_work *tmp, *wk = NULL; mutex_unlock(&ifmgd->mtx); mutex_lock(&local->mtx); - list_for_each_entry(wk, &local->work_list, list) { - if (wk->sdata != sdata) + list_for_each_entry(tmp, &local->work_list, list) { + if (tmp->sdata != sdata) continue; - if (wk->type != IEEE80211_WORK_DIRECT_PROBE && - wk->type != IEEE80211_WORK_AUTH && - wk->type != IEEE80211_WORK_ASSOC && - wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) + if (tmp->type != IEEE80211_WORK_DIRECT_PROBE && + tmp->type != IEEE80211_WORK_AUTH && + tmp->type != IEEE80211_WORK_ASSOC && + tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) continue; - if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) + if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN)) continue; - not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE; - list_del_rcu(&wk->list); - free_work(wk); + not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE; + list_del_rcu(&tmp->list); + synchronize_rcu(); + wk = tmp; break; } mutex_unlock(&local->mtx); + if (wk && wk->type == IEEE80211_WORK_ASSOC) { + /* clean up dummy sta & TX sync */ + sta_info_destroy_addr(wk->sdata, wk->filter_ta); + if (wk->assoc.synced) + drv_finish_tx_sync(local, wk->sdata, + wk->filter_ta, + IEEE80211_TX_SYNC_ASSOC); + } else if (wk && wk->type == IEEE80211_WORK_AUTH) { + if (wk->probe_auth.synced) + drv_finish_tx_sync(local, wk->sdata, + wk->filter_ta, + IEEE80211_TX_SYNC_AUTH); + } + kfree(wk); + /* * If somebody requests authentication and we haven't * sent out an auth frame yet there's no need to send diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index bb6ad81b671d..424ff622ab5f 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c @@ -68,7 +68,6 @@ static int rds_release(struct socket *sock) { struct sock *sk = sock->sk; struct rds_sock *rs; - unsigned long flags; if (!sk) goto out; @@ -94,10 +93,10 @@ static int rds_release(struct socket *sock) rds_rdma_drop_keys(rs); rds_notify_queue_get(rs, NULL); - spin_lock_irqsave(&rds_sock_lock, flags); + spin_lock_bh(&rds_sock_lock); list_del_init(&rs->rs_item); rds_sock_count--; - spin_unlock_irqrestore(&rds_sock_lock, flags); + spin_unlock_bh(&rds_sock_lock); rds_trans_put(rs->rs_transport); @@ -409,7 +408,6 @@ static const struct proto_ops rds_proto_ops = { static int __rds_create(struct socket *sock, struct sock *sk, int protocol) { - unsigned long flags; struct rds_sock *rs; sock_init_data(sock, sk); @@ -426,10 +424,10 @@ static int __rds_create(struct socket *sock, struct sock *sk, int protocol) spin_lock_init(&rs->rs_rdma_lock); rs->rs_rdma_keys = RB_ROOT; - spin_lock_irqsave(&rds_sock_lock, flags); + spin_lock_bh(&rds_sock_lock); list_add_tail(&rs->rs_item, &rds_sock_list); rds_sock_count++; - spin_unlock_irqrestore(&rds_sock_lock, flags); + spin_unlock_bh(&rds_sock_lock); return 0; } @@ -471,12 +469,11 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, { struct rds_sock *rs; struct rds_incoming *inc; - unsigned long flags; unsigned int total = 0; len /= sizeof(struct rds_info_message); - spin_lock_irqsave(&rds_sock_lock, flags); + spin_lock_bh(&rds_sock_lock); list_for_each_entry(rs, &rds_sock_list, rs_item) { read_lock(&rs->rs_recv_lock); @@ -492,7 +489,7 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, read_unlock(&rs->rs_recv_lock); } - spin_unlock_irqrestore(&rds_sock_lock, flags); + spin_unlock_bh(&rds_sock_lock); lens->nr = total; lens->each = sizeof(struct rds_info_message); @@ -504,11 +501,10 @@ static void rds_sock_info(struct socket *sock, unsigned int len, { struct rds_info_socket sinfo; struct rds_sock *rs; - unsigned long flags; len /= sizeof(struct rds_info_socket); - spin_lock_irqsave(&rds_sock_lock, flags); + spin_lock_bh(&rds_sock_lock); if (len < rds_sock_count) goto out; @@ -529,7 +525,7 @@ out: lens->nr = rds_sock_count; lens->each = sizeof(struct rds_info_socket); - spin_unlock_irqrestore(&rds_sock_lock, flags); + spin_unlock_bh(&rds_sock_lock); } static void rds_exit(void) diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index e7e1d0b57b3d..2776012132ea 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -419,7 +419,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) cb = netem_skb_cb(skb); if (q->gap == 0 || /* not doing reordering */ - q->counter < q->gap || /* inside last reordering gap */ + q->counter < q->gap - 1 || /* inside last reordering gap */ q->reorder < get_crandom(&q->reorder_cor)) { psched_time_t now; psched_tdiff_t delay; diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index 1426ec3d0a53..75762f346975 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c @@ -92,6 +92,7 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) if (gcred->acred.group_info != NULL) get_group_info(gcred->acred.group_info); gcred->acred.machine_cred = acred->machine_cred; + gcred->acred.principal = acred->principal; dprintk("RPC: allocated %s cred %p for uid %d gid %d\n", gcred->acred.machine_cred ? "machine" : "generic", @@ -123,6 +124,17 @@ generic_destroy_cred(struct rpc_cred *cred) call_rcu(&cred->cr_rcu, generic_free_cred_callback); } +static int +machine_cred_match(struct auth_cred *acred, struct generic_cred *gcred, int flags) +{ + if (!gcred->acred.machine_cred || + gcred->acred.principal != acred->principal || + gcred->acred.uid != acred->uid || + gcred->acred.gid != acred->gid) + return 0; + return 1; +} + /* * Match credentials against current process creds. */ @@ -132,9 +144,12 @@ generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags) struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base); int i; + if (acred->machine_cred) + return machine_cred_match(acred, gcred, flags); + if (gcred->acred.uid != acred->uid || gcred->acred.gid != acred->gid || - gcred->acred.machine_cred != acred->machine_cred) + gcred->acred.machine_cred != 0) goto out_nomatch; /* Optimisation in the case where pointers are identical... */ diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index aad8fb699989..85d3bb7490aa 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1918,7 +1918,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb; unix_state_lock(sk); - skb = skb_dequeue(&sk->sk_receive_queue); + skb = skb_peek(&sk->sk_receive_queue); if (skb == NULL) { unix_sk(sk)->recursion_level = 0; if (copied >= target) @@ -1958,11 +1958,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (check_creds) { /* Never glue messages from different writers */ if ((UNIXCB(skb).pid != siocb->scm->pid) || - (UNIXCB(skb).cred != siocb->scm->cred)) { - skb_queue_head(&sk->sk_receive_queue, skb); - sk->sk_data_ready(sk, skb->len); + (UNIXCB(skb).cred != siocb->scm->cred)) break; - } } else { /* Copy credentials */ scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); @@ -1977,8 +1974,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, chunk = min_t(unsigned int, skb->len, size); if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { - skb_queue_head(&sk->sk_receive_queue, skb); - sk->sk_data_ready(sk, skb->len); if (copied == 0) copied = -EFAULT; break; @@ -1993,13 +1988,10 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (UNIXCB(skb).fp) unix_detach_fds(siocb->scm, skb); - /* put the skb back if we didn't use it up.. */ - if (skb->len) { - skb_queue_head(&sk->sk_receive_queue, skb); - sk->sk_data_ready(sk, skb->len); + if (skb->len) break; - } + skb_unlink(skb, &sk->sk_receive_queue); consume_skb(skb); if (siocb->scm->fp) @@ -2010,9 +2002,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (UNIXCB(skb).fp) siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); - /* put message back and return */ - skb_queue_head(&sk->sk_receive_queue, skb); - sk->sk_data_ready(sk, skb->len); break; } } while (size); diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index c0e14b3f2306..e8c969577768 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -823,16 +823,6 @@ static int do_spi_entry(const char *filename, struct spi_device_id *id, } ADD_TO_DEVTABLE("spi", struct spi_device_id, do_spi_entry); -/* Looks like: mcp:S */ -static int do_mcp_entry(const char *filename, struct mcp_device_id *id, - char *alias) -{ - sprintf(alias, MCP_MODULE_PREFIX "%s", id->name); - - return 1; -} -ADD_TO_DEVTABLE("mcp", struct mcp_device_id, do_mcp_entry); - static const struct dmifield { const char *prefix; int field; diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index dac3633507c9..a68aed7fce02 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -441,19 +441,22 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) params = kmalloc(sizeof(*params), GFP_KERNEL); if (!params) return -ENOMEM; - if (copy_from_user(params, (void __user *)arg, sizeof(*params))) - return -EFAULT; + if (copy_from_user(params, (void __user *)arg, sizeof(*params))) { + retval = -EFAULT; + goto out; + } retval = snd_compr_allocate_buffer(stream, params); if (retval) { - kfree(params); - return -ENOMEM; + retval = -ENOMEM; + goto out; } retval = stream->ops->set_params(stream, params); if (retval) goto out; stream->runtime->state = SNDRV_PCM_STATE_SETUP; - } else + } else { return -EPERM; + } out: kfree(params); return retval; diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c index 5b68435d195b..501501ef36a9 100644 --- a/sound/pci/hda/alc880_quirks.c +++ b/sound/pci/hda/alc880_quirks.c @@ -762,16 +762,22 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec, /* Looks like the unsol event is incompatible with the standard * definition. 4bit tag is placed at 28 bit! */ - switch (res >> 28) { + res >>= 28; + switch (res) { case ALC_MIC_EVENT: alc88x_simple_mic_automute(codec); break; default: - alc_sku_unsol_event(codec, res); + alc_exec_unsol_event(codec, res); break; } } +static void alc880_unsol_event(struct hda_codec *codec, unsigned int res) +{ + alc_exec_unsol_event(codec, res >> 28); +} + static void alc880_uniwill_p53_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -800,10 +806,11 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, /* Looks like the unsol event is incompatible with the standard * definition. 4bit tag is placed at 28 bit! */ - if ((res >> 28) == ALC_DCVOL_EVENT) + res >>= 28; + if (res == ALC_DCVOL_EVENT) alc880_uniwill_p53_dcvol_automute(codec); else - alc_sku_unsol_event(codec, res); + alc_exec_unsol_event(codec, res); } /* @@ -1677,7 +1684,7 @@ static const struct alc_config_preset alc880_presets[] = { .channel_mode = alc880_lg_ch_modes, .need_dac_fix = 1, .input_mux = &alc880_lg_capture_source, - .unsol_event = alc_sku_unsol_event, + .unsol_event = alc880_unsol_event, .setup = alc880_lg_setup, .init_hook = alc_hp_automute, #ifdef CONFIG_SND_HDA_POWER_SAVE diff --git a/sound/pci/hda/alc882_quirks.c b/sound/pci/hda/alc882_quirks.c index bdf0ed4ab3e2..bb364a53f546 100644 --- a/sound/pci/hda/alc882_quirks.c +++ b/sound/pci/hda/alc882_quirks.c @@ -730,6 +730,11 @@ static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res) alc889A_mb31_automute(codec); } +static void alc882_unsol_event(struct hda_codec *codec, unsigned int res) +{ + alc_exec_unsol_event(codec, res >> 26); +} + /* * configuration and preset */ @@ -775,7 +780,7 @@ static const struct alc_config_preset alc882_presets[] = { .channel_mode = alc885_mba21_ch_modes, .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes), .input_mux = &alc882_capture_source, - .unsol_event = alc_sku_unsol_event, + .unsol_event = alc882_unsol_event, .setup = alc885_mba21_setup, .init_hook = alc_hp_automute, }, @@ -791,7 +796,7 @@ static const struct alc_config_preset alc882_presets[] = { .input_mux = &alc882_capture_source, .dig_out_nid = ALC882_DIGOUT_NID, .dig_in_nid = ALC882_DIGIN_NID, - .unsol_event = alc_sku_unsol_event, + .unsol_event = alc882_unsol_event, .setup = alc885_mbp3_setup, .init_hook = alc_hp_automute, }, @@ -806,7 +811,7 @@ static const struct alc_config_preset alc882_presets[] = { .input_mux = &mb5_capture_source, .dig_out_nid = ALC882_DIGOUT_NID, .dig_in_nid = ALC882_DIGIN_NID, - .unsol_event = alc_sku_unsol_event, + .unsol_event = alc882_unsol_event, .setup = alc885_mb5_setup, .init_hook = alc_hp_automute, }, @@ -821,7 +826,7 @@ static const struct alc_config_preset alc882_presets[] = { .input_mux = &macmini3_capture_source, .dig_out_nid = ALC882_DIGOUT_NID, .dig_in_nid = ALC882_DIGIN_NID, - .unsol_event = alc_sku_unsol_event, + .unsol_event = alc882_unsol_event, .setup = alc885_macmini3_setup, .init_hook = alc_hp_automute, }, @@ -836,7 +841,7 @@ static const struct alc_config_preset alc882_presets[] = { .input_mux = &alc889A_imac91_capture_source, .dig_out_nid = ALC882_DIGOUT_NID, .dig_in_nid = ALC882_DIGIN_NID, - .unsol_event = alc_sku_unsol_event, + .unsol_event = alc882_unsol_event, .setup = alc885_imac91_setup, .init_hook = alc_hp_automute, }, diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 4df72c0e8c37..c2c65f63bf06 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1447,7 +1447,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, for (i = 0; i < c->cvt_setups.used; i++) { p = snd_array_elem(&c->cvt_setups, i); if (!p->active && p->stream_tag == stream_tag && - get_wcaps_type(get_wcaps(codec, p->nid)) == type) + get_wcaps_type(get_wcaps(c, p->nid)) == type) p->dirty = 1; } } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index fb35474c1203..95dfb6874941 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -469,6 +469,7 @@ struct azx { unsigned int irq_pending_warned :1; unsigned int probing :1; /* codec probing phase */ unsigned int snoop:1; + unsigned int align_buffer_size:1; /* for debugging */ unsigned int last_cmd[AZX_MAX_CODECS]; @@ -1690,7 +1691,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) runtime->hw.rates = hinfo->rates; snd_pcm_limit_hw_rates(runtime); snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (align_buffer_size) + if (chip->align_buffer_size) /* constrain buffer sizes to be multiple of 128 bytes. This is more efficient in terms of memory access but isn't required by the HDA spec and @@ -2773,8 +2774,9 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } /* disable buffer size rounding to 128-byte multiples if supported */ + chip->align_buffer_size = align_buffer_size; if (chip->driver_caps & AZX_DCAPS_BUFSIZE) - align_buffer_size = 0; + chip->align_buffer_size = 0; /* allow 64bit DMA address if supported by H/W */ if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index d8a35da0803f..9d819c4b4923 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -282,7 +282,8 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, - const struct auto_pin_cfg *cfg) + const struct auto_pin_cfg *cfg, + char *lastname, int *lastidx) { unsigned int def_conf, conn; char name[44]; @@ -298,6 +299,10 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, return 0; snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); + if (!strcmp(name, lastname) && idx == *lastidx) + idx++; + strncpy(lastname, name, 44); + *lastidx = idx; err = snd_hda_jack_add_kctl(codec, nid, name, idx); if (err < 0) return err; @@ -311,41 +316,42 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { const hda_nid_t *p; - int i, err; + int i, err, lastidx = 0; + char lastname[44] = ""; for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { - err = add_jack_kctl(codec, *p, cfg); + err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); if (err < 0) return err; } for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { if (*p == *cfg->line_out_pins) /* might be duplicated */ break; - err = add_jack_kctl(codec, *p, cfg); + err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); if (err < 0) return err; } for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { if (*p == *cfg->line_out_pins) /* might be duplicated */ break; - err = add_jack_kctl(codec, *p, cfg); + err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); if (err < 0) return err; } for (i = 0; i < cfg->num_inputs; i++) { - err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg); + err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx); if (err < 0) return err; } for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { - err = add_jack_kctl(codec, *p, cfg); + err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); if (err < 0) return err; } - err = add_jack_kctl(codec, cfg->dig_in_pin, cfg); + err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx); if (err < 0) return err; - err = add_jack_kctl(codec, cfg->mono_out_pin, cfg); + err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx); if (err < 0) return err; return 0; diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 0e99357e822c..bc5a993d1146 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -988,8 +988,10 @@ static void cs_automic(struct hda_codec *codec) change_cur_input(codec, !spec->automic_idx, 0); } else { if (present) { - spec->last_input = spec->cur_input; - spec->cur_input = spec->automic_idx; + if (spec->cur_input != spec->automic_idx) { + spec->last_input = spec->cur_input; + spec->cur_input = spec->automic_idx; + } } else { spec->cur_input = spec->last_input; } diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 8a32a69c83c3..a7a5733aa4d2 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3027,7 +3027,7 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), - SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), + SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T510", CXT5066_AUTO), SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520 & W520", CXT5066_AUTO), SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD), diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5e82acf77c5a..a8e82be3d2fc 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -177,6 +177,7 @@ struct alc_spec { unsigned int detect_lo:1; /* Line-out detection enabled */ unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */ unsigned int automute_lo_possible:1; /* there are line outs and HP */ + unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */ /* other flags */ unsigned int no_analog :1; /* digital I/O only */ @@ -185,7 +186,6 @@ struct alc_spec { unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ - unsigned int use_jack_tbl:1; /* 1 for model=auto */ /* auto-mute control */ int automute_mode; @@ -496,13 +496,24 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins, for (i = 0; i < num_pins; i++) { hda_nid_t nid = pins[i]; + unsigned int val; if (!nid) break; switch (spec->automute_mode) { case ALC_AUTOMUTE_PIN: + /* don't reset VREF value in case it's controlling + * the amp (see alc861_fixup_asus_amp_vref_0f()) + */ + if (spec->keep_vref_in_automute) { + val = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + val &= ~PIN_HP; + } else + val = 0; + val |= pin_bits; snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - pin_bits); + val); break; case ALC_AUTOMUTE_AMP: snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, @@ -621,17 +632,10 @@ static void alc_mic_automute(struct hda_codec *codec) alc_mux_select(codec, 0, spec->int_mic_idx, false); } -/* unsolicited event for HP jack sensing */ -static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) +/* handle the specified unsol action (ALC_XXX_EVENT) */ +static void alc_exec_unsol_event(struct hda_codec *codec, int action) { - struct alc_spec *spec = codec->spec; - if (codec->vendor_id == 0x10ec0880) - res >>= 28; - else - res >>= 26; - if (spec->use_jack_tbl) - res = snd_hda_jack_get_action(codec, res); - switch (res) { + switch (action) { case ALC_HP_EVENT: alc_hp_automute(codec); break; @@ -645,6 +649,17 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) snd_hda_jack_report_sync(codec); } +/* unsolicited event for HP jack sensing */ +static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) +{ + if (codec->vendor_id == 0x10ec0880) + res >>= 28; + else + res >>= 26; + res = snd_hda_jack_get_action(codec, res); + alc_exec_unsol_event(codec, res); +} + /* call init functions of standard auto-mute helpers */ static void alc_inithook(struct hda_codec *codec) { @@ -1883,7 +1898,7 @@ static const struct snd_kcontrol_new alc_beep_mixer[] = { }; #endif -static int alc_build_controls(struct hda_codec *codec) +static int __alc_build_controls(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; struct snd_kcontrol *kctl = NULL; @@ -2029,11 +2044,16 @@ static int alc_build_controls(struct hda_codec *codec) alc_free_kctls(codec); /* no longer needed */ - err = snd_hda_jack_add_kctls(codec, &spec->autocfg); + return 0; +} + +static int alc_build_controls(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + int err = __alc_build_controls(codec); if (err < 0) return err; - - return 0; + return snd_hda_jack_add_kctls(codec, &spec->autocfg); } @@ -3233,7 +3253,7 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, int i, err, noutputs; noutputs = cfg->line_outs; - if (spec->multi_ios > 0) + if (spec->multi_ios > 0 && cfg->line_outs < 3) noutputs += spec->multi_ios; for (i = 0; i < noutputs; i++) { @@ -3904,7 +3924,6 @@ static void set_capture_mixer(struct hda_codec *codec) static void alc_auto_init_std(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - spec->use_jack_tbl = 1; alc_auto_init_multi_out(codec); alc_auto_init_extra_out(codec); alc_auto_init_analog_input(codec); @@ -4168,6 +4187,8 @@ static int patch_alc880(struct hda_codec *codec) codec->patch_ops = alc_patch_ops; if (board_config == ALC_MODEL_AUTO) spec->init_hook = alc_auto_init_std; + else + codec->patch_ops.build_controls = __alc_build_controls; #ifdef CONFIG_SND_HDA_POWER_SAVE if (!spec->loopback.amplist) spec->loopback.amplist = alc880_loopbacks; @@ -4297,6 +4318,8 @@ static int patch_alc260(struct hda_codec *codec) codec->patch_ops = alc_patch_ops; if (board_config == ALC_MODEL_AUTO) spec->init_hook = alc_auto_init_std; + else + codec->patch_ops.build_controls = __alc_build_controls; spec->shutup = alc_eapd_shutup; #ifdef CONFIG_SND_HDA_POWER_SAVE if (!spec->loopback.amplist) @@ -4691,6 +4714,8 @@ static int patch_alc882(struct hda_codec *codec) codec->patch_ops = alc_patch_ops; if (board_config == ALC_MODEL_AUTO) spec->init_hook = alc_auto_init_std; + else + codec->patch_ops.build_controls = __alc_build_controls; #ifdef CONFIG_SND_HDA_POWER_SAVE if (!spec->loopback.amplist) @@ -4722,7 +4747,6 @@ enum { ALC262_FIXUP_FSC_H270, ALC262_FIXUP_HP_Z200, ALC262_FIXUP_TYAN, - ALC262_FIXUP_TOSHIBA_RX1, ALC262_FIXUP_LENOVO_3000, ALC262_FIXUP_BENQ, ALC262_FIXUP_BENQ_T31, @@ -4752,16 +4776,6 @@ static const struct alc_fixup alc262_fixups[] = { { } } }, - [ALC262_FIXUP_TOSHIBA_RX1] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x90170110 }, /* speaker */ - { 0x15, 0x0421101f }, /* HP */ - { 0x1a, 0x40f000f0 }, /* N/A */ - { 0x1b, 0x40f000f0 }, /* N/A */ - { 0x1e, 0x40f000f0 }, /* N/A */ - } - }, [ALC262_FIXUP_LENOVO_3000] = { .type = ALC_FIXUP_VERBS, .v.verbs = (const struct hda_verb[]) { @@ -4794,8 +4808,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = { SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ), SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ), SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN), - SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1", - ALC262_FIXUP_TOSHIBA_RX1), SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270), SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000), SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ), @@ -5364,7 +5376,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", ALC269_FIXUP_AMIC), SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269_FIXUP_AMIC), SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC), SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC), SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC), @@ -5573,8 +5584,28 @@ static const struct hda_amp_list alc861_loopbacks[] = { /* Pin config fixes */ enum { PINFIX_FSC_AMILO_PI1505, + PINFIX_ASUS_A6RP, }; +/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */ +static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + unsigned int val; + + if (action != ALC_FIXUP_ACT_INIT) + return; + val = snd_hda_codec_read(codec, 0x0f, 0, + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))) + val |= AC_PINCTL_IN_EN; + val |= AC_PINCTL_VREF_50; + snd_hda_codec_write(codec, 0x0f, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, val); + spec->keep_vref_in_automute = 1; +} + static const struct alc_fixup alc861_fixups[] = { [PINFIX_FSC_AMILO_PI1505] = { .type = ALC_FIXUP_PINS, @@ -5584,9 +5615,15 @@ static const struct alc_fixup alc861_fixups[] = { { } } }, + [PINFIX_ASUS_A6RP] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc861_fixup_asus_amp_vref_0f, + }, }; static const struct snd_pci_quirk alc861_fixup_tbl[] = { + SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP), + SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP), SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505), {} }; diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3556408d6ece..948f0be2f4f3 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1608,7 +1608,7 @@ static const struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a, "Alienware M17x", STAC_ALIENWARE_M17X), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, - "Alienware M17x", STAC_ALIENWARE_M17X), + "Alienware M17x R3", STAC_DELL_EQ), {} /* terminator */ }; @@ -4163,13 +4163,15 @@ static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, return 1; } -static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) +static int is_nid_out_jack_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) { int i; for (i = 0; i < cfg->hp_outs; i++) if (cfg->hp_pins[i] == nid) return 1; /* nid is a HP-Out */ - + for (i = 0; i < cfg->line_outs; i++) + if (cfg->line_out_pins[i] == nid) + return 1; /* nid is a line-Out */ return 0; /* nid is not a HP-Out */ }; @@ -4375,7 +4377,7 @@ static int stac92xx_init(struct hda_codec *codec) continue; } - if (is_nid_hp_pin(cfg, nid)) + if (is_nid_out_jack_pin(cfg, nid)) continue; /* already has an unsol event */ pinctl = snd_hda_codec_read(codec, nid, 0, @@ -4868,7 +4870,14 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity) /* BIOS bug: unfilled OEM string */ if (strstr(dev->name, "HP_Mute_LED_P_G")) { set_hp_led_gpio(codec); - spec->gpio_led_polarity = 1; + switch (codec->subsystem_id) { + case 0x103c148a: + spec->gpio_led_polarity = 0; + break; + default: + spec->gpio_led_polarity = 1; + break; + } return 1; } } diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 03e63fed9caf..284e311040fe 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -199,6 +199,9 @@ struct via_spec { unsigned int no_pin_power_ctl; enum VIA_HDA_CODEC codec_type; + /* analog low-power control */ + bool alc_mode; + /* smart51 setup */ unsigned int smart51_nums; hda_nid_t smart51_pins[2]; @@ -687,6 +690,15 @@ static void via_auto_init_analog_input(struct hda_codec *codec) } } +static void update_power_state(struct hda_codec *codec, hda_nid_t nid, + unsigned int parm) +{ + if (snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_POWER_STATE, 0) == parm) + return; + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm); +} + static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid, unsigned int *affected_parm) { @@ -709,7 +721,7 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid, } else parm = AC_PWRST_D3; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, nid, parm); } static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol, @@ -749,6 +761,7 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol, return 0; spec->no_pin_power_ctl = val; set_widgets_power_state(codec); + analog_low_current_mode(codec); return 1; } @@ -1036,13 +1049,19 @@ static bool is_aa_path_mute(struct hda_codec *codec) } /* enter/exit analog low-current mode */ -static void analog_low_current_mode(struct hda_codec *codec) +static void __analog_low_current_mode(struct hda_codec *codec, bool force) { struct via_spec *spec = codec->spec; bool enable; unsigned int verb, parm; - enable = is_aa_path_mute(codec) && (spec->opened_streams != 0); + if (spec->no_pin_power_ctl) + enable = false; + else + enable = is_aa_path_mute(codec) && !spec->opened_streams; + if (enable == spec->alc_mode && !force) + return; + spec->alc_mode = enable; /* decide low current mode's verb & parameter */ switch (spec->codec_type) { @@ -1074,6 +1093,11 @@ static void analog_low_current_mode(struct hda_codec *codec) snd_hda_codec_write(codec, codec->afg, 0, verb, parm); } +static void analog_low_current_mode(struct hda_codec *codec) +{ + return __analog_low_current_mode(codec, false); +} + /* * generic initialization of ADC, input mixers and output mixers */ @@ -1446,6 +1470,7 @@ static int via_build_controls(struct hda_codec *codec) struct snd_kcontrol *kctl; int err, i; + spec->no_pin_power_ctl = 1; if (spec->set_widgets_power_state) if (!via_clone_control(spec, &via_pin_power_ctl_enum)) return -ENOMEM; @@ -1499,10 +1524,6 @@ static int via_build_controls(struct hda_codec *codec) return err; } - /* init power states */ - set_widgets_power_state(codec); - analog_low_current_mode(codec); - via_free_kctls(codec); /* no longer needed */ err = snd_hda_jack_add_kctls(codec, &spec->autocfg); @@ -2295,10 +2316,7 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol, if (mux) { /* switch to D0 beofre change index */ - if (snd_hda_codec_read(codec, mux, 0, - AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0) - snd_hda_codec_write(codec, mux, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, mux, AC_PWRST_D0); snd_hda_codec_write(codec, mux, 0, AC_VERB_SET_CONNECT_SEL, spec->inputs[cur].mux_idx); @@ -2776,6 +2794,10 @@ static int via_init(struct hda_codec *codec) for (i = 0; i < spec->num_iverbs; i++) snd_hda_sequence_write(codec, spec->init_verbs[i]); + /* init power states */ + set_widgets_power_state(codec); + __analog_low_current_mode(codec, true); + via_auto_init_multi_out(codec); via_auto_init_hp_out(codec); via_auto_init_speaker_out(codec); @@ -2922,9 +2944,9 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec) if (imux_is_smixer) parm = AC_PWRST_D0; /* SW0 (17h), AIW 0/1 (13h/14h) */ - snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x17, parm); + update_power_state(codec, 0x13, parm); + update_power_state(codec, 0x14, parm); /* outputs */ /* PW0 (19h), SW1 (18h), AOW1 (11h) */ @@ -2932,8 +2954,8 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec) set_pin_power_state(codec, 0x19, &parm); if (spec->smart51_enabled) set_pin_power_state(codec, 0x1b, &parm); - snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x18, parm); + update_power_state(codec, 0x11, parm); /* PW6 (22h), SW2 (26h), AOW2 (24h) */ if (is_8ch) { @@ -2941,20 +2963,16 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec) set_pin_power_state(codec, 0x22, &parm); if (spec->smart51_enabled) set_pin_power_state(codec, 0x1a, &parm); - snd_hda_codec_write(codec, 0x26, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x24, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x26, parm); + update_power_state(codec, 0x24, parm); } else if (codec->vendor_id == 0x11064397) { /* PW7(23h), SW2(27h), AOW2(25h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x23, &parm); if (spec->smart51_enabled) set_pin_power_state(codec, 0x1a, &parm); - snd_hda_codec_write(codec, 0x27, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x25, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x27, parm); + update_power_state(codec, 0x25, parm); } /* PW 3/4/7 (1ch/1dh/23h) */ @@ -2966,17 +2984,13 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec) set_pin_power_state(codec, 0x23, &parm); /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */ - snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE, - imux_is_smixer ? AC_PWRST_D0 : parm); - snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm); + update_power_state(codec, 0x10, parm); if (is_8ch) { - snd_hda_codec_write(codec, 0x25, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x27, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x25, parm); + update_power_state(codec, 0x27, parm); } else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode) - snd_hda_codec_write(codec, 0x25, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x25, parm); } static int patch_vt1708S(struct hda_codec *codec); @@ -3149,10 +3163,10 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec) if (imux_is_smixer) parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */ /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */ - snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x13, parm); + update_power_state(codec, 0x12, parm); + update_power_state(codec, 0x1f, parm); + update_power_state(codec, 0x20, parm); /* outputs */ /* PW 3/4 (16h/17h) */ @@ -3160,10 +3174,9 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec) set_pin_power_state(codec, 0x17, &parm); set_pin_power_state(codec, 0x16, &parm); /* MW0 (1ah), AOW 0/1 (10h/1dh) */ - snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, - imux_is_smixer ? AC_PWRST_D0 : parm); - snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1a, imux_is_smixer ? AC_PWRST_D0 : parm); + update_power_state(codec, 0x10, parm); + update_power_state(codec, 0x1d, parm); } static int patch_vt1702(struct hda_codec *codec) @@ -3228,52 +3241,48 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec) if (imux_is_smixer) parm = AC_PWRST_D0; /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */ - snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1e, parm); + update_power_state(codec, 0x1f, parm); + update_power_state(codec, 0x10, parm); + update_power_state(codec, 0x11, parm); /* outputs */ /* PW3 (27h), MW2 (1ah), AOW3 (bh) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x27, &parm); - snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1a, parm); + update_power_state(codec, 0xb, parm); /* PW2 (26h), AOW2 (ah) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x26, &parm); if (spec->smart51_enabled) set_pin_power_state(codec, 0x2b, &parm); - snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0xa, parm); /* PW0 (24h), AOW0 (8h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x24, &parm); if (!spec->hp_independent_mode) /* check for redirected HP */ set_pin_power_state(codec, 0x28, &parm); - snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x8, parm); /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */ - snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE, - imux_is_smixer ? AC_PWRST_D0 : parm); + update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm); /* PW1 (25h), AOW1 (9h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x25, &parm); if (spec->smart51_enabled) set_pin_power_state(codec, 0x2a, &parm); - snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x9, parm); if (spec->hp_independent_mode) { /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x28, &parm); - snd_hda_codec_write(codec, 0x1b, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x34, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0xc, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1b, parm); + update_power_state(codec, 0x34, parm); + update_power_state(codec, 0xc, parm); } } @@ -3433,8 +3442,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec) if (imux_is_smixer) parm = AC_PWRST_D0; /* SW0 (17h), AIW0(13h) */ - snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x17, parm); + update_power_state(codec, 0x13, parm); parm = AC_PWRST_D3; set_pin_power_state(codec, 0x1e, &parm); @@ -3442,12 +3451,11 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec) if (spec->dmic_enabled) set_pin_power_state(codec, 0x22, &parm); else - snd_hda_codec_write(codec, 0x22, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); + update_power_state(codec, 0x22, AC_PWRST_D3); /* SW2(26h), AIW1(14h) */ - snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x26, parm); + update_power_state(codec, 0x14, parm); /* outputs */ /* PW0 (19h), SW1 (18h), AOW1 (11h) */ @@ -3456,8 +3464,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec) /* Smart 5.1 PW2(1bh) */ if (spec->smart51_enabled) set_pin_power_state(codec, 0x1b, &parm); - snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x18, parm); + update_power_state(codec, 0x11, parm); /* PW7 (23h), SW3 (27h), AOW3 (25h) */ parm = AC_PWRST_D3; @@ -3465,12 +3473,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec) /* Smart 5.1 PW1(1ah) */ if (spec->smart51_enabled) set_pin_power_state(codec, 0x1a, &parm); - snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x27, parm); /* Smart 5.1 PW5(1eh) */ if (spec->smart51_enabled) set_pin_power_state(codec, 0x1e, &parm); - snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x25, parm); /* Mono out */ /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/ @@ -3486,9 +3494,9 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec) mono_out = 1; } parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3; - snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x28, parm); + update_power_state(codec, 0x29, parm); + update_power_state(codec, 0x2a, parm); /* PW 3/4 (1ch/1dh) */ parm = AC_PWRST_D3; @@ -3496,15 +3504,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec) set_pin_power_state(codec, 0x1d, &parm); /* HP Independent Mode, power on AOW3 */ if (spec->hp_independent_mode) - snd_hda_codec_write(codec, 0x25, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x25, parm); /* force to D0 for internal Speaker */ /* MW0 (16h), AOW0 (10h) */ - snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE, - imux_is_smixer ? AC_PWRST_D0 : parm); - snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, - mono_out ? AC_PWRST_D0 : parm); + update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm); + update_power_state(codec, 0x10, mono_out ? AC_PWRST_D0 : parm); } static int patch_vt1716S(struct hda_codec *codec) @@ -3580,54 +3585,45 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) set_pin_power_state(codec, 0x2b, &parm); parm = AC_PWRST_D0; /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */ - snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1e, parm); + update_power_state(codec, 0x1f, parm); + update_power_state(codec, 0x10, parm); + update_power_state(codec, 0x11, parm); /* outputs */ /* AOW0 (8h)*/ - snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x8, parm); if (spec->codec_type == VT1802) { /* PW4 (28h), MW4 (18h), MUX4(38h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x28, &parm); - snd_hda_codec_write(codec, 0x18, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x38, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x18, parm); + update_power_state(codec, 0x38, parm); } else { /* PW4 (26h), MW4 (1ch), MUX4(37h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x26, &parm); - snd_hda_codec_write(codec, 0x1c, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x37, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1c, parm); + update_power_state(codec, 0x37, parm); } if (spec->codec_type == VT1802) { /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x25, &parm); - snd_hda_codec_write(codec, 0x15, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x35, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x15, parm); + update_power_state(codec, 0x35, parm); } else { /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x25, &parm); - snd_hda_codec_write(codec, 0x19, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x35, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x19, parm); + update_power_state(codec, 0x35, parm); } if (spec->hp_independent_mode) - snd_hda_codec_write(codec, 0x9, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, 0x9, AC_PWRST_D0); /* Class-D */ /* PW0 (24h), MW0(18h/14h), MUX0(34h) */ @@ -3637,12 +3633,10 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) set_pin_power_state(codec, 0x24, &parm); parm = present ? AC_PWRST_D3 : AC_PWRST_D0; if (spec->codec_type == VT1802) - snd_hda_codec_write(codec, 0x14, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x14, parm); else - snd_hda_codec_write(codec, 0x18, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x18, parm); + update_power_state(codec, 0x34, parm); /* Mono Out */ present = snd_hda_jack_detect(codec, 0x26); @@ -3650,28 +3644,20 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) parm = present ? AC_PWRST_D3 : AC_PWRST_D0; if (spec->codec_type == VT1802) { /* PW15 (33h), MW8(1ch), MUX8(3ch) */ - snd_hda_codec_write(codec, 0x33, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x1c, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x3c, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x33, parm); + update_power_state(codec, 0x1c, parm); + update_power_state(codec, 0x3c, parm); } else { /* PW15 (31h), MW8(17h), MUX8(3bh) */ - snd_hda_codec_write(codec, 0x31, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x17, 0, - AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x3b, 0, - AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x31, parm); + update_power_state(codec, 0x17, parm); + update_power_state(codec, 0x3b, parm); } /* MW9 (21h) */ if (imux_is_smixer || !is_aa_path_mute(codec)) - snd_hda_codec_write(codec, 0x21, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, 0x21, AC_PWRST_D0); else - snd_hda_codec_write(codec, 0x21, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); + update_power_state(codec, 0x21, AC_PWRST_D3); } /* patch for vt2002P */ @@ -3731,30 +3717,28 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec) set_pin_power_state(codec, 0x2b, &parm); parm = AC_PWRST_D0; /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */ - snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1e, parm); + update_power_state(codec, 0x1f, parm); + update_power_state(codec, 0x10, parm); + update_power_state(codec, 0x11, parm); /* outputs */ /* AOW0 (8h)*/ - snd_hda_codec_write(codec, 0x8, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, 0x8, AC_PWRST_D0); /* PW4 (28h), MW4 (18h), MUX4(38h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x28, &parm); - snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x38, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x18, parm); + update_power_state(codec, 0x38, parm); /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x25, &parm); - snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x35, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x15, parm); + update_power_state(codec, 0x35, parm); if (spec->hp_independent_mode) - snd_hda_codec_write(codec, 0x9, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, 0x9, AC_PWRST_D0); /* Internal Speaker */ /* PW0 (24h), MW0(14h), MUX0(34h) */ @@ -3763,15 +3747,11 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec) parm = AC_PWRST_D3; set_pin_power_state(codec, 0x24, &parm); if (present) { - snd_hda_codec_write(codec, 0x14, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - snd_hda_codec_write(codec, 0x34, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); + update_power_state(codec, 0x14, AC_PWRST_D3); + update_power_state(codec, 0x34, AC_PWRST_D3); } else { - snd_hda_codec_write(codec, 0x14, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); - snd_hda_codec_write(codec, 0x34, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, 0x14, AC_PWRST_D0); + update_power_state(codec, 0x34, AC_PWRST_D0); } @@ -3782,26 +3762,20 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec) parm = AC_PWRST_D3; set_pin_power_state(codec, 0x31, &parm); if (present) { - snd_hda_codec_write(codec, 0x1c, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - snd_hda_codec_write(codec, 0x3c, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - snd_hda_codec_write(codec, 0x3e, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); + update_power_state(codec, 0x1c, AC_PWRST_D3); + update_power_state(codec, 0x3c, AC_PWRST_D3); + update_power_state(codec, 0x3e, AC_PWRST_D3); } else { - snd_hda_codec_write(codec, 0x1c, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); - snd_hda_codec_write(codec, 0x3c, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); - snd_hda_codec_write(codec, 0x3e, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); + update_power_state(codec, 0x1c, AC_PWRST_D0); + update_power_state(codec, 0x3c, AC_PWRST_D0); + update_power_state(codec, 0x3e, AC_PWRST_D0); } /* PW15 (33h), MW15 (1dh), MUX15(3dh) */ parm = AC_PWRST_D3; set_pin_power_state(codec, 0x33, &parm); - snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm); - snd_hda_codec_write(codec, 0x3d, 0, AC_VERB_SET_POWER_STATE, parm); + update_power_state(codec, 0x1d, parm); + update_power_state(codec, 0x3d, parm); } diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index e57b89e8aa89..94ab728f5ca8 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -286,17 +286,22 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, snd_card_free(card); return err; } - if ((err = snd_ymfpci_pcm_4ch(chip, 2, NULL)) < 0) { + err = snd_ymfpci_mixer(chip, rear_switch[dev]); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_ymfpci_pcm2(chip, 3, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_ymfpci_mixer(chip, rear_switch[dev])) < 0) { - snd_card_free(card); - return err; + if (chip->ac97->ext_id & AC97_EI_SDAC) { + err = snd_ymfpci_pcm_4ch(chip, 2, NULL); + if (err < 0) { + snd_card_free(card); + return err; + } + err = snd_ymfpci_pcm2(chip, 3, NULL); + if (err < 0) { + snd_card_free(card); + return err; + } } if ((err = snd_ymfpci_timer(chip, 0)) < 0) { snd_card_free(card); diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 03ee4e365311..12a9a2b03387 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -1614,6 +1614,14 @@ static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_e return change; } +static struct snd_kcontrol_new snd_ymfpci_dup4ch __devinitdata = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "4ch Duplication", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = snd_ymfpci_info_dup4ch, + .get = snd_ymfpci_get_dup4ch, + .put = snd_ymfpci_put_dup4ch, +}; static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = { { @@ -1642,13 +1650,6 @@ YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,VOLUME), 1, YDSXGR_SPDIFLOOPVOL), YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), 0, YDSXGR_SPDIFOUTCTRL, 0), YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, YDSXGR_SPDIFINCTRL, 0), YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("Loop",NONE,NONE), 0, YDSXGR_SPDIFINCTRL, 4), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "4ch Duplication", - .info = snd_ymfpci_info_dup4ch, - .get = snd_ymfpci_get_dup4ch, - .put = snd_ymfpci_put_dup4ch, -}, }; @@ -1838,6 +1839,12 @@ int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip))) < 0) return err; } + if (chip->ac97->ext_id & AC97_EI_SDAC) { + kctl = snd_ctl_new1(&snd_ymfpci_dup4ch, chip); + err = snd_ctl_add(chip->card, kctl); + if (err < 0) + return err; + } /* add S/PDIF control */ if (snd_BUG_ON(!chip->pcm_spdif)) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index f8863ebb4304..7f4ba819a9f6 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -987,12 +987,12 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec) /* restore regular registers */ for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) { - /* this regs depends on the others */ + /* These regs should restore in particular order */ if (reg == SGTL5000_CHIP_ANA_POWER || reg == SGTL5000_CHIP_CLK_CTRL || reg == SGTL5000_CHIP_LINREG_CTRL || reg == SGTL5000_CHIP_LINE_OUT_CTRL || - reg == SGTL5000_CHIP_CLK_CTRL) + reg == SGTL5000_CHIP_REF_CTRL) continue; snd_soc_write(codec, reg, cache[reg]); @@ -1003,8 +1003,17 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec) snd_soc_write(codec, reg, cache[reg]); /* - * restore power and other regs according - * to set_power() and set_clock() + * restore these regs according to the power setting sequence in + * sgtl5000_set_power_regs() and clock setting sequence in + * sgtl5000_set_clock(). + * + * The order of restore is: + * 1. SGTL5000_CHIP_CLK_CTRL MCLK_FREQ bits (1:0) should be restore after + * SGTL5000_CHIP_ANA_POWER PLL bits set + * 2. SGTL5000_CHIP_LINREG_CTRL should be set before + * SGTL5000_CHIP_ANA_POWER LINREG_D restored + * 3. SGTL5000_CHIP_REF_CTRL controls Analog Ground Voltage, + * prefer to resotre it after SGTL5000_CHIP_ANA_POWER restored */ snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL, cache[SGTL5000_CHIP_LINREG_CTRL]); diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index eb401ef021fb..372b0b83bd9f 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -60,7 +60,6 @@ struct aic32x4_rate_divs { struct aic32x4_priv { u32 sysclk; - s32 master; u8 page_no; void *control_data; u32 power_cfg; @@ -369,7 +368,6 @@ static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); u8 iface_reg_1; u8 iface_reg_2; u8 iface_reg_3; @@ -384,11 +382,9 @@ static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: - aic32x4->master = 1; iface_reg_1 |= AIC32X4_BCLKMASTER | AIC32X4_WCLKMASTER; break; case SND_SOC_DAIFMT_CBS_CFS: - aic32x4->master = 0; break; default: printk(KERN_ERR "aic32x4: invalid DAI master/slave interface\n"); @@ -526,64 +522,58 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute) static int aic32x4_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); - switch (level) { case SND_SOC_BIAS_ON: - if (aic32x4->master) { - /* Switch on PLL */ - snd_soc_update_bits(codec, AIC32X4_PLLPR, - AIC32X4_PLLEN, AIC32X4_PLLEN); - - /* Switch on NDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_NDAC, - AIC32X4_NDACEN, AIC32X4_NDACEN); - - /* Switch on MDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_MDAC, - AIC32X4_MDACEN, AIC32X4_MDACEN); - - /* Switch on NADC Divider */ - snd_soc_update_bits(codec, AIC32X4_NADC, - AIC32X4_NADCEN, AIC32X4_NADCEN); - - /* Switch on MADC Divider */ - snd_soc_update_bits(codec, AIC32X4_MADC, - AIC32X4_MADCEN, AIC32X4_MADCEN); - - /* Switch on BCLK_N Divider */ - snd_soc_update_bits(codec, AIC32X4_BCLKN, - AIC32X4_BCLKEN, AIC32X4_BCLKEN); - } + /* Switch on PLL */ + snd_soc_update_bits(codec, AIC32X4_PLLPR, + AIC32X4_PLLEN, AIC32X4_PLLEN); + + /* Switch on NDAC Divider */ + snd_soc_update_bits(codec, AIC32X4_NDAC, + AIC32X4_NDACEN, AIC32X4_NDACEN); + + /* Switch on MDAC Divider */ + snd_soc_update_bits(codec, AIC32X4_MDAC, + AIC32X4_MDACEN, AIC32X4_MDACEN); + + /* Switch on NADC Divider */ + snd_soc_update_bits(codec, AIC32X4_NADC, + AIC32X4_NADCEN, AIC32X4_NADCEN); + + /* Switch on MADC Divider */ + snd_soc_update_bits(codec, AIC32X4_MADC, + AIC32X4_MADCEN, AIC32X4_MADCEN); + + /* Switch on BCLK_N Divider */ + snd_soc_update_bits(codec, AIC32X4_BCLKN, + AIC32X4_BCLKEN, AIC32X4_BCLKEN); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: - if (aic32x4->master) { - /* Switch off PLL */ - snd_soc_update_bits(codec, AIC32X4_PLLPR, - AIC32X4_PLLEN, 0); - - /* Switch off NDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_NDAC, - AIC32X4_NDACEN, 0); - - /* Switch off MDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_MDAC, - AIC32X4_MDACEN, 0); - - /* Switch off NADC Divider */ - snd_soc_update_bits(codec, AIC32X4_NADC, - AIC32X4_NADCEN, 0); - - /* Switch off MADC Divider */ - snd_soc_update_bits(codec, AIC32X4_MADC, - AIC32X4_MADCEN, 0); - - /* Switch off BCLK_N Divider */ - snd_soc_update_bits(codec, AIC32X4_BCLKN, - AIC32X4_BCLKEN, 0); - } + /* Switch off PLL */ + snd_soc_update_bits(codec, AIC32X4_PLLPR, + AIC32X4_PLLEN, 0); + + /* Switch off NDAC Divider */ + snd_soc_update_bits(codec, AIC32X4_NDAC, + AIC32X4_NDACEN, 0); + + /* Switch off MDAC Divider */ + snd_soc_update_bits(codec, AIC32X4_MDAC, + AIC32X4_MDACEN, 0); + + /* Switch off NADC Divider */ + snd_soc_update_bits(codec, AIC32X4_NADC, + AIC32X4_NADCEN, 0); + + /* Switch off MADC Divider */ + snd_soc_update_bits(codec, AIC32X4_MADC, + AIC32X4_MADCEN, 0); + + /* Switch off BCLK_N Divider */ + snd_soc_update_bits(codec, AIC32X4_BCLKN, + AIC32X4_BCLKEN, 0); break; case SND_SOC_BIAS_OFF: break; @@ -651,9 +641,11 @@ static int aic32x4_probe(struct snd_soc_codec *codec) if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) { snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE); } - if (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) { - snd_soc_write(codec, AIC32X4_LDOCTL, AIC32X4_LDOCTLEN); - } + + tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ? + AIC32X4_LDOCTLEN : 0; + snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg); + tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE); if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) { tmp_reg |= AIC32X4_LDOIN_18_36; diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index c2880907fced..a75c3766aede 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -733,8 +733,9 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, struct wm2000_priv *wm2000; struct wm2000_platform_data *pdata; const char *filename; - const struct firmware *fw; - int reg, ret; + const struct firmware *fw = NULL; + int ret; + int reg; u16 id; wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv), @@ -751,7 +752,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, ret = PTR_ERR(wm2000->regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", ret); - goto err; + goto out; } /* Verify that this is a WM2000 */ @@ -763,7 +764,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, if (id != 0x2000) { dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id); ret = -ENODEV; - goto err_regmap; + goto out_regmap_exit; } reg = wm2000_read(i2c, WM2000_REG_REVISON); @@ -782,7 +783,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, ret = request_firmware(&fw, filename, &i2c->dev); if (ret != 0) { dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret); - goto err_regmap; + goto out_regmap_exit; } /* Pre-cook the concatenation of the register address onto the image */ @@ -793,15 +794,13 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, if (wm2000->anc_download == NULL) { dev_err(&i2c->dev, "Out of memory\n"); ret = -ENOMEM; - goto err_fw; + goto out_regmap_exit; } wm2000->anc_download[0] = 0x80; wm2000->anc_download[1] = 0x00; memcpy(wm2000->anc_download + 2, fw->data, fw->size); - release_firmware(fw); - wm2000->anc_eng_ena = 1; wm2000->anc_active = 1; wm2000->spk_ena = 1; @@ -809,18 +808,14 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, wm2000_reset(wm2000); - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, - NULL, 0); - if (ret != 0) - goto err_fw; + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0); + if (!ret) + goto out; - return 0; - -err_fw: - release_firmware(fw); -err_regmap: +out_regmap_exit: regmap_exit(wm2000->regmap); -err: +out: + release_firmware(fw); return ret; } diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 8b24323d6b2c..89f2af77b1c3 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -1377,6 +1377,7 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec, switch (wm5100->rev) { case 0: + regcache_cache_bypass(wm5100->regmap, true); snd_soc_write(codec, 0x11, 0x3); snd_soc_write(codec, 0x203, 0xc); snd_soc_write(codec, 0x206, 0); @@ -1392,6 +1393,7 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec, snd_soc_write(codec, wm5100_reva_patches[i].reg, wm5100_reva_patches[i].val); + regcache_cache_bypass(wm5100->regmap, false); break; default: break; @@ -1402,6 +1404,8 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_OFF: + regcache_cache_only(wm5100->regmap, true); + regcache_mark_dirty(wm5100->regmap); if (wm5100->pdata.ldo_ena) gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), @@ -2180,6 +2184,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec) if (wm5100->jack_detecting) { dev_dbg(codec->dev, "Microphone detected\n"); wm5100->jack_mic = true; + wm5100->jack_detecting = false; snd_soc_jack_report(wm5100->jack, SND_JACK_HEADSET, SND_JACK_HEADSET | SND_JACK_BTN_0); @@ -2218,6 +2223,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec) SND_JACK_BTN_0); } else if (wm5100->jack_detecting) { dev_dbg(codec->dev, "Headphone detected\n"); + wm5100->jack_detecting = false; snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE, SND_JACK_HEADPHONE); @@ -2607,6 +2613,13 @@ static const struct regmap_config wm5100_regmap = { .cache_type = REGCACHE_RBTREE, }; +static const unsigned int wm5100_mic_ctrl_reg[] = { + WM5100_IN1L_CONTROL, + WM5100_IN2L_CONTROL, + WM5100_IN3L_CONTROL, + WM5100_IN4L_CONTROL, +}; + static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -2739,7 +2752,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, } for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) { - regmap_update_bits(wm5100->regmap, WM5100_IN1L_CONTROL, + regmap_update_bits(wm5100->regmap, wm5100_mic_ctrl_reg[i], WM5100_IN1_MODE_MASK | WM5100_IN1_DMIC_SUP_MASK, (wm5100->pdata.in_mode[i] << diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 8d4ea43d40a3..40ac888faf3d 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -55,7 +55,7 @@ static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name, return 0; if (fw->size < 32) { - dev_err(codec->dev, "%s: firmware too short (%d bytes)\n", + dev_err(codec->dev, "%s: firmware too short (%zd bytes)\n", name, fw->size); goto err; } diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 296de4e30d26..bda3da887d7e 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -96,7 +96,7 @@ static int wm8962_regulator_event_##n(struct notifier_block *nb, \ struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \ disable_nb[n]); \ if (event & REGULATOR_EVENT_DISABLE) { \ - regcache_cache_only(wm8962->regmap, true); \ + regcache_mark_dirty(wm8962->regmap); \ } \ return 0; \ } diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index d8da10fe5b52..61f7daa4d0e6 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -108,7 +108,7 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \ struct wm8996_priv *wm8996 = container_of(nb, struct wm8996_priv, \ disable_nb[n]); \ if (event & REGULATOR_EVENT_DISABLE) { \ - regcache_cache_only(wm8996->regmap, true); \ + regcache_mark_dirty(wm8996->regmap); \ } \ return 0; \ } @@ -1120,7 +1120,8 @@ SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), @@ -2007,6 +2008,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai, struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); int lfclk = 0; int ratediv = 0; + int sync = WM8996_REG_SYNC; int src; int old; @@ -2051,6 +2053,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai, case 32000: case 32768: lfclk = WM8996_LFCLK_ENA; + sync = 0; break; default: dev_warn(codec->dev, "Unsupported clock rate %dHz\n", @@ -2064,6 +2067,8 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai, WM8996_SYSCLK_SRC_MASK | WM8996_SYSCLK_DIV_MASK, src << WM8996_SYSCLK_SRC_SHIFT | ratediv); snd_soc_update_bits(codec, WM8996_CLOCKING_1, WM8996_LFCLK_ENA, lfclk); + snd_soc_update_bits(codec, WM8996_CONTROL_INTERFACE_1, + WM8996_REG_SYNC, sync); snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1, WM8996_SYSCLK_ENA, old); diff --git a/sound/soc/codecs/wm8996.h b/sound/soc/codecs/wm8996.h index 0fde643194ce..de9ac3e44aec 100644 --- a/sound/soc/codecs/wm8996.h +++ b/sound/soc/codecs/wm8996.h @@ -1567,6 +1567,10 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, /* * R257 (0x101) - Control Interface (1) */ +#define WM8996_REG_SYNC 0x8000 /* REG_SYNC */ +#define WM8996_REG_SYNC_MASK 0x8000 /* REG_SYNC */ +#define WM8996_REG_SYNC_SHIFT 15 /* REG_SYNC */ +#define WM8996_REG_SYNC_WIDTH 1 /* REG_SYNC */ #define WM8996_AUTO_INC 0x0004 /* AUTO_INC */ #define WM8996_AUTO_INC_MASK 0x0004 /* AUTO_INC */ #define WM8996_AUTO_INC_SHIFT 2 /* AUTO_INC */ diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 2a61094075f8..ea2672455d07 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -592,8 +592,8 @@ SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0), }; static const struct snd_kcontrol_new line2n_mix[] = { -SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0), -SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0), +SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0), +SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0), }; static const struct snd_kcontrol_new line2p_mix[] = { @@ -613,6 +613,8 @@ SND_SOC_DAPM_INPUT("IN2RP:VXRP"), SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("LINEOUT_VMID_BUF", WM8993_ANTIPOP1, 7, 0, NULL, 0), + SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, in1l_pga, ARRAY_SIZE(in1l_pga)), SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0, @@ -834,9 +836,11 @@ static const struct snd_soc_dapm_route lineout1_diff_routes[] = { }; static const struct snd_soc_dapm_route lineout1_se_routes[] = { + { "LINEOUT1N Mixer", NULL, "LINEOUT_VMID_BUF" }, { "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" }, { "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" }, + { "LINEOUT1P Mixer", NULL, "LINEOUT_VMID_BUF" }, { "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" }, { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" }, @@ -853,9 +857,11 @@ static const struct snd_soc_dapm_route lineout2_diff_routes[] = { }; static const struct snd_soc_dapm_route lineout2_se_routes[] = { + { "LINEOUT2N Mixer", NULL, "LINEOUT_VMID_BUF" }, { "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" }, { "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" }, + { "LINEOUT2P Mixer", NULL, "LINEOUT_VMID_BUF" }, { "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" }, { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" }, diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index dccfb37a9626..f204dbac11d4 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -124,6 +124,8 @@ static int mxs_saif_set_clk(struct mxs_saif *saif, * * If MCLK is not used, we just set saif clk to 512*fs. */ + clk_prepare_enable(master_saif->clk); + if (master_saif->mclk_in_use) { if (mclk % 32 == 0) { scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; @@ -133,6 +135,7 @@ static int mxs_saif_set_clk(struct mxs_saif *saif, ret = clk_set_rate(master_saif->clk, 384 * rate); } else { /* SAIF MCLK should be either 32x or 48x */ + clk_disable_unprepare(master_saif->clk); return -EINVAL; } } else { @@ -140,6 +143,8 @@ static int mxs_saif_set_clk(struct mxs_saif *saif, scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; } + clk_disable_unprepare(master_saif->clk); + if (ret) return ret; diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 7ac0ba2025c3..c6012ff5bd3e 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -230,8 +230,6 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { /* GTA02 specific routes and controls */ -#ifdef CONFIG_MACH_NEO1973_GTA02 - static int gta02_speaker_enabled; static int lm4853_set_spk(struct snd_kcontrol *kcontrol, @@ -311,10 +309,6 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) return 0; } -#else -static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; } -#endif - static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; @@ -322,10 +316,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) int ret; /* set up NC codec pins */ - if (machine_is_neo1973_gta01()) { - snd_soc_dapm_nc_pin(dapm, "LOUT2"); - snd_soc_dapm_nc_pin(dapm, "ROUT2"); - } snd_soc_dapm_nc_pin(dapm, "OUT3"); snd_soc_dapm_nc_pin(dapm, "OUT4"); snd_soc_dapm_nc_pin(dapm, "LINE1"); @@ -370,50 +360,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) return 0; } -/* GTA01 specific controls */ - -#ifdef CONFIG_MACH_NEO1973_GTA01 - -static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = { - {"Amp IN", NULL, "ROUT1"}, - {"Amp IN", NULL, "LOUT1"}, - - {"Handset Spk", NULL, "Amp EP"}, - {"Stereo Out", NULL, "Amp LS"}, - {"Headphone", NULL, "Amp HP"}, -}; - -static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = { - SND_SOC_DAPM_SPK("Handset Spk", NULL), - SND_SOC_DAPM_SPK("Stereo Out", NULL), - SND_SOC_DAPM_HP("Headphone", NULL), -}; - -static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) -{ - int ret; - - ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets, - ARRAY_SIZE(neo1973_lm4857_dapm_widgets)); - if (ret) - return ret; - - ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes, - ARRAY_SIZE(neo1973_lm4857_routes)); - if (ret) - return ret; - - snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); - snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); - snd_soc_dapm_ignore_suspend(dapm, "Headphone"); - - return 0; -} - -#else -static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; }; -#endif - static struct snd_soc_dai_link neo1973_dai[] = { { /* Hifi Playback - for similatious use with voice below */ .name = "WM8753", @@ -440,11 +386,6 @@ static struct snd_soc_aux_dev neo1973_aux_devs[] = { .name = "dfbmcs320", .codec_name = "dfbmcs320.0", }, - { - .name = "lm4857", - .codec_name = "lm4857.0-007c", - .init = neo1973_lm4857_init, - }, }; static struct snd_soc_codec_conf neo1973_codec_conf[] = { @@ -454,14 +395,10 @@ static struct snd_soc_codec_conf neo1973_codec_conf[] = { }, }; -#ifdef CONFIG_MACH_NEO1973_GTA02 static const struct gpio neo1973_gta02_gpios[] = { { GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" }, { GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" }, }; -#else -static const struct gpio neo1973_gta02_gpios[] = {}; -#endif static struct snd_soc_card neo1973 = { .name = "neo1973", @@ -480,7 +417,7 @@ static int __init neo1973_init(void) { int ret; - if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02()) + if (!machine_is_neo1973_gta02()) return -ENODEV; if (machine_is_neo1973_gta02()) { diff --git a/tools/perf/Makefile b/tools/perf/Makefile index ac86d67b636e..7c12650165ae 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -104,7 +104,7 @@ endif CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) EXTLIBS = -lpthread -lrt -lelf -lm -ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 +ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE ALL_LDFLAGS = $(LDFLAGS) STRIP ?= strip @@ -168,10 +168,7 @@ endif ### --- END CONFIGURATION SECTION --- -# Those must not be GNU-specific; they are shared with perl/ which may -# be built by a different compiler. (Note that this is an artifact now -# but it still might be nice to keep that distinction.) -BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include +BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE BASIC_LDFLAGS = # Guard against environment variables diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 59d43abfbfec..fb8566181f27 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -20,7 +20,6 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ -#define _GNU_SOURCE #include <sys/utsname.h> #include <sys/types.h> #include <sys/stat.h> @@ -31,7 +30,6 @@ #include <stdlib.h> #include <string.h> -#undef _GNU_SOURCE #include "perf.h" #include "builtin.h" #include "util/util.h" diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 8f80df896038..dd162aa24baa 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -89,8 +89,6 @@ void get_term_dimensions(struct winsize *ws) static void perf_top__update_print_entries(struct perf_top *top) { - top->print_entries = top->winsize.ws_row; - if (top->print_entries > 9) top->print_entries -= 9; } @@ -100,6 +98,13 @@ static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *ar struct perf_top *top = arg; get_term_dimensions(&top->winsize); + if (!top->print_entries + || (top->print_entries+4) > top->winsize.ws_row) { + top->print_entries = top->winsize.ws_row; + } else { + top->print_entries += 4; + top->winsize.ws_row = top->print_entries; + } perf_top__update_print_entries(top); } @@ -453,8 +458,10 @@ static void perf_top__handle_keypress(struct perf_top *top, int c) }; perf_top__sig_winch(SIGWINCH, NULL, top); sigaction(SIGWINCH, &act, NULL); - } else + } else { + perf_top__sig_winch(SIGWINCH, NULL, top); signal(SIGWINCH, SIG_DFL); + } break; case 'E': if (top->evlist->nr_entries > 1) { diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 3e7e0b09c12c..ecd7f4dd7eea 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2105,7 +2105,7 @@ int perf_event__synthesize_event_type(struct perf_tool *tool, strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1); ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; - size = strlen(name); + size = strlen(ev.event_type.event_type.name); size = ALIGN(size, sizeof(u64)); ev.event_type.header.size = sizeof(ev.event_type) - (sizeof(ev.event_type.event_type.name) - size); diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index eb25900e2211..29cb65459811 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -19,7 +19,6 @@ * */ -#define _GNU_SOURCE #include <sys/utsname.h> #include <sys/types.h> #include <sys/stat.h> @@ -33,7 +32,6 @@ #include <limits.h> #include <elf.h> -#undef _GNU_SOURCE #include "util.h" #include "event.h" #include "string.h" diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 215d50f2042e..0975438c3e72 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1,4 +1,3 @@ -#define _GNU_SOURCE #include <ctype.h> #include <dirent.h> #include <errno.h> diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 6c164dc9ee95..1a8d4dc4f386 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -21,14 +21,13 @@ * The parts for function graph printing was taken and modified from the * Linux Kernel that were written by Frederic Weisbecker. */ -#define _GNU_SOURCE + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> -#undef _GNU_SOURCE #include "../perf.h" #include "util.h" #include "trace-event.h" diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index 1212a386a033..e81aef1f2569 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c @@ -1,6 +1,4 @@ -#define _GNU_SOURCE #include <stdio.h> -#undef _GNU_SOURCE #include "../libslang.h" #include <stdlib.h> #include <string.h> diff --git a/tools/perf/util/ui/helpline.c b/tools/perf/util/ui/helpline.c index 6ef3c5691762..4f48f5901b30 100644 --- a/tools/perf/util/ui/helpline.c +++ b/tools/perf/util/ui/helpline.c @@ -1,4 +1,3 @@ -#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index b9c530cce79a..ecf9898169c8 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -40,7 +40,6 @@ #define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) #define _ALL_SOURCE 1 -#define _GNU_SOURCE 1 #define _BSD_SOURCE 1 #define HAS_BOOL diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 7287bf5d1c9e..a91f980077d8 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1543,7 +1543,7 @@ void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_memory_slot *memslot, if (memslot && memslot->dirty_bitmap) { unsigned long rel_gfn = gfn - memslot->base_gfn; - if (!__test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap)) + if (!test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap)) memslot->nr_dirty_pages++; } } |