Merge tag 'driver-core-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 26 Jul 2012 18:25:33 +0000 (11:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 26 Jul 2012 18:25:33 +0000 (11:25 -0700)
Pull driver core changes from Greg Kroah-Hartman:
 "Here's the big driver core pull request for 3.6-rc1.

  Unlike 3.5, this kernel should be a lot tamer, with the printk changes
  now settled down.  All we have here is some extcon driver updates, w1
  driver updates, a few printk cleanups that weren't needed for 3.5, but
  are good to have now, and some other minor fixes/changes in the driver
  core.

  All of these have been in the linux-next releases for a while now.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
* tag 'driver-core-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (38 commits)
  printk: Export struct log size and member offsets through vmcoreinfo
  Drivers: hv: Change the hex constant to a decimal constant
  driver core: don't trigger uevent after failure
  extcon: MAX77693: Add extcon-max77693 driver to support Maxim MAX77693 MUIC device
  sysfs: fail dentry revalidation after namespace change fix
  sysfs: fail dentry revalidation after namespace change
  extcon: spelling of detach in function doc
  extcon: arizona: Stop microphone detection if we give up on it
  extcon: arizona: Update cable reporting calls and split headset
  PM / Runtime: Do not increment device usage counts before probing
  kmsg - do not flush partial lines when the console is busy
  kmsg - export "continuation record" flag to /dev/kmsg
  kmsg - avoid warning for CONFIG_PRINTK=n compilations
  kmsg - properly print over-long continuation lines
  driver-core: Use kobj_to_dev instead of re-implementing it
  driver-core: Move kobj_to_dev from genhd.h to device.h
  driver core: Move deferred devices to the end of dpm_list before probing
  driver core: move uevent call to driver_register
  driver core: fix shutdown races with probe/remove(v3)
  Extcon: Arizona: Add driver for Wolfson Arizona class devices
  ...

1  2 
MAINTAINERS
drivers/w1/masters/omap_hdq.c
fs/debugfs/inode.c
fs/sysfs/dir.c
include/linux/device.h
kernel/printk.c

diff --combined MAINTAINERS
@@@ -329,7 -329,7 +329,7 @@@ F: drivers/hwmon/adm1029.
  
  ADM8211 WIRELESS DRIVER
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/
 +W:    http://wireless.kernel.org/
  S:    Orphan
  F:    drivers/net/wireless/adm8211.*
  
@@@ -894,14 -894,6 +894,14 @@@ ARM/MAGICIAN MACHINE SUPPOR
  M:    Philipp Zabel <philipp.zabel@gmail.com>
  S:    Maintained
  
 +ARM/Marvell Armada 370 and Armada XP SOC support
 +M:    Jason Cooper <jason@lakedaemon.net>
 +M:    Andrew Lunn <andrew@lunn.ch>
 +M:    Gregory Clement <gregory.clement@free-electrons.com>
 +L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 +S:    Maintained
 +F:    arch/arm/mach-mvebu/
 +
  ARM/Marvell Dove/Kirkwood/MV78xx0/Orion SOC support
  M:    Jason Cooper <jason@lakedaemon.net>
  M:    Andrew Lunn <andrew@lunn.ch>
@@@ -1111,16 -1103,6 +1111,16 @@@ S:    Supporte
  F:    arch/arm/mach-shmobile/
  F:    drivers/sh/
  
 +ARM/SOCFPGA ARCHITECTURE
 +M:    Dinh Nguyen <dinguyen@altera.com>
 +S:    Maintained
 +F:    arch/arm/mach-socfpga/
 +
 +ARM/SOCFPGA CLOCK FRAMEWORK SUPPORT
 +M:    Dinh Nguyen <dinguyen@altera.com>
 +S:    Maintained
 +F:    drivers/clk/socfpga/
 +
  ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
  M:    Lennert Buytenhek <kernel@wantstofly.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -1441,7 -1423,7 +1441,7 @@@ B43 WIRELESS DRIVE
  M:    Stefano Brivio <stefano.brivio@polimi.it>
  L:    linux-wireless@vger.kernel.org
  L:    b43-dev@lists.infradead.org
 -W:    http://linuxwireless.org/en/users/Drivers/b43
 +W:    http://wireless.kernel.org/en/users/Drivers/b43
  S:    Maintained
  F:    drivers/net/wireless/b43/
  
@@@ -1450,7 -1432,7 +1450,7 @@@ M:      Larry Finger <Larry.Finger@lwfinger.
  M:    Stefano Brivio <stefano.brivio@polimi.it>
  L:    linux-wireless@vger.kernel.org
  L:    b43-dev@lists.infradead.org
 -W:    http://linuxwireless.org/en/users/Drivers/b43
 +W:    http://wireless.kernel.org/en/users/Drivers/b43
  S:    Maintained
  F:    drivers/net/wireless/b43legacy/
  
@@@ -1613,7 -1595,6 +1613,7 @@@ M:      Arend van Spriel <arend@broadcom.com
  M:    Franky (Zhenhui) Lin <frankyl@broadcom.com>
  M:    Kan Yan <kanyan@broadcom.com>
  L:    linux-wireless@vger.kernel.org
 +L:    brcm80211-dev-list@broadcom.com
  S:    Supported
  F:    drivers/net/wireless/brcm80211/
  
@@@ -2728,6 -2709,14 +2728,14 @@@ M:    Mimi Zohar <zohar@us.ibm.com
  S:    Supported
  F:    security/integrity/evm/
  
+ EXTERNAL CONNECTOR SUBSYSTEM (EXTCON)
+ M:    MyungJoo Ham <myungjoo.ham@samsung.com>
+ M:    Chanwoo Choi <cw00.choi@samsung.com>
+ L:    linux-kernel@vger.kernel.org
+ S:    Maintained
+ F:    drivers/extcon/
+ F:    Documentation/extcon/
  EXYNOS DP DRIVER
  M:    Jingoo Han <jg1.han@samsung.com>
  L:    linux-fbdev@vger.kernel.org
@@@ -3452,14 -3441,13 +3460,14 @@@ S:   Supporte
  F:    drivers/idle/i7300_idle.c
  
  IEEE 802.15.4 SUBSYSTEM
 +M:    Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
  M:    Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
 -M:    Sergey Lapin <slapin@ossfans.org>
  L:    linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers)
  W:    http://apps.sourceforge.net/trac/linux-zigbee
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/lowpan/lowpan.git
  S:    Maintained
  F:    net/ieee802154/
 +F:    net/mac802154/
  F:    drivers/ieee802154/
  
  IIO SUBSYSTEM AND DRIVERS
