Merge commit '070680218379e15c1901f4bf21b98e3cbf12b527' into stable/for-linus-fixes-3.3
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Thu, 12 Jan 2012 16:53:55 +0000 (11:53 -0500)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Thu, 12 Jan 2012 16:53:55 +0000 (11:53 -0500)
* commit '070680218379e15c1901f4bf21b98e3cbf12b527': (50 commits)
  xen-balloon: convert sysdev_class to a regular subsystem
  clocksource: convert sysdev_class to a regular subsystem
  ibm_rtl: convert sysdev_class to a regular subsystem
  edac: convert sysdev_class to a regular subsystem
  rtmutex-tester: convert sysdev_class to a regular subsystem
  driver-core: implement 'sysdev' functionality for regular devices and buses
  kref: fix up the kfree build problems
  kref: Remove the memory barriers
  kref: Implement kref_put in terms of kref_sub
  kref: Inline all functions
  Drivers: hv: Get rid of an unnecessary check in hv.c
  Drivers: hv: Make the vmbus driver unloadable
  Drivers: hv: Fix a memory leak
  Documentation: Update stable address
  MAINTAINERS: stable: Update address
  w1: add fast search for single slave bus
  driver-core: skip uevent generation when nobody is listening
  drivers: hv: Don't OOPS when you cannot init vmbus
  firmware: google: fix gsmi.c build warning
  drivers_base: make argument to platform_device_register_full const
  ...

1  2 
MAINTAINERS
drivers/base/core.c
drivers/bluetooth/btusb.c
drivers/net/usb/asix.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/lg-vl600.c
drivers/net/usb/smsc75xx.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/usb/storage/ene_ub6250.c
include/linux/device.h
include/linux/i2c.h

diff --combined MAINTAINERS
@@@ -1106,7 -1106,6 +1106,7 @@@ F:      drivers/media/video/s5p-fimc
  ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
  M:    Kyungmin Park <kyungmin.park@samsung.com>
  M:    Kamil Debski <k.debski@samsung.com>
 +M:     Jeongtae Park <jtp.park@samsung.com>
  L:    linux-arm-kernel@lists.infradead.org
  L:    linux-media@vger.kernel.org
  S:    Maintained