@@@ -3680,6 -3668,14 +3688,6 @@@ T:     git git://git.kernel.org/pub/scm/lin
  S:    Supported
  F:    drivers/net/wireless/iwlwifi/
  
 -INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
 -M:    Samuel Ortiz <samuel.ortiz@intel.com>
 -M:    Intel Linux Wireless <ilw@linux.intel.com>
 -L:    linux-wireless@vger.kernel.org
 -S:    Supported
 -W:    http://wireless.kernel.org/en/users/Drivers/iwmc3200wifi
 -F:    drivers/net/wireless/iwmc3200wifi/
 -
  INTEL MANAGEMENT ENGINE (mei)
  M:    Tomas Winkler <tomas.winkler@intel.com>
  L:    linux-kernel@vger.kernel.org
@@@ -4002,8 -3998,8 +4010,8 @@@ F:      arch/ia64/include/asm/kvm
  F:    arch/ia64/kvm/
  
  KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
 -M:    Carsten Otte <cotte@de.ibm.com>
  M:    Christian Borntraeger <borntraeger@de.ibm.com>
 +M:    Cornelia Huck <cornelia.huck@de.ibm.com>
  M:    linux390@de.ibm.com
  L:    linux-s390@vger.kernel.org
  W:    http://www.ibm.com/developerworks/linux/linux390/
@@@ -4363,7 -4359,7 +4371,7 @@@ F:      arch/m68k/hp300
  MAC80211
  M:    Johannes Berg <johannes@sipsolutions.net>
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/
 +W:    http://wireless.kernel.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
  S:    Maintained
@@@ -4375,7 -4371,7 +4383,7 @@@ MAC80211 PID RATE CONTRO
  M:    Stefano Brivio <stefano.brivio@polimi.it>
  M:    Mattias Nissler <mattias.nissler@gmx.de>
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/PID
 +W:    http://wireless.kernel.org/en/developers/Documentation/mac80211/RateControl/PID
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
  S:    Maintained
@@@ -4604,6 -4600,7 +4612,6 @@@ S:      Maintaine
  F:    drivers/usb/musb/
  
  MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
 -M:    Jon Mason <mason@myri.com>
  M:    Andrew Gallatin <gallatin@myri.com>
  L:    netdev@vger.kernel.org
  W:    http://www.myri.com/scs/download-Myri10GE.html
@@@ -4648,6 -4645,8 +4656,6 @@@ F:      net/sched/sch_netem.
  NETERION 10GbE DRIVERS (s2io/vxge)
  M:    Jon Mason <jdmason@kudzu.us>
  L:    netdev@vger.kernel.org
 -W:    http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous
 -W:    http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous
  S:    Supported
  F:    Documentation/networking/s2io.txt
  F:    Documentation/networking/vxge.txt
@@@ -5058,7 -5057,7 +5066,7 @@@ F:      fs/ocfs2
  
  ORINOCO DRIVER
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/en/users/Drivers/orinoco
 +W:    http://wireless.kernel.org/en/users/Drivers/orinoco
  W:    http://www.nongnu.org/orinoco/
  S:    Orphan
  F:    drivers/net/wireless/orinoco/
@@@ -5210,7 -5209,7 +5218,7 @@@ PCI SUBSYSTE
  M:    Bjorn Helgaas <bhelgaas@google.com>
  L:    linux-pci@vger.kernel.org
  Q:    http://patchwork.ozlabs.org/project/linux-pci/list/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/linux.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
  S:    Supported
  F:    Documentation/PCI/
  F:    drivers/pci/
@@@ -5573,7 -5572,7 +5581,7 @@@ F:      Documentation/networking/LICENSE.qla
  F:    drivers/net/ethernet/qlogic/qla3xxx.*
  
  QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
 -M:    Anirban Chakraborty <anirban.chakraborty@qlogic.com>
 +M:    Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
  M:    Sony Chacko <sony.chacko@qlogic.com>
  M:    linux-driver@qlogic.com
  L:    netdev@vger.kernel.org
@@@ -5581,6 -5580,7 +5589,6 @@@ S:      Supporte
  F:    drivers/net/ethernet/qlogic/qlcnic/
  
  QLOGIC QLGE 10Gb ETHERNET DRIVER
 -M:    Anirban Chakraborty <anirban.chakraborty@qlogic.com>
  M:    Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
  M:    Ron Mercer <ron.mercer@qlogic.com>
  M:    linux-driver@qlogic.com
@@@ -5762,7 -5762,7 +5770,7 @@@ F:      net/rose
  RTL8180 WIRELESS DRIVER
  M:    "John W. Linville" <linville@tuxdriver.com>
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/
 +W:    http://wireless.kernel.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
  S:    Maintained
  F:    drivers/net/wireless/rtl818x/rtl8180/
@@@ -5772,7 -5772,7 +5780,7 @@@ M:      Herton Ronaldo Krzesinski <herton@ca
  M:    Hin-Tak Leung <htl10@users.sourceforge.net>
  M:    Larry Finger <Larry.Finger@lwfinger.net>
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/
 +W:    http://wireless.kernel.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
  S:    Maintained
  F:    drivers/net/wireless/rtl818x/rtl8187/
@@@ -5781,7 -5781,7 +5789,7 @@@ RTL8192CE WIRELESS DRIVE
  M:    Larry Finger <Larry.Finger@lwfinger.net>
  M:    Chaoming Li <chaoming_li@realsil.com.cn>
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/
 +W:    http://wireless.kernel.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
  S:    Maintained
  F:    drivers/net/wireless/rtlwifi/
@@@ -6220,15 -6220,6 +6228,15 @@@ T:    git git://git.kernel.org/pub/scm/lin
  F:    include/linux/srcu*
  F:    kernel/srcu*
  
 +SMACK SECURITY MODULE
 +M:    Casey Schaufler <casey@schaufler-ca.com>
 +L:    linux-security-module@vger.kernel.org
 +W:    http://schaufler-ca.com
 +T:    git git://git.gitorious.org/smack-next/kernel.git
 +S:    Maintained
 +F:    Documentation/security/Smack.txt
 +F:    security/smack/
 +
  SMC91x ETHERNET DRIVER
  M:    Nicolas Pitre <nico@fluxnic.net>
  S:    Odd Fixes
@@@ -6242,9 -6233,9 +6250,9 @@@ F:      Documentation/hwmon/smm66
  F:    drivers/hwmon/smm665.c
  
  SMSC EMC2103 HARDWARE MONITOR DRIVER
 -M:    Steve Glendinning <steve.glendinning@smsc.com>
 +M:    Steve Glendinning <steve.glendinning@shawell.net>
  L:    lm-sensors@lm-sensors.org
 -S:    Supported
 +S:    Maintained
  F:    Documentation/hwmon/emc2103
  F:    drivers/hwmon/emc2103.c
  