@@@ -1789,14 -1788,6 +1789,14 @@@ F:    include/net/cfg80211.
  F:    net/wireless/*
  X:    net/wireless/wext*
  
 +CHAR and MISC DRIVERS
 +M:    Arnd Bergmann <arnd@arndb.de>
 +M:    Greg Kroah-Hartman <greg@kroah.com>
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
 +S:    Maintained
 +F:    drivers/char/*
 +F:    drivers/misc/*
 +
  CHECKPATCH
  M:    Andy Whitcroft <apw@canonical.com>
  S:    Supported
@@@ -1935,11 -1926,9 +1935,11 @@@ S:    Maintaine
  F:    drivers/connector/
  
  CONTROL GROUPS (CGROUPS)
 -M:    Paul Menage <paul@paulmenage.org>
 +M:    Tejun Heo <tj@kernel.org>
  M:    Li Zefan <lizf@cn.fujitsu.com>
  L:    containers@lists.linux-foundation.org
 +L:    cgroups@vger.kernel.org
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
  S:    Maintained
  F:    include/linux/cgroup*
  F:    kernel/cgroup*
@@@ -2353,13 -2342,6 +2353,13 @@@ S:    Supporte
  F:    drivers/gpu/drm/i915
  F:    include/drm/i915*
  
 +DRM DRIVERS FOR EXYNOS
 +M:    Inki Dae <inki.dae@samsung.com>
 +L:    dri-devel@lists.freedesktop.org
 +S:    Supported
 +F:    drivers/gpu/drm/exynos
 +F:    include/drm/exynos*
 +
  DSCC4 DRIVER
  M:    Francois Romieu <romieu@fr.zoreil.com>
  L:    netdev@vger.kernel.org
@@@ -2594,7 -2576,7 +2594,7 @@@ S:      Maintaine
  F:    drivers/net/ethernet/i825xx/eexpress.*
  
  ETHERNET BRIDGE
 -M:    Stephen Hemminger <shemminger@linux-foundation.org>
 +M:    Stephen Hemminger <shemminger@vyatta.com>
  L:    bridge@lists.linux-foundation.org
  L:    netdev@vger.kernel.org
  W:    http://www.linuxfoundation.org/en/Net:Bridge
@@@ -3728,7 -3710,7 +3728,7 @@@ F:      fs/jbd2
  F:    include/linux/jbd2.h
  
  JSM Neo PCI based serial card
 -M:    Breno Leitao <leitao@linux.vnet.ibm.com>
 +M:    Lucas Tavares <lucaskt@linux.vnet.ibm.com>
  L:    linux-serial@vger.kernel.org
  S:    Maintained
  F:    drivers/tty/serial/jsm/
@@@ -4314,7 -4296,6 +4314,7 @@@ MEMORY RESOURCE CONTROLLE
  M:    Balbir Singh <bsingharora@gmail.com>
  M:    Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
  M:    KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
 +L:    cgroups@vger.kernel.org
  L:    linux-mm@kvack.org
  S:    Maintained
  F:    mm/memcontrol.c
@@@ -4348,7 -4329,7 +4348,7 @@@ MIP
  M:    Ralf Baechle <ralf@linux-mips.org>
  L:    linux-mips@linux-mips.org
  W:    http://www.linux-mips.org/
 -T:    git git://git.linux-mips.org/pub/scm/linux.git
 +T:    git git://git.linux-mips.org/pub/scm/ralf/linux.git
  Q:    http://patchwork.linux-mips.org/project/linux-mips/list/
  S:    Supported
  F:    Documentation/mips/
@@@ -4481,7 -4462,7 +4481,7 @@@ S:      Supporte
  F:    drivers/infiniband/hw/nes/
  
  NETEM NETWORK EMULATOR
 -M:    Stephen Hemminger <shemminger@linux-foundation.org>
 +M:    Stephen Hemminger <shemminger@vyatta.com>
  L:    netem@lists.linux-foundation.org
  S:    Maintained
  F:    net/sched/sch_netem.c
@@@ -4958,7 -4939,7 +4958,7 @@@ F:      drivers/char/ppdev.
  F:    include/linux/ppdev.h
  
  PARAVIRT_OPS INTERFACE
 -M:    Jeremy Fitzhardinge <jeremy@xensource.com>
 +M:    Jeremy Fitzhardinge <jeremy@goop.org>
  M:    Chris Wright <chrisw@sous-sol.org>
  M:    Alok Kataria <akataria@vmware.com>
  M:    Rusty Russell <rusty@rustcorp.com.au>
@@@ -5996,7 -5977,7 +5996,7 @@@ S:      Maintaine
  F:    drivers/usb/misc/sisusbvga/
  
  SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
 -M:    Stephen Hemminger <shemminger@linux-foundation.org>
 +M:    Stephen Hemminger <shemminger@vyatta.com>
  L:    netdev@vger.kernel.org
  S:    Maintained
  F:    drivers/net/ethernet/marvell/sk*
@@@ -6141,7 -6122,7 +6141,7 @@@ F:      sound
  SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
  M:    Liam Girdwood <lrg@ti.com>
  M:    Mark Brown <broonie@opensource.wolfsonmicro.com>
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
  L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
  W:    http://alsa-project.org/main/index.php/ASoC
  S:    Supported
@@@ -6261,7 -6242,7 +6261,7 @@@ F:      arch/alpha/kernel/srm_env.
  
  STABLE BRANCH
  M:    Greg Kroah-Hartman <greg@kroah.com>
- L:    stable@kernel.org
+ L:    stable@vger.kernel.org
  S:    Maintained
  
  STAGING SUBSYSTEM
@@@ -7410,8 -7391,8 +7410,8 @@@ S:      Maintaine
  F:    arch/x86/kernel/cpu/mcheck/*
  
  XEN HYPERVISOR INTERFACE
 -M:    Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
  M:    Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
 +M:    Jeremy Fitzhardinge <jeremy@goop.org>
  L:    xen-devel@lists.xensource.com (moderated for non-subscribers)
  L:    virtualization@lists.linux-foundation.org
  S:    Supported
@@@ -7444,8 -7425,7 +7444,8 @@@ F:      drivers/xen/*swiotlb
  
  XFS FILESYSTEM
  P:    Silicon Graphics Inc
 -M:    Alex Elder <aelder@sgi.com>
 +M:    Ben Myers <bpm@sgi.com>
 +M:    Alex Elder <elder@kernel.org>
  M:    xfs-masters@oss.sgi.com
  L:    xfs@oss.sgi.com
  W:    http://oss.sgi.com/projects/xfs
diff --combined drivers/base/core.c
@@@ -22,7 -22,6 +22,7 @@@
  #include <linux/kallsyms.h>
  #include <linux/mutex.h>
  #include <linux/async.h>
 +#include <linux/pm_runtime.h>
  
  #include "base.h"
  #include "power/power.h"
@@@ -118,6 -117,56 +118,56 @@@ static const struct sysfs_ops dev_sysfs
        .store  = dev_attr_store,
  };
  
+ #define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr)
+ ssize_t device_store_ulong(struct device *dev,
+                          struct device_attribute *attr,
+                          const char *buf, size_t size)
+ {
+       struct dev_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(device_store_ulong);
+ ssize_t device_show_ulong(struct device *dev,
+                         struct device_attribute *attr,
+                         char *buf)
+ {
+       struct dev_ext_attribute *ea = to_ext_attr(attr);
+       return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
+ }
+ EXPORT_SYMBOL_GPL(device_show_ulong);
+ ssize_t device_store_int(struct device *dev,
+                        struct device_attribute *attr,
+                        const char *buf, size_t size)
+ {
+       struct dev_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(device_store_int);
+ ssize_t device_show_int(struct device *dev,
+                       struct device_attribute *attr,
+                       char *buf)
+ {
+       struct dev_ext_attribute *ea = to_ext_attr(attr);
+       return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
+ }
+ EXPORT_SYMBOL_GPL(device_show_int);
  
  /**
   *    device_release - free device structure.
@@@ -464,7 -513,7 +514,7 @@@ static ssize_t show_dev(struct device *
  static struct device_attribute devt_attr =
        __ATTR(dev, S_IRUGO, show_dev, NULL);
  
- /* kset to create /sys/devices/  */
+ /* /sys/devices/ */
  struct kset *devices_kset;
  
  /**
@@@ -711,6 -760,10 +761,10 @@@ static struct kobject *get_device_paren
                return k;
        }
  
+       /* subsystems can specify a default root directory for their devices */
+       if (!parent && dev->bus && dev->bus->dev_root)
+               return &dev->bus->dev_root->kobj;
        if (parent)
                return &parent->kobj;
        return NULL;
@@@ -731,14 -784,6 +785,6 @@@ static void cleanup_device_parent(struc
        cleanup_glue_dir(dev, dev->kobj.parent);
  }
  
- static void setup_parent(struct device *dev, struct device *parent)
- {
-       struct kobject *kobj;
-       kobj = get_device_parent(dev, parent);
-       if (kobj)
-               dev->kobj.parent = kobj;
- }
  static int device_add_class_symlinks(struct device *dev)
  {
        int error;
@@@ -891,6 -936,7 +937,7 @@@ int device_private_init(struct device *
  int device_add(struct device *dev)
  {
        struct device *parent = NULL;
+       struct kobject *kobj;
        struct class_interface *class_intf;
        int error = -EINVAL;
  
                dev->init_name = NULL;
        }
  
+       /* subsystems can specify simple device enumeration */
+       if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
+               dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
        if (!dev_name(dev)) {
                error = -EINVAL;
                goto name_error;
        pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
  
        parent = get_device(dev->parent);
-       setup_parent(dev, parent);
+       kobj = get_device_parent(dev, parent);
+       if (kobj)
+               dev->kobj.parent = kobj;
  
        /* use parent numa_node */
        if (parent)
                               &parent->p->klist_children);
  
        if (dev->class) {
-               mutex_lock(&dev->class->p->class_mutex);
+               mutex_lock(&dev->class->p->mutex);
                /* tie the class to the device */
                klist_add_tail(&dev->knode_class,
                               &dev->class->p->klist_devices);
  
                /* notify any interfaces that the device is here */
                list_for_each_entry(class_intf,
-                                   &dev->class->p->class_interfaces, node)
+                                   &dev->class->p->interfaces, node)
                        if (class_intf->add_dev)
                                class_intf->add_dev(dev, class_intf);
-               mutex_unlock(&dev->class->p->class_mutex);
+               mutex_unlock(&dev->class->p->mutex);
        }
  done:
        put_device(dev);
@@@ -1107,15 -1159,15 +1160,15 @@@ void device_del(struct device *dev
        if (dev->class) {
                device_remove_class_symlinks(dev);
  
-               mutex_lock(&dev->class->p->class_mutex);
+               mutex_lock(&dev->class->p->mutex);
                /* notify any interfaces that the device is now gone */
                list_for_each_entry(class_intf,
-                                   &dev->class->p->class_interfaces, node)
+                                   &dev->class->p->interfaces, node)
                        if (class_intf->remove_dev)
                                class_intf->remove_dev(dev, class_intf);
                /* remove the device from the class list */
                klist_del(&dev->knode_class);
-               mutex_unlock(&dev->class->p->class_mutex);
+               mutex_unlock(&dev->class->p->mutex);
        }
        device_remove_file(dev, &uevent_attr);
        device_remove_attrs(dev);
@@@ -1743,8 -1795,6 +1796,8 @@@ void device_shutdown(void
                 */
                list_del_init(&dev->kobj.entry);
                spin_unlock(&devices_kset->list_lock);
 +              /* Disable all device's runtime power management */
 +              pm_runtime_disable(dev);
  
                if (dev->bus && dev->bus->shutdown) {
                        dev_dbg(dev, "shutdown\n");
@@@ -100,9 -100,6 +100,9 @@@ static struct usb_device_id btusb_table
        /* Canyon CN-BTU1 with HID interfaces */
        { USB_DEVICE(0x0c10, 0x0000) },
  
 +      /* Broadcom BCM20702A0 */
 +      { USB_DEVICE(0x413c, 0x8197) },
 +
        { }     /* Terminating entry */
  };
  
@@@ -1223,20 -1220,7 +1223,7 @@@ static struct usb_driver btusb_driver 
        .supports_autosuspend = 1,
  };
  
- static int __init btusb_init(void)
- {
-       BT_INFO("Generic Bluetooth USB driver ver %s", VERSION);
-       return usb_register(&btusb_driver);
- }
- static void __exit btusb_exit(void)
- {
-       usb_deregister(&btusb_driver);
- }
- module_init(btusb_init);
- module_exit(btusb_exit);
+ module_usb_driver(btusb_driver);
  
  module_param(ignore_dga, bool, 0644);
  MODULE_PARM_DESC(ignore_dga, "Ignore devices with id 08fd:0001");
diff --combined drivers/net/usb/asix.c
@@@ -36,7 -36,7 +36,7 @@@
  #include <linux/usb/usbnet.h>
  #include <linux/slab.h>
  
 -#define DRIVER_VERSION "26-Sep-2011"
 +#define DRIVER_VERSION "08-Nov-2011"
  #define DRIVER_NAME "asix"
  
  /* ASIX AX8817X based USB 2.0 Ethernet Devices */
  #define MARVELL_CTRL_TXDELAY  0x0002
  #define MARVELL_CTRL_RXDELAY  0x0080
  
 -#define       PHY_MODE_RTL8211CL      0x0004
 +#define       PHY_MODE_RTL8211CL      0x000C
  
  /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
  struct asix_data {
@@@ -652,17 -652,9 +652,17 @@@ static u32 asix_get_phyid(struct usbne
  {
        int phy_reg;
        u32 phy_id;
 +      int i;
  
 -      phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1);
 -      if (phy_reg < 0)
 +      /* Poll for the rare case the FW or phy isn't ready yet.  */
 +      for (i = 0; i < 100; i++) {
 +              phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1);
 +              if (phy_reg != 0 && phy_reg != 0xFFFF)
 +                      break;
 +              mdelay(1);
 +      }
 +
 +      if (phy_reg <= 0 || phy_reg == 0xFFFF)
                return 0;
  
        phy_id = (phy_reg & 0xffff) << 16;
@@@ -1083,7 -1075,7 +1083,7 @@@ static const struct net_device_ops ax88
  
  static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
  {
 -      int ret;
 +      int ret, embd_phy;
        struct asix_data *data = (struct asix_data *)&dev->data;
        u8 buf[ETH_ALEN];
        u32 phyid;
        dev->mii.reg_num_mask = 0x1f;
        dev->mii.phy_id = asix_get_phy_addr(dev);
  
 -      phyid = asix_get_phyid(dev);
 -      dbg("PHYID=0x%08x", phyid);
 -
        dev->net->netdev_ops = &ax88772_netdev_ops;
        dev->net->ethtool_ops = &ax88772_ethtool_ops;
  
 -      ret = ax88772_reset(dev);
 +      embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0);
 +
 +      /* Reset the PHY to normal operation mode */
 +      ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
 +      if (ret < 0) {
 +              dbg("Select PHY #1 failed: %d", ret);
 +              return ret;
 +      }
 +
 +      ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL);
 +      if (ret < 0)
 +              return ret;
 +
 +      msleep(150);
 +
 +      ret = asix_sw_reset(dev, AX_SWRESET_CLEAR);
        if (ret < 0)
                return ret;
  
 +      msleep(150);
 +
 +      ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_PRTE);
 +
 +      /* Read PHYID register *AFTER* the PHY was reset properly */
 +      phyid = asix_get_phyid(dev);
 +      dbg("PHYID=0x%08x", phyid);
 +
        /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
        if (dev->driver_info->flags & FLAG_FRAMING_AX) {
                /* hard_mtu  is still the default - the device does not support
@@@ -1248,7 -1220,6 +1248,7 @@@ static int ax88178_reset(struct usbnet 
        __le16 eeprom;
        u8 status;
        int gpio0 = 0;
 +      u32 phyid;
  
        asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status);
        dbg("GPIO Status: 0x%04x", status);
                data->ledmode = 0;
                gpio0 = 1;
        } else {
 -              data->phymode = le16_to_cpu(eeprom) & 7;
 +              data->phymode = le16_to_cpu(eeprom) & 0x7F;
                data->ledmode = le16_to_cpu(eeprom) >> 8;
                gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1;
        }
        dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode);
  
 +      /* Power up external GigaPHY through AX88178 GPIO pin */
        asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40);
        if ((le16_to_cpu(eeprom) >> 8) != 1) {
                asix_write_gpio(dev, 0x003c, 30);
                asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30);
        }
  
 +      /* Read PHYID register *AFTER* powering up PHY */
 +      phyid = asix_get_phyid(dev);
 +      dbg("PHYID=0x%08x", phyid);
 +
 +      /* Set AX88178 to enable MII/GMII/RGMII interface for external PHY */
 +      asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0, 0, 0, NULL);
 +
        asix_sw_reset(dev, 0);
        msleep(150);
  