@@@ -6263,22 -6254,22 +6271,22 @@@ F:   Documentation/hwmon/smsc47b39
  F:    drivers/hwmon/smsc47b397.c
  
  SMSC911x ETHERNET DRIVER
 -M:    Steve Glendinning <steve.glendinning@smsc.com>
 +M:    Steve Glendinning <steve.glendinning@shawell.net>
  L:    netdev@vger.kernel.org
 -S:    Supported
 +S:    Maintained
  F:    include/linux/smsc911x.h
  F:    drivers/net/ethernet/smsc/smsc911x.*
  
  SMSC9420 PCI ETHERNET DRIVER
 -M:    Steve Glendinning <steve.glendinning@smsc.com>
 +M:    Steve Glendinning <steve.glendinning@shawell.net>
  L:    netdev@vger.kernel.org
 -S:    Supported
 +S:    Maintained
  F:    drivers/net/ethernet/smsc/smsc9420.*
  
  SMSC UFX6000 and UFX7000 USB to VGA DRIVER
 -M:    Steve Glendinning <steve.glendinning@smsc.com>
 +M:    Steve Glendinning <steve.glendinning@shawell.net>
  L:    linux-fbdev@vger.kernel.org
 -S:    Supported
 +S:    Maintained
  F:    drivers/video/smscufx.c
  
  SN-IA64 (Itanium) SUB-PLATFORM
@@@ -6765,11 -6756,9 +6773,11 @@@ F:    include/linux/tifm.
  
  TI LM49xxx FAMILY ASoC CODEC DRIVERS
  M:    M R Swami Reddy <mr.swami.reddy@ti.com>
 +M:    Vishwas A Deshpande <vishwas.a.deshpande@ti.com>
  L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
  S:    Maintained
  F:    sound/soc/codecs/lm49453*
 +F:    sound/soc/codecs/isabelle*
  
  TI TWL4030 SERIES SOC CODEC DRIVER
  M:    Peter Ujfalusi <peter.ujfalusi@ti.com>
@@@ -6863,11 -6852,10 +6871,11 @@@ F:   include/linux/shmem_fs.
  F:    mm/shmem.c
  
  TPM DEVICE DRIVER
 -M:    Debora Velarde <debora@linux.vnet.ibm.com>
 -M:    Rajiv Andrade <srajiv@linux.vnet.ibm.com>
 +M:    Kent Yoder <key@linux.vnet.ibm.com>
 +M:    Rajiv Andrade <mail@srajiv.net>
  W:    http://tpmdd.sourceforge.net
 -M:    Marcel Selhorst <m.selhorst@sirrix.com>
 +M:    Marcel Selhorst <tpmdd@selhorst.net>
 +M:    Sirrix AG <tpmdd@sirrix.com>
  W:    http://www.sirrix.com
  L:    tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
  S:    Maintained
@@@ -6967,13 -6955,6 +6975,13 @@@ S:    Maintaine
  F:    Documentation/filesystems/ufs.txt
  F:    fs/ufs/
  
 +UHID USERSPACE HID IO DRIVER:
 +M:    David Herrmann <dh.herrmann@googlemail.com>
 +L:    linux-input@vger.kernel.org
 +S:    Maintained
 +F:    drivers/hid/uhid.c
 +F:    include/linux/uhid.h
 +
  ULTRA-WIDEBAND (UWB) SUBSYSTEM:
  L:    linux-usb@vger.kernel.org
  S:    Orphan
@@@ -7234,9 -7215,9 +7242,9 @@@ S:      Supporte
  F:    drivers/usb/serial/whiteheat*
  
  USB SMSC95XX ETHERNET DRIVER
 -M:    Steve Glendinning <steve.glendinning@smsc.com>
 +M:    Steve Glendinning <steve.glendinning@shawell.net>
  L:    netdev@vger.kernel.org
 -S:    Supported
 +S:    Maintained
  F:    drivers/net/usb/smsc95xx.*
  
  USB SN9C1xx DRIVER
@@@ -7605,7 -7586,6 +7613,7 @@@ W:      http://opensource.wolfsonmicro.com/c
  S:    Supported
  F:    Documentation/hwmon/wm83??
  F:    arch/arm/mach-s3c64xx/mach-crag6410*
 +F:    drivers/clk/clk-wm83*.c
  F:    drivers/leds/leds-wm83*.c
  F:    drivers/hwmon/wm83??-hwmon.c
  F:    drivers/input/misc/wm831x-on.c
@@@ -1,7 -1,7 +1,7 @@@
  /*
   * drivers/w1/masters/omap_hdq.c
   *
 - * Copyright (C) 2007 Texas Instruments, Inc.
 + * Copyright (C) 2007,2012 Texas Instruments, Inc.
   *
   * This file is licensed under the terms of the GNU General Public License
   * version 2. This program is licensed "as is" without any warranty of any
@@@ -14,9 -14,9 +14,9 @@@
  #include <linux/interrupt.h>
  #include <linux/slab.h>
  #include <linux/err.h>
 -#include <linux/clk.h>
  #include <linux/io.h>
  #include <linux/sched.h>
 +#include <linux/pm_runtime.h>
  
  #include <asm/irq.h>
  #include <mach/hardware.h>
@@@ -61,6 -61,8 +61,6 @@@ struct hdq_data 
        /* lock status update */
        struct  mutex           hdq_mutex;
        int                     hdq_usecount;
 -      struct  clk             *hdq_ick;
 -      struct  clk             *hdq_fck;
        u8                      hdq_irqstatus;
        /* device lock */
        spinlock_t              hdq_spinlock;
@@@ -100,20 -102,20 +100,20 @@@ static struct w1_bus_master omap_w1_mas
  /* HDQ register I/O routines */
  static inline u8 hdq_reg_in(struct hdq_data *hdq_data, u32 offset)
  {
 -      return __raw_readb(hdq_data->hdq_base + offset);
 +      return __raw_readl(hdq_data->hdq_base + offset);
  }
  
  static inline void hdq_reg_out(struct hdq_data *hdq_data, u32 offset, u8 val)
  {
 -      __raw_writeb(val, hdq_data->hdq_base + offset);
 +      __raw_writel(val, hdq_data->hdq_base + offset);
  }
  
  static inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset,
                        u8 val, u8 mask)
  {
 -      u8 new_val = (__raw_readb(hdq_data->hdq_base + offset) & ~mask)
 +      u8 new_val = (__raw_readl(hdq_data->hdq_base + offset) & ~mask)
                        | (val & mask);
 -      __raw_writeb(new_val, hdq_data->hdq_base + offset);
 +      __raw_writel(new_val, hdq_data->hdq_base + offset);
  
        return new_val;
  }
@@@ -178,6 -180,7 +178,7 @@@ static int hdq_write_byte(struct hdq_da
                hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT);
        if (ret == 0) {
                dev_dbg(hdq_data->dev, "TX wait elapsed\n");
+               ret = -ETIMEDOUT;
                goto out;
        }
  
        /* check irqstatus */
        if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) {
                dev_dbg(hdq_data->dev, "timeout waiting for"
-                       "TXCOMPLETE/RXCOMPLETE, %x", *status);
+                       " TXCOMPLETE/RXCOMPLETE, %x", *status);
                ret = -ETIMEDOUT;
                goto out;
        }
                        OMAP_HDQ_FLAG_CLEAR, &tmp_status);
        if (ret) {
                dev_dbg(hdq_data->dev, "timeout waiting GO bit"
-                       "return to zero, %x", tmp_status);
+                       " return to zero, %x", tmp_status);
        }
  
  out:
@@@ -339,7 -342,7 +340,7 @@@ static int omap_hdq_break(struct hdq_da
                        &tmp_status);
        if (ret)
                dev_dbg(hdq_data->dev, "timeout waiting INIT&GO bits"
-                       "return to zero, %x", tmp_status);
+                       " return to zero, %x", tmp_status);
  
  out:
        mutex_unlock(&hdq_data->hdq_mutex);
@@@ -351,7 -354,6 +352,6 @@@ static int hdq_read_byte(struct hdq_dat
  {
        int ret = 0;
        u8 status;
-       unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT;
  
        ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
        if (ret < 0) {
                        OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO,
                        OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO);
                /*
-                * The RX comes immediately after TX. It
-                * triggers another interrupt before we
-                * sleep. So we have to wait for RXCOMPLETE bit.
+                * The RX comes immediately after TX.
                 */
-               while (!(hdq_data->hdq_irqstatus
-                       & OMAP_HDQ_INT_STATUS_RXCOMPLETE)
-                       && time_before(jiffies, timeout)) {
-                       schedule_timeout_uninterruptible(1);
-               }
+               wait_event_timeout(hdq_wait_queue,
+                                  (hdq_data->hdq_irqstatus
+                                   & OMAP_HDQ_INT_STATUS_RXCOMPLETE),
+                                  OMAP_HDQ_TIMEOUT);
                hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, 0,
                        OMAP_HDQ_CTRL_STATUS_DIR);
                status = hdq_data->hdq_irqstatus;
                /* check irqstatus */
                if (!(status & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) {
                        dev_dbg(hdq_data->dev, "timeout waiting for"
-                               "RXCOMPLETE, %x", status);
+                               " RXCOMPLETE, %x", status);
                        ret = -ETIMEDOUT;
                        goto out;
                }
  out:
        mutex_unlock(&hdq_data->hdq_mutex);
  rtn:
-       return 0;
+       return ret;
  
  }
  
@@@ -417,8 -417,17 +415,8 @@@ static int omap_hdq_get(struct hdq_dat
                hdq_data->hdq_usecount++;
                try_module_get(THIS_MODULE);
                if (1 == hdq_data->hdq_usecount) {
 -                      if (clk_enable(hdq_data->hdq_ick)) {
 -                              dev_dbg(hdq_data->dev, "Can not enable ick\n");
 -                              ret = -ENODEV;
 -                              goto clk_err;
 -                      }
 -                      if (clk_enable(hdq_data->hdq_fck)) {
 -                              dev_dbg(hdq_data->dev, "Can not enable fck\n");
 -                              clk_disable(hdq_data->hdq_ick);
 -                              ret = -ENODEV;
 -                              goto clk_err;
 -                      }
 +
 +                      pm_runtime_get_sync(hdq_data->dev);
  
                        /* make sure HDQ is out of reset */
                        if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) &
                }
        }
  
 -clk_err:
 -      clk_put(hdq_data->hdq_ick);
 -      clk_put(hdq_data->hdq_fck);
  out:
        mutex_unlock(&hdq_data->hdq_mutex);
  rtn:
@@@ -456,13 -468,15 +454,13 @@@ static int omap_hdq_put(struct hdq_dat
  
        if (0 == hdq_data->hdq_usecount) {
                dev_dbg(hdq_data->dev, "attempt to decrement use count"
-                       "when it is zero");
+                       " when it is zero");
                ret = -EINVAL;
        } else {
                hdq_data->hdq_usecount--;
                module_put(THIS_MODULE);
 -              if (0 == hdq_data->hdq_usecount) {
 -                      clk_disable(hdq_data->hdq_ick);
 -                      clk_disable(hdq_data->hdq_fck);
 -              }
 +              if (0 == hdq_data->hdq_usecount)
 +                      pm_runtime_put_sync(hdq_data->dev);
        }
        mutex_unlock(&hdq_data->hdq_mutex);
  