@@@ -1433,6 -1396,7 +1433,6 @@@ static int ax88178_bind(struct usbnet *
  {
        int ret;
        u8 buf[ETH_ALEN];
 -      u32 phyid;
        struct asix_data *data = (struct asix_data *)&dev->data;
  
        data->eeprom_len = AX88772_EEPROM_LEN;
        dev->net->netdev_ops = &ax88178_netdev_ops;
        dev->net->ethtool_ops = &ax88178_ethtool_ops;
  
 -      phyid = asix_get_phyid(dev);
 -      dbg("PHYID=0x%08x", phyid);
 +      /* Blink LEDS so users know driver saw dongle */
 +      asix_sw_reset(dev, 0);
 +      msleep(150);
  
 -      ret = ax88178_reset(dev);
 -      if (ret < 0)
 -              return ret;
 +      asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD);
 +      msleep(150);
  
        /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
        if (dev->driver_info->flags & FLAG_FRAMING_AX) {
@@@ -1670,17 -1634,7 +1670,7 @@@ static struct usb_driver asix_driver = 
        .supports_autosuspend = 1,
  };
  
- static int __init asix_init(void)
- {
-       return usb_register(&asix_driver);
- }
- module_init(asix_init);
- static void __exit asix_exit(void)
- {
-       usb_deregister(&asix_driver);
- }
- module_exit(asix_exit);
+ module_usb_driver(asix_driver);
  
  MODULE_AUTHOR("David Hollis");
  MODULE_VERSION(DRIVER_VERSION);
@@@ -425,6 -425,9 +425,9 @@@ int usbnet_cdc_bind(struct usbnet *dev
        int                             status;
        struct cdc_state                *info = (void *) &dev->data;
  
+       BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data)
+                       < sizeof(struct cdc_state)));
        status = usbnet_generic_cdc_bind(dev, intf);
        if (status < 0)
                return status;
@@@ -567,7 -570,7 +570,7 @@@ static const struct usb_device_id  produ
  {
        USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM,
                        USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
 -      .driver_info = (unsigned long)&wwan_info,
 +      .driver_info = 0,
  },
  
  /*
@@@ -615,21 -618,7 +618,7 @@@ static struct usb_driver cdc_driver = 
        .supports_autosuspend = 1,
  };
  
- static int __init cdc_init(void)
- {
-       BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data)
-                       < sizeof(struct cdc_state)));
-       return usb_register(&cdc_driver);
- }
- module_init(cdc_init);
- static void __exit cdc_exit(void)
- {
-       usb_deregister(&cdc_driver);
- }
- module_exit(cdc_exit);
+ module_usb_driver(cdc_driver);
  
  MODULE_AUTHOR("David Brownell");
  MODULE_DESCRIPTION("USB CDC Ethernet devices");
@@@ -144,11 -144,10 +144,11 @@@ static int vl600_rx_fixup(struct usbne
        }
  
        frame = (struct vl600_frame_hdr *) buf->data;
 -      /* NOTE: Should check that frame->magic == 0x53544448?
 -       * Otherwise if we receive garbage at the beginning of the frame
 -       * we may end up allocating a huge buffer and saving all the
 -       * future incoming data into it.  */
 +      /* Yes, check that frame->magic == 0x53544448 (or 0x44544d48),
 +       * otherwise we may run out of memory w/a bad packet */
 +      if (ntohl(frame->magic) != 0x53544448 &&
 +                      ntohl(frame->magic) != 0x44544d48)
 +              goto error;
  
        if (buf->len < sizeof(*frame) ||
                        buf->len != le32_to_cpup(&frame->len)) {
@@@ -297,11 -296,6 +297,11 @@@ encapsulate
         * overwrite the remaining fields.
         */
        packet = (struct vl600_pkt_hdr *) skb->data;
 +      /* The VL600 wants IPv6 packets to have an IPv4 ethertype
 +       * Since this modem only supports IPv4 and IPv6, just set all
 +       * frames to 0x0800 (ETH_P_IP)
 +       */
 +      packet->h_proto = htons(ETH_P_IP);
        memset(&packet->dummy, 0, sizeof(packet->dummy));
        packet->len = cpu_to_le32(orig_len);
  
        if (skb->len < full_len) /* Pad */
                skb_put(skb, full_len - skb->len);
  
 -      /* The VL600 wants IPv6 packets to have an IPv4 ethertype
 -       * Check if this is an IPv6 packet, and set the ethertype
 -       * to 0x800
 -       */
 -      if ((skb->data[sizeof(struct vl600_pkt_hdr *) + 0x22] & 0xf0) == 0x60) {
 -              skb->data[sizeof(struct vl600_pkt_hdr *) + 0x20] = 0x08;
 -              skb->data[sizeof(struct vl600_pkt_hdr *) + 0x21] = 0;
 -      }
 -
        return skb;
  }
  
  static const struct driver_info       vl600_info = {
        .description    = "LG VL600 modem",
 -      .flags          = FLAG_ETHER | FLAG_RX_ASSEMBLE,
 +      .flags          = FLAG_RX_ASSEMBLE | FLAG_WWAN,
        .bind           = vl600_bind,
        .unbind         = vl600_unbind,
        .status         = usbnet_cdc_status,
@@@ -346,17 -349,7 +346,7 @@@ static struct usb_driver lg_vl600_drive
        .resume         = usbnet_resume,
  };
  