@@@ -524,7 -538,7 +522,7 @@@ static void omap_w1_write_byte(void *_h
        mutex_unlock(&hdq_data->hdq_mutex);
  
        ret = hdq_write_byte(hdq_data, byte, &status);
-       if (ret == 0) {
+       if (ret < 0) {
                dev_dbg(hdq_data->dev, "TX failure:Ctrl status %x\n", status);
                return;
        }
@@@ -575,11 -589,35 +573,11 @@@ static int __devinit omap_hdq_probe(str
                goto err_ioremap;
        }
  
 -      /* get interface & functional clock objects */
 -      hdq_data->hdq_ick = clk_get(&pdev->dev, "ick");
 -      if (IS_ERR(hdq_data->hdq_ick)) {
 -              dev_dbg(&pdev->dev, "Can't get HDQ ick clock object\n");
 -              ret = PTR_ERR(hdq_data->hdq_ick);
 -              goto err_ick;
 -      }
 -
 -      hdq_data->hdq_fck = clk_get(&pdev->dev, "fck");
 -      if (IS_ERR(hdq_data->hdq_fck)) {
 -              dev_dbg(&pdev->dev, "Can't get HDQ fck clock object\n");
 -              ret = PTR_ERR(hdq_data->hdq_fck);
 -              goto err_fck;
 -      }
 -
        hdq_data->hdq_usecount = 0;
        mutex_init(&hdq_data->hdq_mutex);
  
 -      if (clk_enable(hdq_data->hdq_ick)) {
 -              dev_dbg(&pdev->dev, "Can not enable ick\n");
 -              ret = -ENODEV;
 -              goto err_intfclk;
 -      }
 -
 -      if (clk_enable(hdq_data->hdq_fck)) {
 -              dev_dbg(&pdev->dev, "Can not enable fck\n");
 -              ret = -ENODEV;
 -              goto err_fnclk;
 -      }
 +      pm_runtime_enable(&pdev->dev);
 +      pm_runtime_get_sync(&pdev->dev);
  
        rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION);
        dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n",
  
        omap_hdq_break(hdq_data);
  
 -      /* don't clock the HDQ until it is needed */
 -      clk_disable(hdq_data->hdq_ick);
 -      clk_disable(hdq_data->hdq_fck);
 +      pm_runtime_put_sync(&pdev->dev);
  
        omap_w1_master.data = hdq_data;
  
  
        return 0;
  
 -err_w1:
  err_irq:
 -      clk_disable(hdq_data->hdq_fck);
 -
 -err_fnclk:
 -      clk_disable(hdq_data->hdq_ick);
 -
 -err_intfclk:
 -      clk_put(hdq_data->hdq_fck);
 -
 -err_fck:
 -      clk_put(hdq_data->hdq_ick);
 +      pm_runtime_put_sync(&pdev->dev);
 +err_w1:
 +      pm_runtime_disable(&pdev->dev);
  
 -err_ick:
        iounmap(hdq_data->hdq_base);
  
  err_ioremap:
@@@ -645,7 -694,8 +643,7 @@@ static int omap_hdq_remove(struct platf
        mutex_unlock(&hdq_data->hdq_mutex);
  
        /* remove module dependency */
 -      clk_put(hdq_data->hdq_ick);
 -      clk_put(hdq_data->hdq_fck);
 +      pm_runtime_disable(&pdev->dev);
        free_irq(INT_24XX_HDQ_IRQ, hdq_data);
        platform_set_drvdata(pdev, NULL);
        iounmap(hdq_data->hdq_base);
diff --combined fs/debugfs/inode.c
@@@ -54,12 -54,13 +54,12 @@@ static struct inode *debugfs_get_inode(
                        break;
                case S_IFLNK:
                        inode->i_op = &debugfs_link_operations;
 -                      inode->i_fop = fops;
                        inode->i_private = data;
                        break;
                case S_IFDIR:
                        inode->i_op = &simple_dir_inode_operations;
 -                      inode->i_fop = fops ? fops : &simple_dir_operations;
 -                      inode->i_private = data;
 +                      inode->i_fop = &simple_dir_operations;
 +                      inode->i_private = NULL;
  
                        /* directory inodes start off with i_nlink == 2
                         * (for "." entry) */
@@@ -90,12 -91,13 +90,12 @@@ static int debugfs_mknod(struct inode *
        return error;
  }
  
 -static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode,
 -                       void *data, const struct file_operations *fops)
 +static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
  {
        int res;
  
        mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
 -      res = debugfs_mknod(dir, dentry, mode, 0, data, fops);
 +      res = debugfs_mknod(dir, dentry, mode, 0, NULL, NULL);
        if (!res) {
                inc_nlink(dir);
                fsnotify_mkdir(dir, dentry);
  }
  
  static int debugfs_link(struct inode *dir, struct dentry *dentry, umode_t mode,
 -                      void *data, const struct file_operations *fops)
 +                      void *data)
  {
        mode = (mode & S_IALLUGO) | S_IFLNK;
 -      return debugfs_mknod(dir, dentry, mode, 0, data, fops);
 +      return debugfs_mknod(dir, dentry, mode, 0, data, NULL);
  }
  
  static int debugfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
@@@ -291,19 -293,13 +291,19 @@@ static struct file_system_type debug_fs
        .kill_sb =      kill_litter_super,
  };
  
 -static int debugfs_create_by_name(const char *name, umode_t mode,
 -                                struct dentry *parent,
 -                                struct dentry **dentry,
 -                                void *data,
 -                                const struct file_operations *fops)
 +struct dentry *__create_file(const char *name, umode_t mode,
 +                                 struct dentry *parent, void *data,
 +                                 const struct file_operations *fops)
  {
 -      int error = 0;
 +      struct dentry *dentry = NULL;
 +      int error;
 +
 +      pr_debug("debugfs: creating file '%s'\n",name);
 +
 +      error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
 +                            &debugfs_mount_count);
 +      if (error)
 +              goto exit;
  
        /* If the parent is not specified, we create it in the root.
         * We need the root dentry to do this, which is in the super 
        if (!parent)
                parent = debugfs_mount->mnt_root;
  
 -      *dentry = NULL;
 +      dentry = NULL;
        mutex_lock(&parent->d_inode->i_mutex);
 -      *dentry = lookup_one_len(name, parent, strlen(name));
 -      if (!IS_ERR(*dentry)) {
 +      dentry = lookup_one_len(name, parent, strlen(name));
 +      if (!IS_ERR(dentry)) {
                switch (mode & S_IFMT) {
                case S_IFDIR:
 -                      error = debugfs_mkdir(parent->d_inode, *dentry, mode,
 -                                            data, fops);
 +                      error = debugfs_mkdir(parent->d_inode, dentry, mode);
 +                                            
                        break;
                case S_IFLNK:
 -                      error = debugfs_link(parent->d_inode, *dentry, mode,
 -                                           data, fops);
 +                      error = debugfs_link(parent->d_inode, dentry, mode,
 +                                           data);
                        break;
                default:
 -                      error = debugfs_create(parent->d_inode, *dentry, mode,
 +                      error = debugfs_create(parent->d_inode, dentry, mode,
                                               data, fops);
                        break;
                }
 -              dput(*dentry);
 +              dput(dentry);
        } else
 -              error = PTR_ERR(*dentry);
 +              error = PTR_ERR(dentry);
        mutex_unlock(&parent->d_inode->i_mutex);
  
 -      return error;
 +      if (error) {
 +              dentry = NULL;
 +              simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 +      }
 +exit:
 +      return dentry;
  }
  
  /**
@@@ -374,15 -365,25 +374,15 @@@ struct dentry *debugfs_create_file(cons
                                   struct dentry *parent, void *data,
                                   const struct file_operations *fops)
  {
 -      struct dentry *dentry = NULL;
 -      int error;
 -
 -      pr_debug("debugfs: creating file '%s'\n",name);
 -
 -      error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
 -                            &debugfs_mount_count);
 -      if (error)
 -              goto exit;
 -
 -      error = debugfs_create_by_name(name, mode, parent, &dentry,
 -                                     data, fops);
 -      if (error) {
 -              dentry = NULL;
 -              simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 -              goto exit;
 +      switch (mode & S_IFMT) {
 +      case S_IFREG:
 +      case 0:
 +              break;
 +      default:
 +              BUG();
        }
 -exit:
 -      return dentry;
 +
 +      return __create_file(name, mode, parent, data, fops);
  }
  EXPORT_SYMBOL_GPL(debugfs_create_file);
  
   */
  struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
  {
 -      return debugfs_create_file(name, 
 -                                 S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
 +      return __create_file(name, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
                                   parent, NULL, NULL);
  }
  EXPORT_SYMBOL_GPL(debugfs_create_dir);
@@@ -444,7 -446,8 +444,7 @@@ struct dentry *debugfs_create_symlink(c
        if (!link)
                return NULL;
  
 -      result = debugfs_create_file(name, S_IFLNK | S_IRWXUGO, parent, link,
 -                                   NULL);
 +      result = __create_file(name, S_IFLNK | S_IRWXUGO, parent, link, NULL);
        if (!result)
                kfree(link);
        return result;
@@@ -495,7 -498,7 +495,7 @@@ void debugfs_remove(struct dentry *dent
        struct dentry *parent;
        int ret;
  
-       if (!dentry)
+       if (IS_ERR_OR_NULL(dentry))
                return;
  
        parent = dentry->d_parent;
@@@ -527,7 -530,7 +527,7 @@@ void debugfs_remove_recursive(struct de
        struct dentry *child;
        struct dentry *parent;
  
-       if (!dentry)
+       if (IS_ERR_OR_NULL(dentry))
                return;
  
        parent = dentry->d_parent;
diff --combined fs/sysfs/dir.c
@@@ -300,15 -300,16 +300,16 @@@ void release_sysfs_dirent(struct sysfs_
  static int sysfs_dentry_delete(const struct dentry *dentry)
  {
        struct sysfs_dirent *sd = dentry->d_fsdata;
 -      return !!(sd->s_flags & SYSFS_FLAG_REMOVED);
 +      return !(sd && !(sd->s_flags & SYSFS_FLAG_REMOVED));
  }
  
 -static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd)
 +static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags)
  {
        struct sysfs_dirent *sd;
        int is_dir;
+       int type;
  
 -      if (nd->flags & LOOKUP_RCU)
 +      if (flags & LOOKUP_RCU)
                return -ECHILD;
  
        sd = dentry->d_fsdata;
        if (strcmp(dentry->d_name.name, sd->s_name) != 0)
                goto out_bad;
  
+       /* The sysfs dirent has been moved to a different namespace */
+       type = KOBJ_NS_TYPE_NONE;
+       if (sd->s_parent) {
+               type = sysfs_ns_type(sd->s_parent);
+               if (type != KOBJ_NS_TYPE_NONE &&
+                               sysfs_info(dentry->d_sb)->ns[type] != sd->s_ns)
+                       goto out_bad;
+       }
        mutex_unlock(&sysfs_mutex);
  out_valid:
        return 1;
@@@ -355,15 -365,18 +365,15 @@@ out_bad
        return 0;
  }
  
 -static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode)
 +static void sysfs_dentry_release(struct dentry *dentry)
  {
 -      struct sysfs_dirent * sd = dentry->d_fsdata;
 -
 -      sysfs_put(sd);
 -      iput(inode);
 +      sysfs_put(dentry->d_fsdata);
  }
  
 -static const struct dentry_operations sysfs_dentry_ops = {
 +const struct dentry_operations sysfs_dentry_ops = {
        .d_revalidate   = sysfs_dentry_revalidate,
        .d_delete       = sysfs_dentry_delete,
 -      .d_iput         = sysfs_dentry_iput,
 +      .d_release      = sysfs_dentry_release,
  };
  
  struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
@@@ -761,7 -774,7 +771,7 @@@ int sysfs_create_dir(struct kobject * k
  }
  
  static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
 -                              struct nameidata *nd)
 +                              unsigned int flags)
  {
        struct dentry *ret = NULL;
        struct dentry *parent = dentry->d_parent;
                ret = ERR_PTR(-ENOENT);
                goto out_unlock;
        }
 +      dentry->d_fsdata = sysfs_get(sd);
  
        /* attach dentry and inode */
        inode = sysfs_get_inode(dir->i_sb, sd);
        }
  
        /* instantiate and hash dentry */
 -      ret = d_find_alias(inode);
 -      if (!ret) {
 -              d_set_d_op(dentry, &sysfs_dentry_ops);
 -              dentry->d_fsdata = sysfs_get(sd);
 -              d_add(dentry, inode);
 -      } else {
 -              d_move(ret, dentry);
 -              iput(inode);
 -      }
 -
 +      ret = d_materialise_unique(dentry, inode);
   out_unlock:
        mutex_unlock(&sysfs_mutex);
        return ret;
diff --combined include/linux/device.h
@@@ -36,7 -36,6 +36,7 @@@ struct subsys_private
  struct bus_type;
  struct device_node;
  struct iommu_ops;
 +struct iommu_group;
  
  struct bus_attribute {
        struct attribute        attr;
@@@ -688,9 -687,13 +688,14 @@@ struct device 
        const struct attribute_group **groups;  /* optional groups */
  
        void    (*release)(struct device *dev);
 +      struct iommu_group      *iommu_group;
  };
  
+ static inline struct device *kobj_to_dev(struct kobject *kobj)
+ {
+       return container_of(kobj, struct device, kobj);
+ }
  /* Get the wakeup routines, which depend on struct device */
  #include <linux/pm_wakeup.h>
  
@@@ -867,6 -870,8 +872,6 @@@ extern int (*platform_notify_remove)(st
  extern struct device *get_device(struct device *dev);
  extern void put_device(struct device *dev);
  
 -extern void wait_for_device_probe(void);
 -
  #ifdef CONFIG_DEVTMPFS
  extern int devtmpfs_create_node(struct device *dev);
  extern int devtmpfs_delete_node(struct device *dev);
diff --combined kernel/printk.c
@@@ -216,6 -216,7 +216,7 @@@ struct log 
   */
  static DEFINE_RAW_SPINLOCK(logbuf_lock);
  
+ #ifdef CONFIG_PRINTK
  /* the next printk record to read by syslog(READ) or /proc/kmsg */
  static u64 syslog_seq;
  static u32 syslog_idx;
@@@ -228,14 -229,19 +229,19 @@@ static u32 log_first_idx
  
  /* index and sequence number of the next record to store in the buffer */
  static u64 log_next_seq;
- #ifdef CONFIG_PRINTK
  static u32 log_next_idx;
  
+ /* the next printk record to write to the console */
+ static u64 console_seq;
+ static u32 console_idx;
+ static enum log_flags console_prev;
  /* the next printk record to read after the last 'clear' command */
  static u64 clear_seq;
  static u32 clear_idx;
  
- #define LOG_LINE_MAX 1024
+ #define PREFIX_MAX            32
+ #define LOG_LINE_MAX          1024 - PREFIX_MAX
  
  /* record buffer */
  #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
@@@ -360,6 -366,7 +366,7 @@@ static void log_store(int facility, in
  struct devkmsg_user {
        u64 seq;
        u32 idx;
+       enum log_flags prev;
        struct mutex lock;
        char buf[8192];
  };
@@@ -425,6 -432,7 +432,7 @@@ static ssize_t devkmsg_read(struct fil
        struct log *msg;
        u64 ts_usec;
        size_t i;
+       char cont = '-';
        size_t len;
        ssize_t ret;
  
        msg = log_from_idx(user->idx);
        ts_usec = msg->ts_nsec;
        do_div(ts_usec, 1000);
-       len = sprintf(user->buf, "%u,%llu,%llu;",
-                     (msg->facility << 3) | msg->level, user->seq, ts_usec);
+       /*
+        * If we couldn't merge continuation line fragments during the print,
+        * export the stored flags to allow an optional external merge of the
+        * records. Merging the records isn't always neccessarily correct, like
+        * when we hit a race during printing. In most cases though, it produces
+        * better readable output. 'c' in the record flags mark the first
+        * fragment of a line, '+' the following.
+        */
+       if (msg->flags & LOG_CONT && !(user->prev & LOG_CONT))
+               cont = 'c';
+       else if ((msg->flags & LOG_CONT) ||
+                ((user->prev & LOG_CONT) && !(msg->flags & LOG_PREFIX)))
+               cont = '+';
+       len = sprintf(user->buf, "%u,%llu,%llu,%c;",
+                     (msg->facility << 3) | msg->level,
+                     user->seq, ts_usec, cont);
+       user->prev = msg->flags;
  
        /* escape non-printable characters */
        for (i = 0; i < msg->text_len; i++) {
@@@ -646,6 -671,15 +671,15 @@@ void log_buf_kexec_setup(void
        VMCOREINFO_SYMBOL(log_buf_len);
        VMCOREINFO_SYMBOL(log_first_idx);
        VMCOREINFO_SYMBOL(log_next_idx);
+       /*
+        * Export struct log size and field offsets. User space tools can
+        * parse it and detect any changes to structure down the line.
+        */
+       VMCOREINFO_STRUCT_SIZE(log);
+       VMCOREINFO_OFFSET(log, ts_nsec);
+       VMCOREINFO_OFFSET(log, len);
+       VMCOREINFO_OFFSET(log, text_len);
+       VMCOREINFO_OFFSET(log, dict_len);
  }
  #endif
  
@@@ -876,7 -910,7 +910,7 @@@ static size_t msg_print_text(const stru
  
                if (buf) {
                        if (print_prefix(msg, syslog, NULL) +
-                           text_len + 1>= size - len)
+                           text_len + 1 >= size - len)
                                break;
  
                        if (prefix)
@@@ -907,7 -941,7 +941,7 @@@ static int syslog_print(char __user *bu
        struct log *msg;
        int len = 0;
  
-       text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
+       text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL);
        if (!text)
                return -ENOMEM;
  
  
                skip = syslog_partial;
                msg = log_from_idx(syslog_idx);
-               n = msg_print_text(msg, syslog_prev, true, text, LOG_LINE_MAX);
+               n = msg_print_text(msg, syslog_prev, true, text,
+                                  LOG_LINE_MAX + PREFIX_MAX);
                if (n - syslog_partial <= size) {
                        /* message fits into buffer, move forward */
                        syslog_idx = log_next(syslog_idx);
@@@ -969,7 -1004,7 +1004,7 @@@ static int syslog_print_all(char __use
        char *text;
        int len = 0;
  
-       text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
+       text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL);
        if (!text)
                return -ENOMEM;
  
                        struct log *msg = log_from_idx(idx);
                        int textlen;
  
-                       textlen = msg_print_text(msg, prev, true, text, LOG_LINE_MAX);
+                       textlen = msg_print_text(msg, prev, true, text,
+                                                LOG_LINE_MAX + PREFIX_MAX);
                        if (textlen < 0) {
                                len = textlen;
                                break;
@@@ -1192,6 -1228,21 +1228,6 @@@ SYSCALL_DEFINE3(syslog, int, type, cha
        return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
  }
  
 -#ifdef        CONFIG_KGDB_KDB
 -/* kdb dmesg command needs access to the syslog buffer.  do_syslog()
 - * uses locks so it cannot be used during debugging.  Just tell kdb
 - * where the start and end of the physical and logical logs are.  This
 - * is equivalent to do_syslog(3).
 - */
 -void kdb_syslog_data(char *syslog_data[4])
 -{
 -      syslog_data[0] = log_buf;
 -      syslog_data[1] = log_buf + log_buf_len;
 -      syslog_data[2] = log_buf + log_first_idx;
 -      syslog_data[3] = log_buf + log_next_idx;
 -}
 -#endif        /* CONFIG_KGDB_KDB */
 -
  static bool __read_mostly ignore_loglevel;
  
  static int __init ignore_loglevel_setup(char *str)
@@@ -1349,20 -1400,36 +1385,36 @@@ static struct cont 
        u64 ts_nsec;                    /* time of first print */
        u8 level;                       /* log level of first message */
        u8 facility;                    /* log level of first message */
+       enum log_flags flags;           /* prefix, newline flags */
        bool flushed:1;                 /* buffer sealed and committed */
  } cont;
  
- static void cont_flush(void)
+ static void cont_flush(enum log_flags flags)
  {
        if (cont.flushed)
                return;
        if (cont.len == 0)
                return;
  
-       log_store(cont.facility, cont.level, LOG_NOCONS, cont.ts_nsec,
-                 NULL, 0, cont.buf, cont.len);
-       cont.flushed = true;
+       if (cont.cons) {
+               /*
+                * If a fragment of this line was directly flushed to the
+                * console; wait for the console to pick up the rest of the
+                * line. LOG_NOCONS suppresses a duplicated output.
+                */
+               log_store(cont.facility, cont.level, flags | LOG_NOCONS,
+                         cont.ts_nsec, NULL, 0, cont.buf, cont.len);
+               cont.flags = flags;
+               cont.flushed = true;
+       } else {
+               /*
+                * If no fragment of this line ever reached the console,
+                * just submit it to the store and free the buffer.
+                */
+               log_store(cont.facility, cont.level, flags, 0,
+                         NULL, 0, cont.buf, cont.len);
+               cont.len = 0;
+       }
  }
  
  static bool cont_add(int facility, int level, const char *text, size_t len)
                return false;
  
        if (cont.len + len > sizeof(cont.buf)) {
-               cont_flush();
+               /* the line gets too long, split it up in separate records */
+               cont_flush(LOG_CONT);
                return false;
        }
  
                cont.level = level;
                cont.owner = current;
                cont.ts_nsec = local_clock();
+               cont.flags = 0;
                cont.cons = 0;
                cont.flushed = false;
        }
  
        memcpy(cont.buf + cont.len, text, len);
        cont.len += len;
+       if (cont.len > (sizeof(cont.buf) * 80) / 100)
+               cont_flush(LOG_CONT);
        return true;
  }
  
@@@ -1394,7 -1467,7 +1452,7 @@@ static size_t cont_print_text(char *tex
        size_t textlen = 0;
        size_t len;
  
-       if (cont.cons == 0) {
+       if (cont.cons == 0 && (console_prev & LOG_NEWLINE)) {
                textlen += print_time(cont.ts_nsec, text);
                size -= textlen;
        }
        }
  
        if (cont.flushed) {
-               text[textlen++] = '\n';
+               if (cont.flags & LOG_NEWLINE)
+                       text[textlen++] = '\n';
                /* got everything, release buffer */
                cont.len = 0;
        }
@@@ -1507,7 -1581,7 +1566,7 @@@ asmlinkage int vprintk_emit(int facilit
                 * or another task also prints continuation lines.
                 */
                if (cont.len && (lflags & LOG_PREFIX || cont.owner != current))
-                       cont_flush();
+                       cont_flush(LOG_NEWLINE);
  
                /* buffer line if possible, otherwise store it right away */
                if (!cont_add(facility, level, text, text_len))
                if (cont.len && cont.owner == current) {
                        if (!(lflags & LOG_PREFIX))
                                stored = cont_add(facility, level, text, text_len);
-                       cont_flush();
+                       cont_flush(LOG_NEWLINE);
                }
  
                if (!stored)
@@@ -1616,9 -1690,20 +1675,20 @@@ asmlinkage int printk(const char *fmt, 
  }
  EXPORT_SYMBOL(printk);
  
- #else
+ #else /* CONFIG_PRINTK */
  
+ #define LOG_LINE_MAX          0
+ #define PREFIX_MAX            0
  #define LOG_LINE_MAX 0
+ static u64 syslog_seq;
+ static u32 syslog_idx;
+ static u64 console_seq;
+ static u32 console_idx;
+ static enum log_flags syslog_prev;
+ static u64 log_first_seq;
+ static u32 log_first_idx;
+ static u64 log_next_seq;
+ static enum log_flags console_prev;
  static struct cont {
        size_t len;
        size_t cons;
@@@ -1902,10 -1987,34 +1972,34 @@@ void wake_up_klogd(void
                this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
  }
  
- /* the next printk record to write to the console */
- static u64 console_seq;
- static u32 console_idx;
- static enum log_flags console_prev;
+ static void console_cont_flush(char *text, size_t size)
+ {
+       unsigned long flags;
+       size_t len;
+       raw_spin_lock_irqsave(&logbuf_lock, flags);
+       if (!cont.len)
+               goto out;
+       /*
+        * We still queue earlier records, likely because the console was
+        * busy. The earlier ones need to be printed before this one, we
+        * did not flush any fragment so far, so just let it queue up.
+        */
+       if (console_seq < log_next_seq && !cont.cons)
+               goto out;
+       len = cont_print_text(text, size);
+       raw_spin_unlock(&logbuf_lock);
+       stop_critical_timings();
+       call_console_drivers(cont.level, text, len);
+       start_critical_timings();
+       local_irq_restore(flags);
+       return;
+ out:
+       raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+ }
  
  /**
   * console_unlock - unlock the console system
   */
  void console_unlock(void)
  {
-       static char text[LOG_LINE_MAX];
+       static char text[LOG_LINE_MAX + PREFIX_MAX];
        static u64 seen_seq;
        unsigned long flags;
        bool wake_klogd = false;
        console_may_schedule = 0;
  
        /* flush buffered message fragment immediately to console */
-       raw_spin_lock_irqsave(&logbuf_lock, flags);
-       if (cont.len && (cont.cons < cont.len || cont.flushed)) {
-               size_t len;
-               len = cont_print_text(text, sizeof(text));
-               raw_spin_unlock(&logbuf_lock);
-               stop_critical_timings();
-               call_console_drivers(cont.level, text, len);
-               start_critical_timings();
-               local_irq_restore(flags);
-       } else
-               raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+       console_cont_flush(text, sizeof(text));
  again:
        for (;;) {
                struct log *msg;
@@@ -1986,6 -2083,7 +2068,7 @@@ skip
                         * will properly dump everything later.
                         */
                        msg->flags &= ~LOG_NOCONS;
+                       console_prev = msg->flags;
                        goto skip;
                }
  
@@@ -2510,7 -2608,7 +2593,7 @@@ void kmsg_dump(enum kmsg_dump_reason re
  }
  
  /**
 - * kmsg_dump_get_line - retrieve one kmsg log line
 + * kmsg_dump_get_line_nolock - retrieve one kmsg log line (unlocked version)
   * @dumper: registered kmsg dumper
   * @syslog: include the "<4>" prefixes
   * @line: buffer to copy the line to
   *
   * A return value of FALSE indicates that there are no more records to
   * read.
 + *
 + * The function is similar to kmsg_dump_get_line(), but grabs no locks.
   */
 -bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
 -                      char *line, size_t size, size_t *len)
 +bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog,
 +                             char *line, size_t size, size_t *len)
  {
 -      unsigned long flags;
        struct log *msg;
        size_t l = 0;
        bool ret = false;
        if (!dumper->active)
                goto out;
  
 -      raw_spin_lock_irqsave(&logbuf_lock, flags);
        if (dumper->cur_seq < log_first_seq) {
                /* messages are gone, move to first available one */
                dumper->cur_seq = log_first_seq;
        }
  
        /* last entry */
 -      if (dumper->cur_seq >= log_next_seq) {
 -              raw_spin_unlock_irqrestore(&logbuf_lock, flags);
 +      if (dumper->cur_seq >= log_next_seq)
                goto out;
 -      }
  
        msg = log_from_idx(dumper->cur_idx);
        l = msg_print_text(msg, 0, syslog, line, size);
        dumper->cur_idx = log_next(dumper->cur_idx);
        dumper->cur_seq++;
        ret = true;
 -      raw_spin_unlock_irqrestore(&logbuf_lock, flags);
  out:
        if (len)
                *len = l;
        return ret;
  }
 +
 +/**
 + * kmsg_dump_get_line - retrieve one kmsg log line
 + * @dumper: registered kmsg dumper
 + * @syslog: include the "<4>" prefixes
 + * @line: buffer to copy the line to
 + * @size: maximum size of the buffer
 + * @len: length of line placed into buffer
 + *
 + * Start at the beginning of the kmsg buffer, with the oldest kmsg
 + * record, and copy one record into the provided buffer.
 + *
 + * Consecutive calls will return the next available record moving
 + * towards the end of the buffer with the youngest messages.
 + *
 + * A return value of FALSE indicates that there are no more records to
 + * read.
 + */
 +bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
 +                      char *line, size_t size, size_t *len)
 +{
 +      unsigned long flags;
 +      bool ret;
 +
 +      raw_spin_lock_irqsave(&logbuf_lock, flags);
 +      ret = kmsg_dump_get_line_nolock(dumper, syslog, line, size, len);
 +      raw_spin_unlock_irqrestore(&logbuf_lock, flags);
 +
 +      return ret;
 +}
  EXPORT_SYMBOL_GPL(kmsg_dump_get_line);
  
  /**
  EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
  
  /**
 + * kmsg_dump_rewind_nolock - reset the interator (unlocked version)
 + * @dumper: registered kmsg dumper
 + *
 + * Reset the dumper's iterator so that kmsg_dump_get_line() and
 + * kmsg_dump_get_buffer() can be called again and used multiple
 + * times within the same dumper.dump() callback.
 + *
 + * The function is similar to kmsg_dump_rewind(), but grabs no locks.
 + */
 +void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper)
 +{
 +      dumper->cur_seq = clear_seq;
 +      dumper->cur_idx = clear_idx;
 +      dumper->next_seq = log_next_seq;
 +      dumper->next_idx = log_next_idx;
 +}
 +
 +/**
   * kmsg_dump_rewind - reset the interator
   * @dumper: registered kmsg dumper
   *
@@@ -2721,7 -2774,10 +2804,7 @@@ void kmsg_dump_rewind(struct kmsg_dumpe
        unsigned long flags;
  
        raw_spin_lock_irqsave(&logbuf_lock, flags);
 -      dumper->cur_seq = clear_seq;
 -      dumper->cur_idx = clear_idx;
 -      dumper->next_seq = log_next_seq;
 -      dumper->next_idx = log_next_idx;
 +      kmsg_dump_rewind_nolock(dumper);
        raw_spin_unlock_irqrestore(&logbuf_lock, flags);
  }
  EXPORT_SYMBOL_GPL(kmsg_dump_rewind);