- static int __init vl600_init(void)
- {
-       return usb_register(&lg_vl600_driver);
- }
- module_init(vl600_init);
- static void __exit vl600_exit(void)
- {
-       usb_deregister(&lg_vl600_driver);
- }
- module_exit(vl600_exit);
+ module_usb_driver(lg_vl600_driver);
  
  MODULE_AUTHOR("Anrzej Zaborowski");
  MODULE_DESCRIPTION("LG-VL600 modem's ethernet link");
@@@ -51,7 -51,6 +51,7 @@@
  #define USB_VENDOR_ID_SMSC            (0x0424)
  #define USB_PRODUCT_ID_LAN7500                (0x7500)
  #define USB_PRODUCT_ID_LAN7505                (0x7505)
 +#define RXW_PADDING                   2
  
  #define check_warn(ret, fmt, args...) \
        ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
@@@ -1089,13 -1088,13 +1089,13 @@@ static int smsc75xx_rx_fixup(struct usb
  
                memcpy(&rx_cmd_b, skb->data, sizeof(rx_cmd_b));
                le32_to_cpus(&rx_cmd_b);
 -              skb_pull(skb, 4 + NET_IP_ALIGN);
 +              skb_pull(skb, 4 + RXW_PADDING);
  
                packet = skb->data;
  
                /* get the packet length */
 -              size = (rx_cmd_a & RX_CMD_A_LEN) - NET_IP_ALIGN;
 -              align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4;
 +              size = (rx_cmd_a & RX_CMD_A_LEN) - RXW_PADDING;
 +              align_count = (4 - ((size + RXW_PADDING) % 4)) % 4;
  
                if (unlikely(rx_cmd_a & RX_CMD_A_RED)) {
                        netif_dbg(dev, rx_err, dev->net,
@@@ -1237,17 -1236,7 +1237,7 @@@ static struct usb_driver smsc75xx_drive
        .disconnect     = usbnet_disconnect,
  };
  
- static int __init smsc75xx_init(void)
- {
-       return usb_register(&smsc75xx_driver);
- }
- module_init(smsc75xx_init);
- static void __exit smsc75xx_exit(void)
- {
-       usb_deregister(&smsc75xx_driver);
- }
- module_exit(smsc75xx_exit);
+ module_usb_driver(smsc75xx_driver);
  
  MODULE_AUTHOR("Nancy Lin");
  MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>");
@@@ -919,7 -919,6 +919,7 @@@ static struct usb_device_id rt2800usb_d
        { USB_DEVICE(0x050d, 0x935b) },
        /* Buffalo */
        { USB_DEVICE(0x0411, 0x00e8) },
 +      { USB_DEVICE(0x0411, 0x0158) },
        { USB_DEVICE(0x0411, 0x016f) },
        { USB_DEVICE(0x0411, 0x01a2) },
        /* Corega */
@@@ -1234,15 -1233,4 +1234,4 @@@ static struct usb_driver rt2800usb_driv
        .resume         = rt2x00usb_resume,
  };
  
- static int __init rt2800usb_init(void)
- {
-       return usb_register(&rt2800usb_driver);
- }
- static void __exit rt2800usb_exit(void)
- {
-       usb_deregister(&rt2800usb_driver);
- }
- module_init(rt2800usb_init);
- module_exit(rt2800usb_exit);
+ module_usb_driver(rt2800usb_driver);
@@@ -1762,9 -1762,10 +1762,9 @@@ static int ms_scsi_write(struct us_dat
                result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
        } else {
                void *buf;
 -              int offset;
 +              int offset = 0;
                u16 PhyBlockAddr;
                u8 PageNum;
 -              u32 result;
                u16 len, oldphy, newphy;
  
                buf = kmalloc(blenByte, GFP_KERNEL);
@@@ -2409,15 -2410,4 +2409,4 @@@ static struct usb_driver ene_ub6250_dri
        .soft_unbind =  1,
  };
  
- static int __init ene_ub6250_init(void)
- {
-       return usb_register(&ene_ub6250_driver);
- }
- static void __exit ene_ub6250_exit(void)
- {
-       usb_deregister(&ene_ub6250_driver);
- }
- module_init(ene_ub6250_init);
- module_exit(ene_ub6250_exit);
+ module_usb_driver(ene_ub6250_driver);
diff --combined include/linux/device.h
@@@ -53,6 -53,8 +53,8 @@@ extern void bus_remove_file(struct bus_
   * struct bus_type - The bus type of the device
   *
   * @name:     The name of the bus.
+  * @dev_name: Used for subsystems to enumerate devices like ("foo%u", dev->id).
+  * @dev_root: Default device to use as the parent.
   * @bus_attrs:        Default attributes of the bus.
   * @dev_attrs:        Default attributes of the devices on the bus.
   * @drv_attrs:        Default attributes of the device drivers on the bus.
@@@ -69,7 -71,7 +71,7 @@@
   * @resume:   Called to bring a device on this bus out of sleep mode.
   * @pm:               Power management operations of this bus, callback the specific
   *            device driver's pm-ops.
 - * @iommu_ops   IOMMU specific operations for this bus, used to attach IOMMU
 + * @iommu_ops:  IOMMU specific operations for this bus, used to attach IOMMU
   *              driver implementations to a bus and allow the driver to do
   *              bus-specific setup
   * @p:                The private data of the driver core, only the driver core can
@@@ -86,6 -88,8 +88,8 @@@
   */
  struct bus_type {
        const char              *name;
+       const char              *dev_name;
+       struct device           *dev_root;
        struct bus_attribute    *bus_attrs;
        struct device_attribute *dev_attrs;
        struct driver_attribute *drv_attrs;
        struct subsys_private *p;
  };
  
- extern int __must_check bus_register(struct bus_type *bus);
+ /* This is a #define to keep the compiler from merging different
+  * instances of the __key variable */
+ #define bus_register(subsys)                  \
+ ({                                            \
+       static struct lock_class_key __key;     \
+       __bus_register(subsys, &__key); \
+ })
+ extern int __must_check __bus_register(struct bus_type *bus,
+                                      struct lock_class_key *key);
  extern void bus_unregister(struct bus_type *bus);
  
  extern int __must_check bus_rescan_devices(struct bus_type *bus);
  
  /* iterator helpers for buses */
+ struct subsys_dev_iter {
+       struct klist_iter               ki;
+       const struct device_type        *type;
+ };
+ void subsys_dev_iter_init(struct subsys_dev_iter *iter,
+                        struct bus_type *subsys,
+                        struct device *start,
+                        const struct device_type *type);
+ struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter);
+ void subsys_dev_iter_exit(struct subsys_dev_iter *iter);
  
  int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data,
                     int (*fn)(struct device *dev, void *data));
@@@ -121,10 -143,10 +143,10 @@@ struct device *bus_find_device(struct b
  struct device *bus_find_device_by_name(struct bus_type *bus,
                                       struct device *start,
                                       const char *name);
+ struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id,
+                                       struct device *hint);
  int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
                     void *data, int (*fn)(struct device_driver *, void *));
  void bus_sort_breadthfirst(struct bus_type *bus,
                           int (*compare)(const struct device *a,
                                          const struct device *b));
@@@ -255,6 -277,33 +277,33 @@@ struct device *driver_find_device(struc
                                  struct device *start, void *data,
                                  int (*match)(struct device *dev, void *data));
  
+ /**
+  * struct subsys_interface - interfaces to device functions
+  * @name        name of the device function
+  * @subsystem   subsytem of the devices to attach to
+  * @node        the list of functions registered at the subsystem
+  * @add         device hookup to device function handler
+  * @remove      device hookup to device function handler
+  *
+  * Simple interfaces attached to a subsystem. Multiple interfaces can
+  * attach to a subsystem and its devices. Unlike drivers, they do not
+  * exclusively claim or control devices. Interfaces usually represent
+  * a specific functionality of a subsystem/class of devices.
+  */
+ struct subsys_interface {
+       const char *name;
+       struct bus_type *subsys;
+       struct list_head node;
+       int (*add_dev)(struct device *dev, struct subsys_interface *sif);
+       int (*remove_dev)(struct device *dev, struct subsys_interface *sif);
+ };
+ int subsys_interface_register(struct subsys_interface *sif);
+ void subsys_interface_unregister(struct subsys_interface *sif);
+ int subsys_system_register(struct bus_type *subsys,
+                          const struct attribute_group **groups);
  /**
   * struct class - device classes
   * @name:     Name of the class.
@@@ -438,8 -487,28 +487,28 @@@ struct device_attribute 
                         const char *buf, size_t count);
  };
  
+ struct dev_ext_attribute {
+       struct device_attribute attr;
+       void *var;
+ };
+ ssize_t device_show_ulong(struct device *dev, struct device_attribute *attr,
+                         char *buf);
+ ssize_t device_store_ulong(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count);
+ ssize_t device_show_int(struct device *dev, struct device_attribute *attr,
+                       char *buf);
+ ssize_t device_store_int(struct device *dev, struct device_attribute *attr,
+                        const char *buf, size_t count);
  #define DEVICE_ATTR(_name, _mode, _show, _store) \
- struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
+       struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
+ #define DEVICE_ULONG_ATTR(_name, _mode, _var) \
+       struct dev_ext_attribute dev_attr_##_name = \
+               { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
+ #define DEVICE_INT_ATTR(_name, _mode, _var) \
+       struct dev_ext_attribute dev_attr_##_name = \
+               { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
  
  extern int __must_check device_create_file(struct device *device,
                                        const struct device_attribute *entry);
@@@ -490,6 -559,9 +559,9 @@@ extern int devres_release_group(struct 
  extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
  extern void devm_kfree(struct device *dev, void *p);
  
+ void __iomem *devm_request_and_ioremap(struct device *dev,
+                       struct resource *res);
  struct device_dma_parameters {
        /*
         * a low level driver may set these to teach IOMMU code about
@@@ -600,6 -672,7 +672,7 @@@ struct device 
        struct device_node      *of_node; /* associated device tree node */
  
        dev_t                   devt;   /* dev_t, creates the sysfs "dev" */
+       u32                     id;     /* device instance */
  
        spinlock_t              devres_lock;
        struct list_head        devres_head;
@@@ -682,11 -755,6 +755,11 @@@ static inline bool device_async_suspend
        return !!dev->power.async_suspend;
  }
  
 +static inline void pm_suspend_ignore_children(struct device *dev, bool enable)
 +{
 +      dev->power.ignore_children = enable;
 +}
 +
  static inline void device_lock(struct device *dev)
  {
        mutex_lock(&dev->mutex);
@@@ -924,4 -992,25 +997,25 @@@ extern long sysfs_deprecated
  #define sysfs_deprecated 0
  #endif
  
+ /**
+  * module_driver() - Helper macro for drivers that don't do anything
+  * special in module init/exit. This eliminates a lot of boilerplate.
+  * Each module may only use this macro once, and calling it replaces
+  * module_init() and module_exit().
+  *
+  * Use this macro to construct bus specific macros for registering
+  * drivers, and do not use it on its own.
+  */
+ #define module_driver(__driver, __register, __unregister) \
+ static int __init __driver##_init(void) \
+ { \
+       return __register(&(__driver)); \
+ } \
+ module_init(__driver##_init); \
+ static void __exit __driver##_exit(void) \
+ { \
+       __unregister(&(__driver)); \
+ } \
+ module_exit(__driver##_exit);
  #endif /* _DEVICE_H_ */
diff --combined include/linux/i2c.h
@@@ -432,6 -432,9 +432,6 @@@ void i2c_unlock_adapter(struct i2c_adap
  /* Internal numbers to terminate lists */
  #define I2C_CLIENT_END                0xfffeU
  
 -/* The numbers to use to set I2C bus address */
 -#define ANY_I2C_BUS           0xffff
 -
  /* Construct an I2C_CLIENT_END-terminated array of i2c addresses */
  #define I2C_ADDRS(addr, addrs...) \
        ((const unsigned short []){ addr, ## addrs, I2C_CLIENT_END })
@@@ -482,6 -485,19 +482,19 @@@ static inline int i2c_adapter_id(struc
  {
        return adap->nr;
  }
+ /**
+  * module_i2c_driver() - Helper macro for registering a I2C driver
+  * @__i2c_driver: i2c_driver struct
+  *
+  * Helper macro for I2C drivers which do not do anything special in module
+  * init/exit. This eliminates a lot of boilerplate. Each module may only
+  * use this macro once, and calling it replaces module_init() and module_exit()
+  */
+ #define module_i2c_driver(__i2c_driver) \
+       module_driver(__i2c_driver, i2c_add_driver, \
+                       i2c_del_driver)
  #endif /* I2C */
  #endif /* __KERNEL__ */