]> git.ipfire.org Git - ipfire-2.x.git/commitdiff
Drop backports
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 8 Apr 2021 10:23:56 +0000 (10:23 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 8 Apr 2021 10:23:56 +0000 (10:23 +0000)
These are some old drivers that we used to pull in from more recent
kernels.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
12 files changed:
lfs/backports [deleted file]
make.sh
src/patches/backports-3.18.1-1-ipfire-build.patch [deleted file]
src/patches/backports-3.18.1-1_add_libertas_uap.patch [deleted file]
src/patches/backports-3.18.1-1_no_dma_sgtable_on_x86_64.patch [deleted file]
src/patches/backports-3.18.1-1_rt2x00usb_suppress_queue_warnings.patch [deleted file]
src/patches/backports-4.2.6-1-add_usbnet_modules.patch [deleted file]
src/patches/backports-4.2.6-1-ath9k_add_missing_mask_init.patch [deleted file]
src/patches/backports-4.2.6-1-grsecurity.patch [deleted file]
src/patches/backports-4.2.6-1-mt7601_upstream_fixes.patch [deleted file]
src/patches/backports-4.2.6-1_ath10k_remove_logspam.patch [deleted file]
src/patches/linux/backports-4.2.6-1_ath10k_remove_logspam.patch [deleted file]

diff --git a/lfs/backports b/lfs/backports
deleted file mode 100644 (file)
index 0ad9b0c..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-###############################################################################
-#                                                                             #
-# IPFire.org - A linux based firewall                                         #
-# Copyright (C) 2007-2018  IPFire Team  <info@ipfire.org>                     #
-#                                                                             #
-# This program is free software: you can redistribute it and/or modify        #
-# it under the terms of the GNU General Public License as published by        #
-# the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.       #
-#                                                                             #
-###############################################################################
-
-###############################################################################
-# Definitions
-###############################################################################
-
-include Config
-
-VERSUFIX   = ipfire$(KCFG)
-
-VER        = 4.2.6-1
-
-THISAPP    = backports-$(VER)
-DL_FILE    = $(THISAPP).tar.xz
-DL_FROM    = $(URL_IPFIRE)
-DIR_APP    = $(DIR_SRC)/$(THISAPP)
-TARGET     = $(DIR_INFO)/$(THISAPP)-kmod-$(KVER)-$(VERSUFIX)
-
-#ifeq "$(BUILD_PLATFORM)" "arm"
-CFLAGS   += -fno-PIC
-#endif
-
-###############################################################################
-# Top-level Rules
-###############################################################################
-
-objects = $(DL_FILE)
-
-$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
-
-$(DL_FILE)_MD5 = 3f978eb56473d9289cf21ebbcb5aa80b
-
-install : $(TARGET)
-
-check : $(patsubst %,$(DIR_CHK)/%,$(objects))
-
-download :$(patsubst %,$(DIR_DL)/%,$(objects))
-
-md5 : $(subst %,%_MD5,$(objects))
-
-dist: 
-       $(PAK)
-
-###############################################################################
-# Downloading, checking, md5sum
-###############################################################################
-
-$(patsubst %,$(DIR_CHK)/%,$(objects)) :
-       @$(CHECK)
-
-$(patsubst %,$(DIR_DL)/%,$(objects)) :
-       @$(LOAD)
-
-$(subst %,%_MD5,$(objects)) :
-       @$(MD5)
-
-###############################################################################
-# Installation Details
-###############################################################################
-
-$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
-       @$(PREBUILD)
-
-       # remove replaced kernel modules
-       rm -rf /lib/modules/$(KVER)-$(VERSUFIX)/kernel/drivers/net/wireless/rtl818x/rtl8180/rtl8180.ko
-       rm -rf /lib/modules/$(KVER)-$(VERSUFIX)/kernel/drivers/media
-
-       @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar Jxf $(DIR_DL)/$(DL_FILE)
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/backports-3.18.1-1-ipfire-build.patch
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/backports-4.2.6-1-grsecurity.patch
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/backports-4.2.6-1-add_usbnet_modules.patch
-ifeq "$(BUILD_ARCH)" "x86_64"
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/backports-3.18.1-1_no_dma_sgtable_on_x86_64.patch
-endif
-
-       # DVB patches
-       cd $(DIR_APP) && patch -Np2 < $(DIR_SRC)/src/patches/v4l-dvb_fix_tua6034_pll.patch
-
-       # Wlan patches
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/compat-drivers-3.8.3-ath_ignore_eeprom_regdomain.patch
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.14.22-iwlwifi-noibss_only_on_radar_chan.patch
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.10.37-rt2800usb_add_dlink_dwa137_usbid.patch
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/backports-3.18.1-1_rt2x00usb_suppress_queue_warnings.patch
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/backports-4.2.6-1-mt7601_upstream_fixes.patch
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/backports-3.18.1-1_add_libertas_uap.patch
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/backports-4.2.6-1_ath10k_remove_logspam.patch
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/backports-4.2.6-1-ath9k_add_missing_mask_init.patch
-
-       # smsc mac address patch for pandaboard and raspberry pi
-ifeq "$(KCFG)" "-multi"
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.10-smsc95xx-add_mac_addr_param.patch
-endif
-ifeq "$(KCFG)" "-rpi"
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.10-smsc95xx-add_mac_addr_param.patch
-endif
-
-       # Patches form stable linux updates
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/backports/backports-linux-upstream-1.patch
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/backports/backports-linux-upstream-2.patch
-       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/backports/backports-linux-upstream-3.patch
-
-       # generate config
-       cd $(DIR_APP) && make KLIB=/lib/modules/$(KVER)-$(VERSUFIX)/ allmodconfig
-
-       # Disable some settings
-       cd $(DIR_APP) && sed -i -e "s/CPTCFG_CFG80211_DEVELOPER_WARNINGS=y/# CPTCFG_CFG80211_DEVELOPER_WARNINGS is not set/g" .config
-       cd $(DIR_APP) && sed -i -e "s/CPTCFG_CFG80211_INTERNAL_REGDB=y/# CPTCFG_CFG80211_INTERNAL_REGDB is not set/g" .config
-       cd $(DIR_APP) && sed -i -e "s/CPTCFG_CFG80211_DEFAULT_PS=y/# CPTCFG_CFG80211_DEFAULT_PS is not set/g" .config
-       cd $(DIR_APP) && sed -i -e "s/CPTCFG_NFC=m/# CPTCFG_NFC is not set/g" .config
-
-ifeq "$(BUILD_ARCH)" "x86_64"
-       cd $(DIR_APP) && sed -i -e "s/CPTCFG_LIBERTAS_UAP=m/# CPTCFG_LIBERTAS_UAP is not set/g" .config
-endif
-
-       # Disable some modules (build fail/missing symbols)
-       cd $(DIR_APP) && sed -i -e "s/CPTCFG_VIDEO_AM437X_VPFE=m/# CPTCFG_VIDEO_AM437X_VPFE is not set/g" .config
-       cd $(DIR_APP) && sed -i -e "s/CPTCFG_VIDEO_VIA_CAMERA=m/# CPTCFG_VIDEO_VIA_CAMERA is not set/g" .config
-       cd $(DIR_APP) && sed -i -e "s/CPTCFG_VIDEO_XILINX=m/# CPTCFG_VIDEO_XILINX is not set/g" .config
-       cd $(DIR_APP) && sed -i -e "s/CPTCFG_IR_SUNXI=m/# CPTCFG_IR_SUNXI is not set/g" .config
-       cd $(DIR_APP) && sed -i -e "s/CPTCFG_BT_6LOWPAN=m/# CPTCFG_BT_6LOWPAN is not set/g" .config
-
-       # Disable DEBUG
-       cd $(DIR_APP) && sed -i -e "s/.*DEBUG=y/# & is not set/g" .config
-       cd $(DIR_APP) && sed -i -e "s/.*DEBUGFS=y/# & is not set/g" .config
-       cd $(DIR_APP) && sed -i -e "s/=y is not set/ is not set/g" .config
-
-       cd $(DIR_APP) && make $(MAKETUNING) KLIB=/lib/modules/$(KVER)-$(VERSUFIX)/ install
-
-       @rm -rf $(DIR_APP)
-       @$(POSTBUILD)
diff --git a/make.sh b/make.sh
index 997caa92cda7c817a537364c4efae98a7f388f2a..829d5da97d9ee66d275eb611e5372f00708b9670 100755 (executable)
--- a/make.sh
+++ b/make.sh
@@ -1196,7 +1196,6 @@ buildipfire() {
   case "${BUILD_ARCH}" in
        x86_64|aarch64)
                lfsmake2 linux                  KCFG=""
-#              lfsmake2 backports                      KCFG=""
 #              lfsmake2 e1000e                 KCFG=""
 #              lfsmake2 igb                            KCFG=""
 #              lfsmake2 ixgbe                  KCFG=""
@@ -1206,7 +1205,6 @@ buildipfire() {
        i586)
                # x86 kernel build
                lfsmake2 linux                  KCFG=""
-#              lfsmake2 backports                      KCFG=""
 #              lfsmake2 e1000e                 KCFG=""
 #              lfsmake2 igb                            KCFG=""
 #              lfsmake2 ixgbe                  KCFG=""
@@ -1217,7 +1215,6 @@ buildipfire() {
        armv5tel)
                # arm multi platform (Panda, Wandboard ...) kernel build
                lfsmake2 linux                  KCFG="-multi"
-#              lfsmake2 backports                      KCFG="-multi"
 #              lfsmake2 e1000e                 KCFG="-multi"
 #              lfsmake2 igb                            KCFG="-multi"
 #              lfsmake2 ixgbe                  KCFG="-multi"
diff --git a/src/patches/backports-3.18.1-1-ipfire-build.patch b/src/patches/backports-3.18.1-1-ipfire-build.patch
deleted file mode 100644 (file)
index 0b2998e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-diff -Naur backports-3.18.1-1.org/Makefile backports-3.18.1-1/Makefile
---- backports-3.18.1-1.org/Makefile    2014-12-21 22:37:13.000000000 +0100
-+++ backports-3.18.1-1/Makefile        2014-12-29 15:51:19.358111370 +0100
-@@ -8,9 +8,9 @@
- SHELL := /bin/bash
- BACKPORT_PWD := $(shell pwd)
--KMODDIR ?= updates
-+KMODDIR ?= kernel
- ifneq ($(origin KLIB), undefined)
--KMODPATH_ARG := "INSTALL_MOD_PATH=$(KLIB)"
-+KMODPATH_ARG :=
- else
- KLIB := /lib/modules/$(shell uname -r)/
- KMODPATH_ARG :=
-diff -Naur backports-3.18.1-1.org/Makefile.real backports-3.18.1-1/Makefile.real
---- backports-3.18.1-1.org/Makefile.real       2014-12-21 22:37:13.000000000 +0100
-+++ backports-3.18.1-1/Makefile.real   2014-12-29 15:51:40.934780933 +0100
-@@ -92,11 +92,11 @@
-       @$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_PWD)                     \
-               INSTALL_MOD_DIR=$(KMODDIR) $(KMODPATH_ARG)              \
-               modules_install
--      @./scripts/blacklist.sh $(KLIB)/ $(KLIB)/$(KMODDIR)
-+#     @./scripts/blacklist.sh $(KLIB)/ $(KLIB)/$(KMODDIR)
-       @./scripts/compress_modules.sh $(KLIB)/$(KMODDIR)
--      @./scripts/check_depmod.sh
--      @/sbin/depmod -a
--      @./scripts/update-initramfs.sh $(KLIB)
-+#     @./scripts/check_depmod.sh
-+#     @/sbin/depmod -a
-+#     @./scripts/update-initramfs.sh $(KLIB)
-       @echo
-       @echo Your backported driver modules should be installed now.
-       @echo Reboot.
diff --git a/src/patches/backports-3.18.1-1_add_libertas_uap.patch b/src/patches/backports-3.18.1-1_add_libertas_uap.patch
deleted file mode 100644 (file)
index 9a5b01b..0000000
+++ /dev/null
@@ -1,5058 +0,0 @@
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/Kconfig backports-3.18.1-1/drivers/net/wireless/Kconfig
---- backports-3.18.1-1.org/drivers/net/wireless/Kconfig        2014-12-21 22:37:15.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/Kconfig    2014-12-29 20:37:43.945764119 +0100
-@@ -55,6 +55,14 @@
-       ---help---
-         A driver for Marvell Libertas 8388 USB devices using thinfirm.
-+config LIBERTAS_UAP
-+      tristate "Marvell 8xxx Libertas UAP"
-+      depends on MAC80211
-+      depends on MMC
-+      select FW_LOADER
-+      ---help---
-+        Driver for Marvell Libertas 8xxx micro AP.
-+
- config AIRO
-       depends on n
-       tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/Makefile backports-3.18.1-1/drivers/net/wireless/libertas_uap/Makefile
---- backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/Makefile  1970-01-01 01:00:00.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/libertas_uap/Makefile      2014-12-29 20:41:50.975778546 +0100
-@@ -0,0 +1,6 @@
-+obj-$(CPTCFG_LIBERTAS_UAP) += uap8xxx.o
-+
-+uap8xxx-y += uap_main.o uap_sdio_mmc.o
-+uap8xxx-$(CPTCFG_PROC_FS) += uap_proc.o uap_debug.o
-+
-+EXTRA_CFLAGS += -DFPNUM='"52"' -DPXA3XX_DMA_ALIGN -DDEBUG_LEVEL1
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_debug.c backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_debug.c
---- backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_debug.c       1970-01-01 01:00:00.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_debug.c   2014-12-29 20:37:43.949097590 +0100
-@@ -0,0 +1,260 @@
-+/** @file uap_debug.c
-+  * @brief This file contains functions for debug proc file.
-+  *
-+  * Copyright (C) 2008-2009, Marvell International Ltd.
-+  *
-+  * This software file (the "File") is distributed by Marvell International
-+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+  * (the "License").  You may use, redistribute and/or modify this File in
-+  * accordance with the terms and conditions of the License, a copy of which
-+  * is available along with the File in the gpl.txt file or by writing to
-+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+  *
-+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
-+  * this warranty disclaimer.
-+  *
-+  */
-+#ifdef CONFIG_PROC_FS
-+#include  "uap_headers.h"
-+
-+/********************************************************
-+              Local Variables
-+********************************************************/
-+
-+#define item_size(n) (sizeof ((uap_adapter *)0)->n)
-+#define item_addr(n) ((u32) &((uap_adapter *)0)->n)
-+
-+#define item_dbg_size(n) (sizeof (((uap_adapter *)0)->dbg.n))
-+#define item_dbg_addr(n) ((u32) &(((uap_adapter *)0)->dbg.n))
-+
-+#define item_dev_size(n) (sizeof ((uap_dev_t *)0)->n)
-+#define item_dev_addr(n) ((u32) &((uap_dev_t *)0)->n)
-+
-+/** MicroAp device offset */
-+#define OFFSET_UAP_DEV                0x01
-+/** Bluetooth adapter offset */
-+#define OFFSET_UAP_ADAPTER    0x02
-+
-+struct debug_data
-+{
-+    /** Name */
-+    char name[32];
-+    /** Size */
-+    u32 size;
-+    /** Address */
-+    u32 addr;
-+    /** Offset */
-+    u32 offset;
-+    /** Flag */
-+    u32 flag;
-+};
-+
-+/* To debug any member of uap_adapter, simply add one line here.
-+ */
-+static struct debug_data items[] = {
-+    {"cmd_sent", item_dev_size(cmd_sent), 0, item_dev_addr(cmd_sent),
-+     OFFSET_UAP_DEV},
-+    {"data_sent", item_dev_size(data_sent), 0, item_dev_addr(data_sent),
-+     OFFSET_UAP_DEV},
-+    {"IntCounter", item_size(IntCounter), 0, item_addr(IntCounter),
-+     OFFSET_UAP_ADAPTER},
-+    {"cmd_pending", item_size(cmd_pending), 0, item_addr(cmd_pending),
-+     OFFSET_UAP_ADAPTER},
-+    {"num_cmd_h2c_fail", item_dbg_size(num_cmd_host_to_card_failure), 0,
-+     item_dbg_addr(num_cmd_host_to_card_failure), OFFSET_UAP_ADAPTER},
-+    {"num_tx_h2c_fail", item_dbg_size(num_tx_host_to_card_failure), 0,
-+     item_dbg_addr(num_tx_host_to_card_failure), OFFSET_UAP_ADAPTER},
-+    {"psmode", item_size(psmode), 0, item_addr(psmode), OFFSET_UAP_ADAPTER},
-+    {"ps_state", item_size(ps_state), 0, item_addr(ps_state),
-+     OFFSET_UAP_ADAPTER},
-+#ifdef DEBUG_LEVEL1
-+    {"drvdbg", sizeof(drvdbg), (u32) & drvdbg, 0, 0}
-+#endif
-+};
-+
-+static int num_of_items = sizeof(items) / sizeof(items[0]);
-+
-+/********************************************************
-+              Global Variables
-+********************************************************/
-+
-+/********************************************************
-+              Local Functions
-+********************************************************/
-+/**
-+ *  @brief proc read function
-+ *
-+ *  @param page          pointer to buffer
-+ *  @param s       read data starting position
-+ *  @param off     offset
-+ *  @param cnt     counter
-+ *  @param eof     end of file flag
-+ *  @param data    data to output
-+ *  @return      number of output data
-+ */
-+static int uap_debug_proc_show(struct seq_file *s, void *data) {
-+    int val = 0;
-+    int i;
-+
-+    struct debug_data *d = (struct debug_data *)s->private;
-+
-+    if (MODULE_GET == 0)
-+        return UAP_STATUS_FAILURE;
-+
-+    for (i = 0; i < num_of_items; i++) {
-+        if (d[i].size == 1)
-+            val = *((u8 *) d[i].addr);
-+        else if (d[i].size == 2)
-+            val = *((u16 *) d[i].addr);
-+        else if (d[i].size == 4)
-+            val = *((u32 *) d[i].addr);
-+
-+        seq_printf(s, "%s=%d\n", d[i].name, val);
-+    }
-+    MODULE_PUT;
-+    return 0;
-+}
-+
-+static int uap_debug_proc_open(struct inode* inode, struct file* file) {
-+      return single_open(file, uap_debug_proc_show, PDE_DATA(inode));
-+}
-+
-+/**
-+ *  @brief proc write function
-+ *
-+ *  @param f     file pointer
-+ *  @param buf     pointer to data buffer
-+ *  @param cnt     data number to write
-+ *  @param data    data to write
-+ *  @return      number of data
-+ */
-+static ssize_t uap_debug_proc_write(struct file *f, const char __user *buf, size_t cnt, loff_t *data) {
-+    int r, i;
-+    char *pdata;
-+    char *p;
-+    char *p0;
-+    char *p1;
-+    char *p2;
-+    struct debug_data *d = (struct debug_data *)PDE_DATA(file_inode(f));
-+
-+    if (MODULE_GET == 0)
-+        return UAP_STATUS_FAILURE;
-+
-+    pdata = (char *) kmalloc(cnt, GFP_KERNEL);
-+    if (pdata == NULL) {
-+        MODULE_PUT;
-+        return 0;
-+    }
-+
-+    if (copy_from_user(pdata, buf, cnt)) {
-+        PRINTM(INFO, "Copy from user failed\n");
-+        kfree(pdata);
-+        MODULE_PUT;
-+        return 0;
-+    }
-+
-+    p0 = pdata;
-+    for (i = 0; i < num_of_items; i++) {
-+        do {
-+            p = strstr(p0, d[i].name);
-+            if (p == NULL)
-+                break;
-+            p1 = strchr(p, '\n');
-+            if (p1 == NULL)
-+                break;
-+            p0 = p1++;
-+            p2 = strchr(p, '=');
-+            if (!p2)
-+                break;
-+            p2++;
-+            r = string_to_number(p2);
-+            if (d[i].size == 1)
-+                *((u8 *) d[i].addr) = (u8) r;
-+            else if (d[i].size == 2)
-+                *((u16 *) d[i].addr) = (u16) r;
-+            else if (d[i].size == 4)
-+                *((u32 *) d[i].addr) = (u32) r;
-+            break;
-+        } while (TRUE);
-+    }
-+    kfree(pdata);
-+#ifdef DEBUG_LEVEL1
-+    printk(KERN_ALERT "drvdbg = 0x%x\n", drvdbg);
-+    printk(KERN_ALERT "INFO  (%08lx) %s\n", DBG_INFO,
-+           (drvdbg & DBG_INFO) ? "X" : "");
-+    printk(KERN_ALERT "WARN  (%08lx) %s\n", DBG_WARN,
-+           (drvdbg & DBG_WARN) ? "X" : "");
-+    printk(KERN_ALERT "ENTRY (%08lx) %s\n", DBG_ENTRY,
-+           (drvdbg & DBG_ENTRY) ? "X" : "");
-+    printk(KERN_ALERT "CMD_D (%08lx) %s\n", DBG_CMD_D,
-+           (drvdbg & DBG_CMD_D) ? "X" : "");
-+    printk(KERN_ALERT "DAT_D (%08lx) %s\n", DBG_DAT_D,
-+           (drvdbg & DBG_DAT_D) ? "X" : "");
-+    printk(KERN_ALERT "CMND  (%08lx) %s\n", DBG_CMND,
-+           (drvdbg & DBG_CMND) ? "X" : "");
-+    printk(KERN_ALERT "DATA  (%08lx) %s\n", DBG_DATA,
-+           (drvdbg & DBG_DATA) ? "X" : "");
-+    printk(KERN_ALERT "ERROR (%08lx) %s\n", DBG_ERROR,
-+           (drvdbg & DBG_ERROR) ? "X" : "");
-+    printk(KERN_ALERT "FATAL (%08lx) %s\n", DBG_FATAL,
-+           (drvdbg & DBG_FATAL) ? "X" : "");
-+    printk(KERN_ALERT "MSG   (%08lx) %s\n", DBG_MSG,
-+           (drvdbg & DBG_MSG) ? "X" : "");
-+#endif
-+    MODULE_PUT;
-+    return cnt;
-+}
-+
-+static const struct file_operations uap_debug_proc_fops = {
-+      .owner   = THIS_MODULE,
-+      .open    = uap_debug_proc_open,
-+      .read    = seq_read,
-+      .llseek  = seq_lseek,
-+      .release = single_release,
-+      .write   = uap_debug_proc_write,
-+};
-+
-+/********************************************************
-+              Global Functions
-+********************************************************/
-+/**
-+ *  @brief create debug proc file
-+ *
-+ *  @param priv          pointer uap_private
-+ *  @param dev     pointer net_device
-+ *  @return      N/A
-+ */
-+void
-+uap_debug_entry(uap_private * priv, struct net_device *dev)
-+{
-+    int i;
-+
-+    if (priv->proc_entry == NULL)
-+        return;
-+
-+    for (i = 0; i < num_of_items; i++) {
-+        if (items[i].flag & OFFSET_UAP_ADAPTER)
-+            items[i].addr = items[i].offset + (u32) priv->adapter;
-+        if (items[i].flag & OFFSET_UAP_DEV)
-+            items[i].addr = items[i].offset + (u32) & priv->uap_dev;
-+    }
-+    proc_create_data("debug", 0644, priv->proc_entry, &uap_debug_proc_fops,
-+      &items[0]);
-+}
-+
-+/**
-+ *  @brief remove proc file
-+ *
-+ *  @param priv          pointer uap_private
-+ *  @return      N/A
-+ */
-+void
-+uap_debug_remove(uap_private * priv)
-+{
-+    remove_proc_entry("debug", priv->proc_entry);
-+}
-+
-+#endif
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_drv.h backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_drv.h
---- backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_drv.h 1970-01-01 01:00:00.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_drv.h     2014-12-29 20:37:43.949097590 +0100
-@@ -0,0 +1,667 @@
-+/** @file uap_drv.h
-+  * @brief This file contains Linux OS related definitions and
-+  * declarations, uAP driver
-+  *
-+  * Copyright (C) 2008-2009, Marvell International Ltd.
-+  *
-+  * This software file (the "File") is distributed by Marvell International
-+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+  * (the "License").  You may use, redistribute and/or modify this File in
-+  * accordance with the terms and conditions of the License, a copy of which
-+  * is available along with the File in the gpl.txt file or by writing to
-+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+  *
-+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
-+  * this warranty disclaimer.
-+  *
-+  */
-+
-+#ifndef _UAP_DRV_H
-+#define _UAP_DRV_H
-+
-+/** Driver release version */
-+#define DRIVER_VERSION                "26146"
-+
-+/** True */
-+#ifndef       TRUE
-+#define TRUE                  1
-+#endif
-+/** False */
-+#ifndef       FALSE
-+#define       FALSE                   0
-+#endif
-+
-+/** Bit definitions */
-+#ifndef BIT
-+#define BIT(x)        (1UL << (x))
-+#endif
-+
-+/** Dma addresses are 32-bits wide.  */
-+#ifndef __ATTRIB_ALIGN__
-+#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
-+#endif
-+
-+/**  attribute pack */
-+#ifndef __ATTRIB_PACK__
-+#define __ATTRIB_PACK__ __attribute__ ((packed))
-+#endif
-+
-+/** Debug Macro definition*/
-+#ifdef        DEBUG_LEVEL1
-+
-+extern u32 drvdbg;
-+
-+/** Debug message control bit definition for drvdbg */
-+/** Debug message */
-+#define       DBG_MSG         BIT(0)
-+/** Debug fatal message */
-+#define DBG_FATAL     BIT(1)
-+/** Debug error message */
-+#define DBG_ERROR     BIT(2)
-+/** Debug data message */
-+#define DBG_DATA      BIT(3)
-+/** Debug command message */
-+#define DBG_CMND      BIT(4)
-+
-+/** Debug data */
-+#define DBG_DAT_D     BIT(16)
-+/** Debug command */
-+#define DBG_CMD_D     BIT(17)
-+
-+/** Debug entry */
-+#define DBG_ENTRY     BIT(28)
-+/** Debug warning */
-+#define DBG_WARN      BIT(29)
-+/** Debug info */
-+#define DBG_INFO      BIT(30)
-+
-+/** Print info */
-+#define       PRINTM_INFO(msg...)  {if (drvdbg & DBG_INFO) printk(KERN_DEBUG msg);}
-+/** Print warn message */
-+#define       PRINTM_WARN(msg...)  {if (drvdbg & DBG_WARN) printk(KERN_DEBUG msg);}
-+/** Print entry */
-+#define       PRINTM_ENTRY(msg...) {if (drvdbg & DBG_ENTRY) printk(KERN_DEBUG msg);}
-+/** Print cmd_d */
-+#define       PRINTM_CMD_D(msg...) {if (drvdbg & DBG_CMD_D) printk(KERN_DEBUG msg);}
-+/** Print data_d */
-+#define       PRINTM_DAT_D(msg...) {if (drvdbg & DBG_DAT_D) printk(KERN_DEBUG msg);}
-+/** Print command */
-+#define       PRINTM_CMND(msg...)  {if (drvdbg & DBG_CMND) printk(KERN_DEBUG msg);}
-+/** Print data */
-+#define       PRINTM_DATA(msg...)  {if (drvdbg & DBG_DATA) printk(KERN_DEBUG msg);}
-+/** Print error message */
-+#define       PRINTM_ERROR(msg...) {if (drvdbg & DBG_ERROR) printk(KERN_DEBUG msg);}
-+/** Print fatal message */
-+#define       PRINTM_FATAL(msg...) {if (drvdbg & DBG_FATAL) printk(KERN_DEBUG msg);}
-+/** Print message */
-+#define       PRINTM_MSG(msg...)   {if (drvdbg & DBG_MSG) printk(KERN_ALERT msg);}
-+/** Print level */
-+#define       PRINTM(level,msg...) PRINTM_##level(msg)
-+
-+#else
-+
-+#define       PRINTM(level,msg...) do {} while (0)
-+
-+#endif /* DEBUG_LEVEL1 */
-+
-+/** Wait until a condition becomes true */
-+#define ASSERT(cond)                                          \
-+do {                                                          \
-+      if (!(cond))                                            \
-+              PRINTM(INFO, "ASSERT: %s, %s:%i\n",             \
-+                     __FUNCTION__, __FILE__, __LINE__);       \
-+} while(0)
-+
-+/** Log enrty point for debugging */
-+#define       ENTER()                 PRINTM(ENTRY, "Enter: %s, %s:%i\n", __FUNCTION__, \
-+                                                      __FILE__, __LINE__)
-+/** Log exit point for debugging */
-+#define       LEAVE()                 PRINTM(ENTRY, "Leave: %s, %s:%i\n", __FUNCTION__, \
-+                                                      __FILE__, __LINE__)
-+
-+#ifdef        DEBUG_LEVEL1
-+/** Dump buffer length */
-+#define DBG_DUMP_BUF_LEN    64
-+/** Maximum dump per line */
-+#define MAX_DUMP_PER_LINE   16
-+/** Data dump length */
-+#define DATA_DUMP_LEN       32
-+
-+static inline void
-+hexdump(char *prompt, u8 * buf, int len)
-+{
-+    int i;
-+    char dbgdumpbuf[DBG_DUMP_BUF_LEN];
-+    char *ptr = dbgdumpbuf;
-+
-+    printk(KERN_DEBUG "%s:\n", prompt);
-+    for (i = 1; i <= len; i++) {
-+        ptr += sprintf(ptr, "%02x ", *buf);
-+        buf++;
-+        if (i % MAX_DUMP_PER_LINE == 0) {
-+            *ptr = 0;
-+            printk(KERN_DEBUG "%s\n", dbgdumpbuf);
-+            ptr = dbgdumpbuf;
-+        }
-+    }
-+    if (len % MAX_DUMP_PER_LINE) {
-+        *ptr = 0;
-+        printk(KERN_DEBUG "%s\n", dbgdumpbuf);
-+    }
-+}
-+
-+/** Debug command */
-+#define DBG_HEXDUMP_CMD_D(x,y,z)    {if (drvdbg & DBG_CMD_D) hexdump(x,y,z);}
-+/** Debug data */
-+#define DBG_HEXDUMP_DAT_D(x,y,z)    {if (drvdbg & DBG_DAT_D) hexdump(x,y,z);}
-+/** Debug hexdump */
-+#define       DBG_HEXDUMP(level,x,y,z)    DBG_HEXDUMP_##level(x,y,z)
-+/** hexdump */
-+#define HEXDUMP(x,y,z)              {if (drvdbg & DBG_INFO) hexdump(x,y,z);}
-+#else
-+/** Do nothing since debugging is not turned on */
-+#define DBG_HEXDUMP(level,x,y,z)    do {} while (0)
-+/** Do nothing since debugging is not turned on */
-+#define HEXDUMP(x,y,z)              do {} while (0)
-+#endif
-+
-+/**
-+ * Typedefs
-+ */
-+/** Unsigned char */
-+typedef u8 BOOLEAN;
-+
-+/*
-+ * OS macro definitions
-+ */
-+/** OS macro to get time */
-+#define os_time_get() jiffies
-+
-+/** OS macro to update transfer start time */
-+#define UpdateTransStart(dev) { \
-+      dev->trans_start = jiffies; \
-+}
-+
-+/** Try to get a reference to the module */
-+#define MODULE_GET    try_module_get(THIS_MODULE)
-+/** Decrease module reference count */
-+#define MODULE_PUT    module_put(THIS_MODULE)
-+
-+/** OS macro to initialize semaphore */
-+#define OS_INIT_SEMAPHORE(x)  sema_init(x,1)
-+/** OS macro to acquire blocking semaphore */
-+#define OS_ACQ_SEMAPHORE_BLOCK(x)     down_interruptible(x)
-+/** OS macro to acquire non-blocking semaphore */
-+#define OS_ACQ_SEMAPHORE_NOBLOCK(x)   down_trylock(x)
-+/** OS macro to release semaphore */
-+#define OS_REL_SEMAPHORE(x)           up(x)
-+
-+static inline void
-+os_sched_timeout(u32 millisec)
-+{
-+    set_current_state(TASK_INTERRUPTIBLE);
-+    schedule_timeout((millisec * HZ) / 1000);
-+}
-+
-+/** Maximum size of ethernet packet */
-+#define MRVDRV_MAXIMUM_ETH_PACKET_SIZE        1514
-+
-+/** Maximum size of multicast list */
-+#define MRVDRV_MAX_MULTICAST_LIST_SIZE        32
-+
-+/** Find minimum */
-+#ifndef MIN
-+#define MIN(a,b)              ((a) < (b) ? (a) : (b))
-+#endif
-+
-+/** Find maximum */
-+#ifndef MAX
-+#define MAX(a,b)              ((a) > (b) ? (a) : (b))
-+#endif
-+
-+/** Find number of elements */
-+#ifndef NELEMENTS
-+#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
-+#endif
-+
-+/** Buffer Constants */
-+
-+/** Size of command buffer */
-+#define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
-+
-+/** Length of device length */
-+#define DEV_NAME_LEN                  32
-+
-+/** Length of ethernet address */
-+#ifndef       ETH_ALEN
-+#define ETH_ALEN                      6
-+#endif
-+
-+/** Default watchdog timeout */
-+#define MRVDRV_DEFAULT_WATCHDOG_TIMEOUT (2 * HZ)
-+
-+/** Success */
-+#define UAP_STATUS_SUCCESS         (0)
-+/** Failure */
-+#define UAP_STATUS_FAILURE         (-1)
-+/** Not accepted */
-+#define UAP_STATUS_NOT_ACCEPTED    (-2)
-+
-+/** Max loop count (* 100ms) for waiting device ready at init time */
-+#define MAX_WAIT_DEVICE_READY_COUNT   50
-+
-+/** Tx high watermark. Stop Tx queue after this is crossed */
-+#define TX_HIGH_WATERMARK   4
-+/** Tx low watermark. Restart Tx queue after this is crossed */
-+#define TX_LOW_WATERMARK    2
-+
-+/** Netlink protocol number */
-+#define NETLINK_MARVELL     (MAX_LINKS - 1)
-+/** Netlink maximum payload size */
-+#define NL_MAX_PAYLOAD      1024
-+/** Netlink multicast group number */
-+#define NL_MULTICAST_GROUP  1
-+
-+/** 20 seconds */
-+#define MRVDRV_TIMER_20S              20000
-+
-+/** Host Command option for wait till Send */
-+#define HostCmd_OPTION_WAITFORSEND            0x0001
-+/** Host Command option for wait for RSP */
-+#define HostCmd_OPTION_WAITFORRSP             0x0002
-+/** Host Command option for wait for RSP or Timeout */
-+#define HostCmd_OPTION_WAITFORRSP_TIMEOUT     0x0003
-+/** Host Command option for wait for RSP of sleep confirm */
-+#define HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM   0x0004
-+
-+/** Sleep until a condition gets true or a timeout elapses */
-+#define os_wait_interruptible_timeout(waitq, cond, timeout) \
-+      wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000))
-+
-+/** Private command ID to Host command */
-+#define       UAPHOSTCMD                      (SIOCDEVPRIVATE + 1)
-+
-+/** Private command ID to Power Mode */
-+#define       UAP_POWER_MODE                  (SIOCDEVPRIVATE + 3)
-+/** sleep_param */
-+typedef struct _ps_sleep_param
-+{
-+    /** control bitmap */
-+    u32 ctrl_bitmap;
-+    /** minimum sleep period (micro second) */
-+    u32 min_sleep;
-+    /** maximum sleep period (micro second) */
-+    u32 max_sleep;
-+} ps_sleep_param;
-+
-+/** inactivity sleep_param */
-+typedef struct _inact_sleep_param
-+{
-+    /** inactivity timeout (micro second) */
-+    u32 inactivity_to;
-+    /** miniumu awake period (micro second) */
-+    u32 min_awake;
-+    /** maximum awake period (micro second) */
-+    u32 max_awake;
-+} inact_sleep_param;
-+
-+/** flag for ps mode */
-+#define PS_FLAG_PS_MODE                 1
-+/** flag for sleep param */
-+#define PS_FLAG_SLEEP_PARAM             2
-+/** flag for inactivity sleep param */
-+#define PS_FLAG_INACT_SLEEP_PARAM       4
-+
-+/** Disable power mode */
-+#define PS_MODE_DISABLE                      0
-+/** Enable periodic dtim ps */
-+#define PS_MODE_PERIODIC_DTIM                1
-+/** Enable inactivity ps */
-+#define PS_MODE_INACTIVITY                   2
-+
-+/** sleep parameter */
-+#define SLEEP_PARAMETER                     1
-+/** inactivity sleep parameter */
-+#define INACTIVITY_SLEEP_PARAMETER          2
-+/** ps_mgmt */
-+typedef struct _ps_mgmt
-+{
-+    /** flags for valid field */
-+    u16 flags;
-+    /** power mode */
-+    u16 ps_mode;
-+    /** sleep param */
-+    ps_sleep_param sleep_param;
-+    /** inactivity sleep param */
-+    inact_sleep_param inact_param;
-+} ps_mgmt;
-+
-+/** Semaphore structure */
-+typedef struct semaphore SEMAPHORE;
-+
-+/** Global Varibale Declaration */
-+/** Private data structure of the device */
-+typedef struct _uap_private uap_private;
-+/** Adapter data structure of the device */
-+typedef struct _uap_adapter uap_adapter;
-+/** private structure */
-+extern uap_private *uappriv;
-+
-+/** ENUM definition*/
-+
-+/** Hardware status codes */
-+typedef enum _HARDWARE_STATUS
-+{
-+    HWReady,
-+    HWInitializing,
-+    HWReset,
-+    HWClosing,
-+    HWNotReady
-+} HARDWARE_STATUS;
-+
-+/** info for debug purpose */
-+typedef struct _uap_dbg
-+{
-+        /** Number of host to card command failures */
-+    u32 num_cmd_host_to_card_failure;
-+        /** Number of host to card Tx failures */
-+    u32 num_tx_host_to_card_failure;
-+} uap_dbg;
-+
-+/** Set thread state */
-+#define OS_SET_THREAD_STATE(x)                set_current_state(x)
-+
-+typedef struct
-+{
-+    /** Task */
-+    struct task_struct *task;
-+    /** Queue */
-+    wait_queue_head_t waitQ;
-+    /** PID */
-+    pid_t pid;
-+    /** Private structure */
-+    void *priv;
-+} uap_thread;
-+
-+static inline void
-+uap_activate_thread(uap_thread * thr)
-+{
-+        /** Record the thread pid */
-+    thr->pid = current->pid;
-+
-+        /** Initialize the wait queue */
-+    init_waitqueue_head(&thr->waitQ);
-+}
-+
-+static inline void
-+uap_deactivate_thread(uap_thread * thr)
-+{
-+    thr->pid = 0;
-+    return;
-+}
-+
-+static inline void
-+uap_create_thread(int (*uapfunc) (void *), uap_thread * thr, char *name)
-+{
-+    thr->task = kthread_run(uapfunc, thr, "%s", name);
-+}
-+
-+static inline int
-+uap_terminate_thread(uap_thread * thr)
-+{
-+    /* Check if the thread is active or not */
-+    if (!thr->pid)
-+        return -1;
-+    kthread_stop(thr->task);
-+    return 0;
-+}
-+
-+/** Data structure for the Marvell uAP device */
-+typedef struct _uap_dev
-+{
-+        /** device name */
-+    char name[DEV_NAME_LEN];
-+        /** card pointer */
-+    void *card;
-+        /** IO port */
-+    u32 ioport;
-+        /** Rx unit */
-+    u8 rx_unit;
-+        /** Data sent:
-+          TRUE - Data is sent to fw, no Tx Done received
-+          FALSE - Tx done received for previous Tx */
-+    BOOLEAN data_sent;
-+        /** CMD sent:
-+          TRUE - CMD is sent to fw, no CMD Done received
-+          FALSE - CMD done received for previous CMD */
-+    BOOLEAN cmd_sent;
-+        /** netdev pointer */
-+    struct net_device *netdev;
-+} uap_dev_t, *puap_dev_t;
-+
-+/** Private structure for the MV device */
-+struct _uap_private
-+{
-+        /** Device open */
-+    int open;
-+
-+        /** Device adapter structure */
-+    uap_adapter *adapter;
-+        /** Device structure */
-+    uap_dev_t uap_dev;
-+
-+        /** Net device statistics structure */
-+    struct net_device_stats stats;
-+
-+        /** Number of Tx timeouts */
-+    u32 num_tx_timeout;
-+
-+        /** Media connection status */
-+    BOOLEAN MediaConnected;
-+
-+#ifdef CONFIG_PROC_FS
-+    struct proc_dir_entry *proc_uap;
-+    struct proc_dir_entry *proc_entry;
-+#endif                          /* CONFIG_PROC_FS */
-+
-+        /** Firmware helper */
-+    const struct firmware *fw_helper;
-+        /** Firmware */
-+    const struct firmware *firmware;
-+        /** Hotplug device */
-+    struct device *hotplug_device;
-+        /** thread to service interrupts */
-+    uap_thread MainThread;
-+        /** Driver lock */
-+    spinlock_t driver_lock;
-+        /** Driver lock flags */
-+    ulong driver_flags;
-+
-+};
-+
-+/** PS_CMD_ConfirmSleep */
-+typedef struct _PS_CMD_ConfirmSleep
-+{
-+        /** SDIO Length */
-+    u16 SDLen;
-+    /** SDIO Type */
-+    u16 SDType;
-+        /** Command */
-+    u16 Command;
-+        /** Size */
-+    u16 Size;
-+        /** Sequence number */
-+    u16 SeqNum;
-+        /** Result */
-+    u16 Result;
-+} __ATTRIB_PACK__ PS_CMD_ConfirmSleep, *PPS_CMD_ConfirmSleep;
-+
-+/** Wlan Adapter data structure*/
-+struct _uap_adapter
-+{
-+        /** Power save confirm sleep command */
-+    PS_CMD_ConfirmSleep PSConfirmSleep;
-+        /** Device status */
-+    HARDWARE_STATUS HardwareStatus;
-+        /** Interrupt counter */
-+    u32 IntCounter;
-+        /** Tx packet queue */
-+    struct sk_buff_head tx_queue;
-+        /** Cmd packet queue */
-+    struct sk_buff_head cmd_queue;
-+        /** Command sequence number */
-+    u16 SeqNum;
-+        /** Command buffer */
-+    u8 *CmdBuf;
-+        /** cmd pending flag */
-+    u8 cmd_pending;
-+        /** cmd wait option */
-+    u8 cmd_wait_option;
-+        /** Command buffer length */
-+    u32 CmdSize;
-+        /** Command wait queue */
-+    wait_queue_head_t cmdwait_q __ATTRIB_ALIGN__;
-+        /** Command wait queue state flag */
-+    u8 CmdWaitQWoken;
-+        /** PnP support */
-+    BOOLEAN SurpriseRemoved;
-+        /** Debug */
-+    uap_dbg dbg;
-+        /** Netlink kernel socket */
-+    struct sock *nl_sk;
-+        /** Semaphore for CMD */
-+    SEMAPHORE CmdSem;
-+         /** Power Save mode */
-+    u8 psmode;
-+        /** Power Save state */
-+    u8 ps_state;
-+        /** Number of wakeup tries */
-+    u32 WakeupTries;
-+};
-+
-+static inline int
-+os_upload_rx_packet(uap_private * priv, struct sk_buff *skb)
-+{
-+    skb->dev = priv->uap_dev.netdev;
-+    skb->protocol = eth_type_trans(skb, priv->uap_dev.netdev);
-+    skb->ip_summed = CHECKSUM_UNNECESSARY;
-+    if (in_interrupt())
-+        netif_rx(skb);
-+    else
-+        netif_rx_ni(skb);
-+    return 0;
-+}
-+
-+/*
-+ *  netif carrier_on/off and start(wake)/stop_queue handling
-+ */
-+static inline void
-+os_carrier_on(uap_private * priv)
-+{
-+    if (!netif_carrier_ok(priv->uap_dev.netdev) &&
-+        (priv->MediaConnected == TRUE)) {
-+        netif_carrier_on(priv->uap_dev.netdev);
-+    }
-+}
-+
-+static inline void
-+os_carrier_off(uap_private * priv)
-+{
-+    if (netif_carrier_ok(priv->uap_dev.netdev)) {
-+        netif_carrier_off(priv->uap_dev.netdev);
-+    }
-+}
-+
-+static inline void
-+os_start_queue(uap_private * priv)
-+{
-+    if (netif_queue_stopped(priv->uap_dev.netdev) &&
-+        (priv->MediaConnected == TRUE)) {
-+        netif_wake_queue(priv->uap_dev.netdev);
-+    }
-+}
-+
-+static inline void
-+os_stop_queue(uap_private * priv)
-+{
-+    if (!netif_queue_stopped(priv->uap_dev.netdev)) {
-+        netif_stop_queue(priv->uap_dev.netdev);
-+    }
-+}
-+
-+/** Interface specific header */
-+#define INTF_HEADER_LEN         4
-+
-+/** headroom alignment for tx packet */
-+#define HEADER_ALIGNMENT      8
-+
-+/** The number of times to try when polling for status bits */
-+#define MAX_POLL_TRIES                        100
-+
-+/** Length of SNAP header */
-+#define MRVDRV_SNAP_HEADER_LEN          8
-+
-+/** Extra length of Tx packet buffer */
-+#define EXTRA_LEN     36
-+
-+/** Buffer size for ethernet Tx packets */
-+#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
-+      (ETH_FRAME_LEN + sizeof(TxPD) + EXTRA_LEN)
-+
-+/** Buffer size for ethernet Rx packets */
-+#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
-+      (ETH_FRAME_LEN + sizeof(RxPD) \
-+       + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
-+
-+/** Packet type: data, command & event */
-+typedef enum _mv_type
-+{
-+    MV_TYPE_DAT = 0,
-+    MV_TYPE_CMD = 1,
-+    MV_TYPE_EVENT = 3
-+} mv_type;
-+
-+/** Disable interrupt */
-+#define OS_INT_DISABLE        spin_lock_irqsave(&priv->driver_lock, priv->driver_flags)
-+/** Enable interrupt */
-+#define       OS_INT_RESTORE  spin_unlock_irqrestore(&priv->driver_lock, priv->driver_flags)
-+
-+int uap_process_rx_packet(uap_private * priv, struct sk_buff *skb);
-+void uap_interrupt(uap_private * priv);
-+uap_private *uap_add_card(void *card);
-+int uap_remove_card(void *card);
-+int uap_process_event(uap_private * priv, u8 * payload, uint len);
-+int uap_soft_reset(uap_private * priv);
-+int uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len);
-+
-+#ifdef CONFIG_PROC_FS
-+/** The proc fs interface */
-+void uap_proc_entry(uap_private * priv, struct net_device *dev);
-+void uap_proc_remove(uap_private * priv);
-+int string_to_number(char *s);
-+void uap_debug_entry(uap_private * priv, struct net_device *dev);
-+void uap_debug_remove(uap_private * priv);
-+#endif /* CONFIG_PROC_FS */
-+
-+int sbi_register(void);
-+
-+void sbi_unregister(void);
-+int sbi_register_dev(uap_private * priv);
-+int sbi_unregister_dev(uap_private * priv);
-+int sbi_prog_fw_w_helper(uap_private *);
-+
-+int sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb);
-+int sbi_enable_host_int(uap_private * priv);
-+int sbi_disable_host_int(uap_private * priv);
-+
-+int sbi_get_int_status(uap_private * priv, u8 * ireg);
-+/** Check firmware status */
-+int sbi_check_fw_status(uap_private *, int);
-+int sbi_prog_helper(uap_private *);
-+
-+int sbi_wakeup_firmware(uap_private * priv);
-+
-+#endif /* _UAP_DRV_H */
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_fw.h backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_fw.h
---- backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_fw.h  1970-01-01 01:00:00.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_fw.h      2014-12-29 20:37:43.949097590 +0100
-@@ -0,0 +1,359 @@
-+/** @file uap_fw.h
-+ *
-+ * @brief This file contains firmware specific defines.
-+ *
-+ * Copyright (C) 2008-2009, Marvell International Ltd.
-+ *
-+ * This software file (the "File") is distributed by Marvell International
-+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+ * (the "License").  You may use, redistribute and/or modify this File in
-+ * accordance with the terms and conditions of the License, a copy of which
-+ * is available along with the File in the gpl.txt file or by writing to
-+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+ *
-+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
-+ * this warranty disclaimer.
-+ *
-+ */
-+/********************************************************
-+Change log:
-+      02/26/08: Initial creation
-+********************************************************/
-+
-+#ifndef _UAP_FW_H
-+#define _UAP_FW_H
-+
-+/** uap upload size */
-+#define       UAP_UPLD_SIZE                   2312
-+/** Packet type Micro AP */
-+#define PKT_TYPE_MICROAP              1
-+/** Packet type client */
-+#define PKT_TYPE_CLIENT                       0
-+
-+/** TxPD descriptor */
-+typedef struct _TxPD
-+{
-+        /** Bss Type */
-+    u8 BssType;
-+        /** Bss num */
-+    u8 BssNum;
-+        /** Tx packet length */
-+    u16 TxPktLength;
-+        /** Tx packet offset */
-+    u16 TxPktOffset;
-+        /** Tx packet type */
-+    u16 TxPktType;
-+        /** Tx Control */
-+    u32 TxControl;
-+        /** reserved */
-+    u32 reserved[2];
-+} __ATTRIB_PACK__ TxPD, *PTxPD;
-+
-+/** RxPD Descriptor */
-+typedef struct _RxPD
-+{
-+        /** Bss Type */
-+    u8 BssType;
-+        /** Bss Num */
-+    u8 BssNum;
-+        /** Tx packet length */
-+    u16 RxPktLength;
-+        /** Tx packet offset */
-+    u16 RxPktOffset;
-+} __ATTRIB_PACK__ RxPD, *PRxPD;
-+
-+#ifdef BIG_ENDIAN
-+/** Convert from 16 bit little endian format to CPU format */
-+#define uap_le16_to_cpu(x) le16_to_cpu(x)
-+/** Convert from 32 bit little endian format to CPU format */
-+#define uap_le32_to_cpu(x) le32_to_cpu(x)
-+/** Convert from 64 bit little endian format to CPU format */
-+#define uap_le64_to_cpu(x) le64_to_cpu(x)
-+/** Convert to 16 bit little endian format from CPU format */
-+#define uap_cpu_to_le16(x) cpu_to_le16(x)
-+/** Convert to 32 bit little endian format from CPU format */
-+#define uap_cpu_to_le32(x) cpu_to_le32(x)
-+/** Convert to 64 bit little endian format from CPU format */
-+#define uap_cpu_to_le64(x) cpu_to_le64(x)
-+
-+/** Convert TxPD to little endian format from CPU format */
-+#define endian_convert_TxPD(x);                                         \
-+    {                                                                   \
-+        (x)->TxPktLength = uap_cpu_to_le16((x)->TxPktLength);         \
-+        (x)->TxPktOffset = uap_cpu_to_le32((x)->TxPktOffset);         \
-+        (x)->TxControl = uap_cpu_to_le32((x)->TxControl);              \
-+        (x)->TxPktType = uap_cpu_to_le32((x)->TxPktType);             \
-+    }
-+
-+/** Convert RxPD from little endian format to CPU format */
-+#define endian_convert_RxPD(x);                                       \
-+    {                                                                 \
-+        (x)->RxPktLength = uap_le16_to_cpu((x)->RxPktLength);         \
-+        (x)->RxPktOffset = uap_le32_to_cpu((x)->RxPktOffset);         \
-+    }
-+#else /* BIG_ENDIAN */
-+/** Do nothing */
-+#define uap_le16_to_cpu(x) x
-+/** Do nothing */
-+#define uap_le32_to_cpu(x) x
-+/** Do nothing */
-+#define uap_le64_to_cpu(x) x
-+/** Do nothing */
-+#define uap_cpu_to_le16(x) x
-+/** Do nothing */
-+#define uap_cpu_to_le32(x) x
-+/** Do nothing */
-+#define uap_cpu_to_le64(x) x
-+
-+/** Do nothing */
-+#define endian_convert_TxPD(x)
-+/** Do nothing */
-+#define endian_convert_RxPD(x)
-+#endif /* BIG_ENDIAN */
-+
-+/** Host Command ID : Function initialization */
-+#define HostCmd_CMD_FUNC_INIT                 0x00a9
-+/** Host Command ID : Function shutdown */
-+#define HostCmd_CMD_FUNC_SHUTDOWN             0x00aa
-+
-+/** Host Command id: SYS_INFO  */
-+#define HOST_CMD_APCMD_SYS_INFO               0x00ae
-+/** Host Command id: SYS_RESET  */
-+#define HOST_CMD_APCMD_SYS_RESET              0x00af
-+/** Host Command id: SYS_CONFIGURE  */
-+#define HOST_CMD_APCMD_SYS_CONFIGURE          0x00b0
-+/** Host Command id: BSS_START  */
-+#define HOST_CMD_APCMD_BSS_START              0x00b1
-+/** Host Command id: SYS_STOP  */
-+#define HOST_CMD_APCMD_BSS_STOP               0x00b2
-+/** Host Command id: STA_LIST  */
-+#define HOST_CMD_APCMD_STA_LIST               0x00b3
-+/** Host Command id: STA_FILTER_TABLE  */
-+#define HOST_CMD_APCMD_STA_FILTER_TABLE       0x00b4
-+/** Host Command id: STA_DEAUTH  */
-+#define HOST_CMD_APCMD_STA_DEAUTH             0x00b5
-+/** Host Command id: SOFT_RESET  */
-+#define HOST_CMD_APCMD_SOFT_RESET             0x00d5
-+/** Host Command id: POWER_MGMT_EXT  */
-+#define HOST_CMD_POWER_MGMT_EXT               0x00ef
-+/** Host Command id: SLEEP_CONFIRM*/
-+#define HOST_CMD_SLEEP_CONFIRM              0x00d8
-+
-+/** TLV type : SSID */
-+#define TLV_TYPE_SSID                         0x0000
-+/** TLV type : Rates */
-+#define TLV_TYPE_RATES                                0x0001
-+/** TLV type : PHY DS */
-+#define TLV_TYPE_PHY_DS                               0x0003
-+
-+/** TLV Id : Base id */
-+#define PROPRIETARY_TLV_BASE_ID               0x0100
-+/** TLV Id : AP_MAC_ADDRESS */
-+#define MRVL_AP_MAC_ADDRESS_TLV_ID      (PROPRIETARY_TLV_BASE_ID + 43)
-+/** TLV Id : Beacon period */
-+#define MRVL_BEACON_PERIOD_TLV_ID       (PROPRIETARY_TLV_BASE_ID + 44)
-+/** TLV Id : Dtim period */
-+#define MRVL_DTIM_PERIOD_TLV_ID         (PROPRIETARY_TLV_BASE_ID + 45)
-+/** TLV Id : Basic rates */
-+#define MRVL_BASIC_RATES_TLV_ID         (PROPRIETARY_TLV_BASE_ID + 46)
-+/** TLV Id : Tx Power */
-+#define MRVL_TX_POWER_TLV_ID            (PROPRIETARY_TLV_BASE_ID + 47)
-+/** TLV Id : Broadcast SSID control */
-+#define MRVL_BCAST_SSID_CTL_TLV_ID      (PROPRIETARY_TLV_BASE_ID + 48)
-+/** TLV Id : Preamble control */
-+#define MRVL_PREAMBLE_CTL_TLV_ID        (PROPRIETARY_TLV_BASE_ID + 49)
-+/** TLV Id : Antenna control */
-+#define MRVL_ANTENNA_CTL_TLV_ID         (PROPRIETARY_TLV_BASE_ID + 50)
-+/** TLV Id : RTS threshold */
-+#define MRVL_RTS_THRESHOLD_TLV_ID       (PROPRIETARY_TLV_BASE_ID + 51)
-+/** TLV Id : Radio control */
-+#define MRVL_RADIO_CTL_TLV_ID           (PROPRIETARY_TLV_BASE_ID + 52)
-+/** TLV Id : TX data rate */
-+#define MRVL_TX_DATA_RATE_TLV_ID        (PROPRIETARY_TLV_BASE_ID + 53)
-+/** TLV Id : Packet forward control */
-+#define MRVL_PKT_FWD_CTL_TLV_ID         (PROPRIETARY_TLV_BASE_ID + 54)
-+/** TLV Id : STA info */
-+#define MRVL_STA_INFO_TLV_ID            (PROPRIETARY_TLV_BASE_ID + 55)
-+/** TLV Id : STA MAC address filter */
-+#define MRVL_STA_MAC_ADDR_FILTER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 56)
-+/** TLV Id : STA ageout timer */
-+#define MRVL_STA_AGEOUT_TIMER_TLV_ID    (PROPRIETARY_TLV_BASE_ID + 57)
-+/** TLV Id : Security config */
-+#define MRVL_SECURITY_CFG_TLV_ID        (PROPRIETARY_TLV_BASE_ID + 58)
-+/** TLV Id : WEP KEY */
-+#define MRVL_WEP_KEY_TLV_ID             (PROPRIETARY_TLV_BASE_ID + 59)
-+/** TLV Id : WPA Passphrase */
-+#define MRVL_WPA_PASSPHRASE_TLV_ID      (PROPRIETARY_TLV_BASE_ID + 60)
-+
-+/** Action get */
-+#define ACTION_GET    0
-+/** Action set */
-+#define ACTION_SET    1
-+/** Length of ethernet address */
-+#ifndef       ETH_ALEN
-+#define ETH_ALEN                      6
-+#endif
-+
-+/** HostCmd_DS_GEN */
-+typedef struct
-+{
-+    /** Command */
-+    u16 Command;
-+    /** Size */
-+    u16 Size;
-+    /** Sequence number */
-+    u16 SeqNum;
-+    /** Result */
-+    u16 Result;
-+} __ATTRIB_PACK__ HostCmd_DS_GEN;
-+
-+/** Size of HostCmd_DS_GEN */
-+#define S_DS_GEN    sizeof(HostCmd_DS_GEN)
-+
-+/** _HostCmd_HEADER*/
-+typedef struct
-+{
-+    /** Command Header : Command */
-+    u16 Command;
-+    /** Command Header : Size */
-+    u16 Size;
-+} __ATTRIB_PACK__ HostCmd_HEADER;
-+
-+/** HostCmd_SYS_CONFIG */
-+typedef struct _HostCmd_SYS_CONFIG
-+{
-+        /** CMD Action GET/SET*/
-+    u16 Action;
-+        /** Tlv buffer */
-+    u8 TlvBuffer[0];
-+} __ATTRIB_PACK__ HostCmd_SYS_CONFIG;
-+
-+/** HostCmd_DS_POWER_MGMT_EXT */
-+typedef struct _HostCmd_DS_POWER_MGMT_EXT
-+{
-+    /** CMD Action Get/Set*/
-+    u16 action;
-+    /** power mode */
-+    u16 power_mode;
-+} __ATTRIB_PACK__ HostCmd_DS_POWER_MGMT_EXT;
-+
-+/** _HostCmd_DS_COMMAND*/
-+typedef struct _HostCmd_DS_COMMAND
-+{
-+
-+        /** Command Header : Command */
-+    u16 Command;
-+        /** Command Header : Size */
-+    u16 Size;
-+        /** Command Header : Sequence number */
-+    u16 SeqNum;
-+        /** Command Header : Result */
-+    u16 Result;
-+        /** Command Body */
-+    union
-+    {
-+        HostCmd_SYS_CONFIG sys_config;
-+        HostCmd_DS_POWER_MGMT_EXT pm_cfg;
-+
-+    } params;
-+} __ATTRIB_PACK__ HostCmd_DS_COMMAND;
-+
-+/** MrvlIEtypesHeader_*/
-+typedef struct _MrvlIEtypesHeader
-+{
-+    /** Header type */
-+    u16 Type;
-+    /** Header length */
-+    u16 Len;
-+} __ATTRIB_PACK__ MrvlIEtypesHeader_t;
-+
-+/** MrvlIEtypes_Data_t */
-+typedef struct _MrvlIEtypes_Data_t
-+{
-+    /** Header */
-+    MrvlIEtypesHeader_t Header;
-+    /** Data */
-+    u8 Data[1];
-+} __ATTRIB_PACK__ MrvlIEtypes_Data_t;
-+
-+/** MrvlIEtypes_ChanListParamSet_t */
-+typedef struct _MrvlIEtypes_MacAddr_t
-+{
-+    /** Header */
-+    MrvlIEtypesHeader_t Header;
-+    /** AP MAC address */
-+    u8 ApMacAddr[ETH_ALEN];
-+} __ATTRIB_PACK__ MrvlIEtypes_MacAddr_t;
-+
-+/** Event ID: BSS started */
-+#define MICRO_AP_EV_ID_BSS_START    46
-+
-+/** Event ID: BSS idle event */
-+#define MICRO_AP_EV_BSS_IDLE       67
-+
-+/** Event ID: BSS active event */
-+#define MICRO_AP_EV_BSS_ACTIVE             68
-+
-+/** Event ID: PS_AWAKE */
-+#define EVENT_PS_AWAKE     0x0a
-+
-+/** Event ID: PS_SLEEP */
-+#define EVENT_PS_SLEEP     0x0b
-+
-+/** PS_STATE */
-+typedef enum _PS_STATE
-+{
-+    PS_STATE_AWAKE,
-+    PS_STATE_PRE_SLEEP,
-+    PS_STATE_SLEEP
-+} PS_STATE;
-+
-+/** TLV type: AP Sleep param */
-+#define TLV_TYPE_AP_SLEEP_PARAM         (PROPRIETARY_TLV_BASE_ID + 106)
-+/** TLV type: AP Inactivity Sleep param */
-+#define TLV_TYPE_AP_INACT_SLEEP_PARAM   (PROPRIETARY_TLV_BASE_ID + 107)
-+
-+/** MrvlIEtypes_sleep_param_t */
-+typedef struct _MrvlIEtypes_sleep_param_t
-+{
-+    /** Header */
-+    MrvlIEtypesHeader_t header;
-+    /** control bitmap */
-+    u32 ctrl_bitmap;
-+    /** min_sleep */
-+    u32 min_sleep;
-+    /** max_sleep */
-+    u32 max_sleep;
-+} __ATTRIB_PACK__ MrvlIEtypes_sleep_param_t;
-+
-+/** MrvlIEtypes_inact_sleep_param_t */
-+typedef struct _MrvlIEtypes_inact_sleep_param_t
-+{
-+    /** Header */
-+    MrvlIEtypesHeader_t header;
-+    /** inactivity timeout */
-+    u32 inactivity_to;
-+    /** min_awake */
-+    u32 min_awake;
-+    /** max_awake */
-+    u32 max_awake;
-+} __ATTRIB_PACK__ MrvlIEtypes_inact_sleep_param_t;
-+
-+/** AP_Event */
-+typedef struct _AP_Event
-+{
-+    /** Event ID */
-+    u32 EventId;
-+    /*
-+     * Reserved for STA_ASSOCIATED event and contains
-+     * status information for the MIC_COUNTERMEASURES event.
-+     */
-+    /** Reserved/status */
-+    u16 status;
-+    /** AP MAC address */
-+    u8 MacAddr[ETH_ALEN];
-+} __ATTRIB_PACK__ AP_Event;
-+#endif /* _UAP_FW_H */
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_headers.h backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_headers.h
---- backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_headers.h     1970-01-01 01:00:00.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_headers.h 2014-12-29 20:37:43.949097590 +0100
-@@ -0,0 +1,64 @@
-+/** @file uap_headers.h
-+ *
-+ * @brief This file contains all the necessary include file.
-+ *
-+  * Copyright (C) 2008-2009, Marvell International Ltd.
-+ *
-+ * This software file (the "File") is distributed by Marvell International
-+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+ * (the "License").  You may use, redistribute and/or modify this File in
-+ * accordance with the terms and conditions of the License, a copy of which
-+ * is available along with the File in the gpl.txt file or by writing to
-+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+ *
-+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
-+ * this warranty disclaimer.
-+ *
-+ */
-+#ifndef _UAP_HEADERS_H
-+#define _UAP_HEADERS_H
-+
-+/* Linux header files */
-+#include    <linux/kernel.h>
-+#include    <linux/module.h>
-+#include    <linux/init.h>
-+#include    <linux/version.h>
-+#include    <linux/param.h>
-+#include    <linux/types.h>
-+#include    <linux/interrupt.h>
-+#include    <linux/proc_fs.h>
-+#include    <linux/kthread.h>
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
-+#include    <linux/semaphore.h>
-+#else
-+#include    <asm/semaphore.h>
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
-+#include    <linux/config.h>
-+#endif
-+
-+/* Net header files */
-+#include    <linux/netdevice.h>
-+#include    <linux/net.h>
-+#include    <linux/skbuff.h>
-+#include    <linux/if_ether.h>
-+#include    <linux/etherdevice.h>
-+#include    <net/sock.h>
-+#include    <linux/netlink.h>
-+#include    <linux/firmware.h>
-+#include    <linux/delay.h>
-+
-+#include    "uap_drv.h"
-+#include    "uap_fw.h"
-+
-+#include <linux/mmc/sdio.h>
-+#include <linux/mmc/sdio_ids.h>
-+#include <linux/mmc/sdio_func.h>
-+#include <linux/mmc/card.h>
-+#include "uap_sdio_mmc.h"
-+
-+#endif /* _UAP_HEADERS_H */
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_main.c backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_main.c
---- backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_main.c        1970-01-01 01:00:00.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_main.c    2014-12-29 20:37:43.952431125 +0100
-@@ -0,0 +1,1817 @@
-+/** @file uap_main.c
-+  * @brief This file contains the major functions in uAP
-+  * driver. It includes init, exit etc..
-+  * This file also contains the initialization for SW,
-+  * FW and HW
-+  *
-+  * Copyright (C) 2008-2009, Marvell International Ltd.
-+  *
-+  * This software file (the "File") is distributed by Marvell International
-+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+  * (the "License").  You may use, redistribute and/or modify this File in
-+  * accordance with the terms and conditions of the License, a copy of which
-+  * is available along with the File in the gpl.txt file or by writing to
-+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+  *
-+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
-+  * this warranty disclaimer.
-+  *
-+  */
-+/**
-+  * @mainpage uAP Linux Driver
-+  *
-+  * @section overview_sec Overview
-+  *
-+  * This is Linux reference driver for Marvell uAP.
-+  *
-+  * @section copyright_sec Copyright
-+  *
-+  * Copyright (C) 2008, Marvell International Ltd.
-+  *
-+  */
-+
-+#include      "uap_headers.h"
-+
-+/**
-+ * the global variable of a pointer to uap_private
-+ * structure variable
-+ */
-+uap_private *uappriv = NULL;
-+#ifdef DEBUG_LEVEL1
-+#define DEFAULT_DEBUG_MASK    (DBG_MSG | DBG_FATAL | DBG_ERROR)
-+u32 drvdbg = DEFAULT_DEBUG_MASK;
-+#endif
-+/** Helper name */
-+char *helper_name = NULL;
-+/** Firmware name */
-+char *fw_name = NULL;
-+
-+/** Semaphore for add/remove card */
-+SEMAPHORE AddRemoveCardSem;
-+
-+/********************************************************
-+              Local Functions
-+********************************************************/
-+/**
-+ *  @brief This function send sleep confirm command to firmware
-+ *
-+ *  @param priv       A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_dnld_sleep_confirm_cmd(uap_private * priv)
-+{
-+    uap_adapter *Adapter = priv->adapter;
-+    int ret = UAP_STATUS_SUCCESS;
-+    ENTER();
-+    PRINTM(CMND, "Sleep confirm\n");
-+    Adapter->cmd_pending = TRUE;
-+    Adapter->cmd_wait_option = HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM;
-+    ret =
-+        sbi_host_to_card(priv, (u8 *) & Adapter->PSConfirmSleep,
-+                         sizeof(PS_CMD_ConfirmSleep));
-+    if (ret != UAP_STATUS_SUCCESS) {
-+        Adapter->ps_state = PS_STATE_AWAKE;
-+        Adapter->cmd_pending = FALSE;
-+        Adapter->cmd_wait_option = FALSE;
-+    }
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function process sleep confirm resp from firmware
-+ *
-+ *  @param priv       A pointer to uap_private structure
-+ *  @param resp       A pointer to resp buf
-+ *  @param resp_len   resp buf len
-+ *  @return      UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE
-+ */
-+int
-+uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    HostCmd_DS_COMMAND *cmd;
-+    uap_adapter *Adapter = priv->adapter;
-+    ENTER();
-+    PRINTM(CMND, "Sleep confirm resp\n");
-+    if (!resp_len) {
-+        PRINTM(ERROR, "Cmd Size is 0\n");
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+    cmd = (HostCmd_DS_COMMAND *) resp;
-+    cmd->Result = uap_le16_to_cpu(cmd->Result);
-+    if (cmd->Result != UAP_STATUS_SUCCESS) {
-+        PRINTM(ERROR, "HOST_CMD_APCMD_PS_SLEEP_CONFIRM fail=%x\n", cmd->Result);
-+        ret = -EFAULT;
-+    }
-+  done:
-+    if (ret == UAP_STATUS_SUCCESS)
-+        Adapter->ps_state = PS_STATE_SLEEP;
-+    else
-+        Adapter->ps_state = PS_STATE_AWAKE;
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function checks condition and prepares to
-+ *  send sleep confirm command to firmware if OK.
-+ *
-+ *  @param priv       A pointer to uap_private structure
-+ *  @return           n/a
-+ */
-+static void
-+uap_ps_cond_check(uap_private * priv)
-+{
-+    uap_adapter *Adapter = priv->adapter;
-+
-+    ENTER();
-+    if (!priv->uap_dev.cmd_sent &&
-+        !Adapter->cmd_pending && !Adapter->IntCounter) {
-+        uap_dnld_sleep_confirm_cmd(priv);
-+    } else {
-+        PRINTM(INFO, "Delay Sleep Confirm (%s%s%s)\n",
-+               (priv->uap_dev.cmd_sent) ? "D" : "",
-+               (Adapter->cmd_pending) ? "C" : "",
-+               (Adapter->IntCounter) ? "I" : "");
-+    }
-+    LEAVE();
-+}
-+
-+/**
-+ *  @brief This function add cmd to cmdQ and waiting for response
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param skb           A pointer to the skb for process
-+ *  @param wait_option Wait option
-+ *  @return      UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_process_cmd(uap_private * priv, struct sk_buff *skb, u8 wait_option)
-+{
-+    uap_adapter *Adapter = priv->adapter;
-+    int ret = UAP_STATUS_SUCCESS;
-+    HostCmd_DS_COMMAND *cmd;
-+    u8 *headptr;
-+    ENTER();
-+    if (Adapter->HardwareStatus != HWReady) {
-+        PRINTM(ERROR, "Hw not ready, uap_process_cmd\n");
-+        kfree(skb);
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    skb->cb[0] = wait_option;
-+    headptr = skb->data;
-+    *(u16 *) & headptr[0] = uap_cpu_to_le16(skb->len);
-+    *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_CMD);
-+    cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
-+    Adapter->SeqNum++;
-+    cmd->SeqNum = uap_cpu_to_le16(Adapter->SeqNum);
-+    PRINTM(CMND, "process_cmd: %x\n", cmd->Command);
-+    DBG_HEXDUMP(CMD_D, "process_cmd", (u8 *) cmd, cmd->Size);
-+    if (!wait_option) {
-+        skb_queue_tail(&priv->adapter->cmd_queue, skb);
-+        wake_up_interruptible(&priv->MainThread.waitQ);
-+        LEAVE();
-+        return ret;
-+    }
-+    if (OS_ACQ_SEMAPHORE_BLOCK(&Adapter->CmdSem)) {
-+        PRINTM(ERROR, "Acquire semaphore error, uap_prepare_cmd\n");
-+        kfree(skb);
-+        LEAVE();
-+        return -EBUSY;
-+    }
-+    skb_queue_tail(&priv->adapter->cmd_queue, skb);
-+    Adapter->CmdWaitQWoken = FALSE;
-+    wake_up_interruptible(&priv->MainThread.waitQ);
-+    /* Sleep until response is generated by FW */
-+    if (wait_option == HostCmd_OPTION_WAITFORRSP_TIMEOUT) {
-+        if (!os_wait_interruptible_timeout
-+            (Adapter->cmdwait_q, Adapter->CmdWaitQWoken, MRVDRV_TIMER_20S)) {
-+            PRINTM(ERROR, "Cmd timeout\n");
-+            Adapter->cmd_pending = FALSE;
-+            ret = -EFAULT;
-+        }
-+    } else
-+        wait_event_interruptible(Adapter->cmdwait_q, Adapter->CmdWaitQWoken);
-+    OS_REL_SEMAPHORE(&Adapter->CmdSem);
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief Inspect the response buffer for pointers to expected TLVs
-+ *
-+ *
-+ *  @param pTlv        Pointer to the start of the TLV buffer to parse
-+ *  @param tlvBufSize  Size of the TLV buffer
-+ *  @param reqTlvType  request tlv's tlvtype
-+ *  @param ppTlv       Output parameter: Pointer to the request TLV if found
-+ *
-+ *  @return            void
-+ */
-+static void
-+uap_get_tlv_ptrs(MrvlIEtypes_Data_t * pTlv, int tlvBufSize,
-+                 u16 reqTlvType, MrvlIEtypes_Data_t ** ppTlv)
-+{
-+    MrvlIEtypes_Data_t *pCurrentTlv;
-+    int tlvBufLeft;
-+    u16 tlvType;
-+    u16 tlvLen;
-+
-+    ENTER();
-+    pCurrentTlv = pTlv;
-+    tlvBufLeft = tlvBufSize;
-+    *ppTlv = NULL;
-+    PRINTM(INFO, "uap_get_tlv: tlvBufSize = %d, reqTlvType=%x\n", tlvBufSize,
-+           reqTlvType);
-+    while (tlvBufLeft >= sizeof(MrvlIEtypesHeader_t)) {
-+        tlvType = uap_le16_to_cpu(pCurrentTlv->Header.Type);
-+        tlvLen = uap_le16_to_cpu(pCurrentTlv->Header.Len);
-+        if (reqTlvType == tlvType)
-+            *ppTlv = (MrvlIEtypes_Data_t *) pCurrentTlv;
-+        if (*ppTlv) {
-+            HEXDUMP("TLV Buf", (u8 *) * ppTlv, tlvLen);
-+            break;
-+        }
-+        tlvBufLeft -= (sizeof(pTlv->Header) + tlvLen);
-+        pCurrentTlv = (MrvlIEtypes_Data_t *) (pCurrentTlv->Data + tlvLen);
-+    }                           /* while */
-+    LEAVE();
-+}
-+
-+/**
-+ *  @brief This function get mac
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS on success, otherwise failure code
-+ */
-+static int
-+uap_get_mac_address(uap_private * priv)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    u32 CmdSize;
-+    HostCmd_DS_COMMAND *cmd;
-+    uap_adapter *Adapter = priv->adapter;
-+    struct sk_buff *skb;
-+    MrvlIEtypes_MacAddr_t *pMacAddrTlv;
-+    MrvlIEtypes_Data_t *pTlv;
-+    u16 tlvBufSize;
-+    ENTER();
-+    skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+    if (!skb) {
-+        PRINTM(ERROR, "No free skb\n");
-+        ret = -ENOMEM;
-+        goto done;
-+    }
-+    CmdSize =
-+        S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t);
-+    cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
-+    cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
-+    cmd->Size = uap_cpu_to_le16(CmdSize);
-+    cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_GET);
-+    pMacAddrTlv =
-+        (MrvlIEtypes_MacAddr_t *) (skb->data + INTF_HEADER_LEN + S_DS_GEN +
-+                                   sizeof(HostCmd_SYS_CONFIG));
-+    pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID);
-+    pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN);
-+    skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+    if (UAP_STATUS_SUCCESS !=
-+        uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
-+        PRINTM(ERROR, "Fail to process cmd SYS_CONFIGURE Query\n");
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+    if (!Adapter->CmdSize) {
-+        PRINTM(ERROR, "Cmd Size is 0\n");
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+    cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf;
-+    cmd->Result = uap_le16_to_cpu(cmd->Result);
-+    if (cmd->Result != UAP_STATUS_SUCCESS) {
-+        PRINTM(ERROR, "uap_get_mac_address fail=%x\n", cmd->Result);
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+    pTlv =
-+        (MrvlIEtypes_Data_t *) (Adapter->CmdBuf + S_DS_GEN +
-+                                sizeof(HostCmd_SYS_CONFIG));
-+    tlvBufSize = Adapter->CmdSize - S_DS_GEN - sizeof(HostCmd_SYS_CONFIG);
-+    uap_get_tlv_ptrs(pTlv, tlvBufSize, MRVL_AP_MAC_ADDRESS_TLV_ID,
-+                     (MrvlIEtypes_Data_t **) & pMacAddrTlv);
-+    if (pMacAddrTlv) {
-+        memcpy(priv->uap_dev.netdev->dev_addr, pMacAddrTlv->ApMacAddr,
-+               ETH_ALEN);
-+        HEXDUMP("Original MAC addr", priv->uap_dev.netdev->dev_addr, ETH_ALEN);
-+    }
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function checks the conditions and sends packet to device
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param skb           A pointer to the skb for process
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_process_tx(uap_private * priv, struct sk_buff *skb)
-+{
-+    uap_adapter *Adapter = priv->adapter;
-+    int ret = UAP_STATUS_SUCCESS;
-+    TxPD *pLocalTxPD;
-+    u8 *headptr;
-+    struct sk_buff *newskb;
-+    int newheadlen;
-+    ENTER();
-+    ASSERT(skb);
-+    if (!skb) {
-+        LEAVE();
-+        return UAP_STATUS_FAILURE;
-+    }
-+    if (skb_headroom(skb) < (sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT)) {
-+        newheadlen = sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT;
-+        PRINTM(WARN, "Tx: Insufficient skb headroom %d\n", skb_headroom(skb));
-+        /* Insufficient skb headroom - allocate a new skb */
-+        newskb = skb_realloc_headroom(skb, newheadlen);
-+        if (unlikely(newskb == NULL)) {
-+            PRINTM(ERROR, "Tx: Cannot allocate skb\n");
-+            ret = UAP_STATUS_FAILURE;
-+            goto done;
-+        }
-+        kfree_skb(skb);
-+        skb = newskb;
-+        PRINTM(INFO, "new skb headroom %d\n", skb_headroom(skb));
-+    }
-+    /* headptr should be aligned */
-+    headptr = skb->data - sizeof(TxPD) - INTF_HEADER_LEN;
-+    headptr = (u8 *) ((u32) headptr & ~((u32) (HEADER_ALIGNMENT - 1)));
-+
-+    pLocalTxPD = (TxPD *) (headptr + INTF_HEADER_LEN);
-+    memset(pLocalTxPD, 0, sizeof(TxPD));
-+    pLocalTxPD->BssType = PKT_TYPE_MICROAP;
-+    pLocalTxPD->TxPktLength = skb->len;
-+    /* offset of actual data */
-+    pLocalTxPD->TxPktOffset = (long) skb->data - (long) pLocalTxPD;
-+    endian_convert_TxPD(pLocalTxPD);
-+    *(u16 *) & headptr[0] =
-+        uap_cpu_to_le16(skb->len + ((long) skb->data - (long) headptr));
-+    *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_DAT);
-+    ret =
-+        sbi_host_to_card(priv, headptr,
-+                         skb->len + ((long) skb->data - (long) headptr));
-+    if (ret) {
-+        PRINTM(ERROR, "uap_process_tx Error: sbi_host_to_card failed: 0x%X\n",
-+               ret);
-+        Adapter->dbg.num_tx_host_to_card_failure++;
-+        goto done;
-+    }
-+    PRINTM(DATA, "Data => FW\n");
-+    DBG_HEXDUMP(DAT_D, "Tx", headptr,
-+                MIN(skb->len + sizeof(TxPD), DATA_DUMP_LEN));
-+  done:
-+    /* Freed skb */
-+    kfree_skb(skb);
-+    LEAVE();
-+    return ret;
-+}
-+
-+static struct netlink_kernel_cfg cfg = {
-+      .groups = NL_MULTICAST_GROUP,
-+};
-+
-+/**
-+ *  @brief This function initializes the adapter structure
-+ *  and set default value to the member of adapter.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_init_sw(uap_private * priv)
-+{
-+    uap_adapter *Adapter = priv->adapter;
-+
-+    ENTER();
-+
-+    if (!(Adapter->CmdBuf = kmalloc(MRVDRV_SIZE_OF_CMD_BUFFER, GFP_KERNEL))) {
-+        PRINTM(INFO, "Failed to allocate command buffer!\n");
-+        LEAVE();
-+        return UAP_STATUS_FAILURE;
-+    }
-+
-+    Adapter->cmd_pending = FALSE;
-+    Adapter->CmdWaitQWoken = FALSE;
-+    Adapter->ps_state = PS_STATE_AWAKE;
-+    Adapter->WakeupTries = 0;
-+
-+    memset(&Adapter->PSConfirmSleep, 0, sizeof(PS_CMD_ConfirmSleep));
-+        /** SDIO header */
-+    Adapter->PSConfirmSleep.SDLen =
-+        uap_cpu_to_le16(sizeof(PS_CMD_ConfirmSleep));
-+    Adapter->PSConfirmSleep.SDType = uap_cpu_to_le16(MV_TYPE_CMD);
-+    Adapter->PSConfirmSleep.SeqNum = 0;
-+    Adapter->PSConfirmSleep.Command = uap_cpu_to_le16(HOST_CMD_SLEEP_CONFIRM);
-+    Adapter->PSConfirmSleep.Size = uap_cpu_to_le16(sizeof(HostCmd_DS_GEN));
-+    Adapter->PSConfirmSleep.Result = 0;
-+
-+    init_waitqueue_head(&Adapter->cmdwait_q);
-+    OS_INIT_SEMAPHORE(&Adapter->CmdSem);
-+
-+    skb_queue_head_init(&Adapter->tx_queue);
-+    skb_queue_head_init(&Adapter->cmd_queue);
-+
-+    /* Status variable */
-+    Adapter->HardwareStatus = HWInitializing;
-+
-+    /* PnP support */
-+    Adapter->SurpriseRemoved = FALSE;
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
-+    Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL,
-+                                           NL_MULTICAST_GROUP, NULL,
-+                                           THIS_MODULE);
-+#else
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-+    Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL,
-+                                           NL_MULTICAST_GROUP, NULL, NULL,
-+                                           THIS_MODULE);
-+#else
-+    Adapter->nl_sk = netlink_kernel_create(&init_net, NETLINK_MARVELL, &cfg);
-+#endif
-+#endif
-+    if (!Adapter->nl_sk) {
-+        PRINTM(ERROR,
-+               "Could not initialize netlink event passing mechanism!\n");
-+    }
-+    LEAVE();
-+    return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ *  @brief This function sends FUNC_INIT command to firmware
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS on success, otherwise failure code
-+ */
-+static int
-+uap_func_init(uap_private * priv)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    u32 CmdSize;
-+    HostCmd_DS_GEN *cmd;
-+    uap_adapter *Adapter = priv->adapter;
-+    struct sk_buff *skb;
-+    ENTER();
-+    if (Adapter->HardwareStatus != HWReady) {
-+        PRINTM(ERROR, "uap_func_init:Hardware is not ready!\n");
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+    skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+    if (!skb) {
-+        PRINTM(ERROR, "No free skb\n");
-+        ret = -ENOMEM;
-+        goto done;
-+    }
-+    CmdSize = sizeof(HostCmd_DS_GEN);
-+    cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
-+    cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_INIT);
-+    cmd->Size = uap_cpu_to_le16(CmdSize);
-+    skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+    PRINTM(CMND, "HostCmd_CMD_FUNC_INIT\n");
-+    if (UAP_STATUS_SUCCESS !=
-+        uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
-+        PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_INIT\n");
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function sends FUNC_SHUTDOWN command to firmware
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS on success, otherwise failure code
-+ */
-+static int __exit
-+uap_func_shutdown(uap_private * priv)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    u32 CmdSize;
-+    HostCmd_DS_GEN *cmd;
-+    uap_adapter *Adapter = priv->adapter;
-+    struct sk_buff *skb;
-+    ENTER();
-+    if (Adapter->HardwareStatus != HWReady) {
-+        PRINTM(ERROR, "uap_func_shutdown:Hardware is not ready!\n");
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+    skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+    if (!skb) {
-+        PRINTM(ERROR, "No free skb\n");
-+        ret = -ENOMEM;
-+        goto done;
-+    }
-+    CmdSize = sizeof(HostCmd_DS_GEN);
-+    cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
-+    cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_SHUTDOWN);
-+    cmd->Size = uap_cpu_to_le16(CmdSize);
-+    skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+    PRINTM(CMND, "HostCmd_CMD_FUNC_SHUTDOWN\n");
-+    if (UAP_STATUS_SUCCESS !=
-+        uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
-+        PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_SHUTDOWN\n");
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function initializes firmware
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_init_fw(uap_private * priv)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    ENTER();
-+    sbi_disable_host_int(priv);
-+    /* Check if firmware is already running */
-+    if (sbi_check_fw_status(priv, 1) == UAP_STATUS_SUCCESS) {
-+        PRINTM(MSG, "UAP FW already running! Skip FW download\n");
-+    } else {
-+        if ((ret = request_firmware(&priv->fw_helper, helper_name,
-+                                    priv->hotplug_device)) < 0) {
-+            PRINTM(FATAL,
-+                   "request_firmware() failed (helper), error code = %#x\n",
-+                   ret);
-+            goto done;
-+        }
-+
-+        /* Download the helper */
-+        ret = sbi_prog_helper(priv);
-+
-+        if (ret) {
-+            PRINTM(FATAL,
-+                   "Bootloader in invalid state! Helper download failed!\n");
-+            ret = UAP_STATUS_FAILURE;
-+            goto done;
-+        }
-+        if ((ret = request_firmware(&priv->firmware, fw_name,
-+                                    priv->hotplug_device)) < 0) {
-+            PRINTM(FATAL, "request_firmware() failed, error code = %#x\n", ret);
-+            goto done;
-+        }
-+
-+        /* Download the main firmware via the helper firmware */
-+        if (sbi_prog_fw_w_helper(priv)) {
-+            PRINTM(FATAL, "UAP FW download failed!\n");
-+            ret = UAP_STATUS_FAILURE;
-+            goto done;
-+        }
-+        /* Check if the firmware is downloaded successfully or not */
-+        if (sbi_check_fw_status(priv, MAX_FIRMWARE_POLL_TRIES) ==
-+            UAP_STATUS_FAILURE) {
-+            PRINTM(FATAL, "FW failed to be active in time!\n");
-+            ret = UAP_STATUS_FAILURE;
-+            goto done;
-+        }
-+        PRINTM(MSG, "UAP FW is active\n");
-+    }
-+    sbi_enable_host_int(priv);
-+    priv->adapter->HardwareStatus = HWReady;
-+    if (uap_func_init(priv) != UAP_STATUS_SUCCESS) {
-+        ret = UAP_STATUS_FAILURE;
-+        goto done;
-+    }
-+  done:
-+    if (priv->fw_helper)
-+        release_firmware(priv->fw_helper);
-+    if (priv->firmware)
-+        release_firmware(priv->firmware);
-+    LEAVE();
-+    return ret;
-+
-+}
-+
-+/**
-+ *  @brief This function frees the structure of adapter
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      n/a
-+ */
-+static void
-+uap_free_adapter(uap_private * priv)
-+{
-+    uap_adapter *Adapter = priv->adapter;
-+
-+    ENTER();
-+
-+    if (Adapter) {
-+        if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) {
-+            sock_release((Adapter->nl_sk)->sk_socket);
-+            Adapter->nl_sk = NULL;
-+        }
-+        if (Adapter->CmdBuf)
-+            kfree(Adapter->CmdBuf);
-+        skb_queue_purge(&priv->adapter->tx_queue);
-+        skb_queue_purge(&priv->adapter->cmd_queue);
-+        /* Free the adapter object itself */
-+        kfree(Adapter);
-+        priv->adapter = NULL;
-+    }
-+
-+    LEAVE();
-+}
-+
-+/**
-+ *  @brief This function handles the major job in uap driver.
-+ *  it handles the event generated by firmware, rx data received
-+ *  from firmware and tx data sent from kernel.
-+ *
-+ *  @param data    A pointer to uap_thread structure
-+ *  @return        BT_STATUS_SUCCESS
-+ */
-+static int
-+uap_service_main_thread(void *data)
-+{
-+    uap_thread *thread = data;
-+    uap_private *priv = thread->priv;
-+    uap_adapter *Adapter = priv->adapter;
-+    wait_queue_t wait;
-+    u8 ireg = 0;
-+    struct sk_buff *skb;
-+    ENTER();
-+    uap_activate_thread(thread);
-+    init_waitqueue_entry(&wait, current);
-+    current->flags |= PF_NOFREEZE;
-+
-+    for (;;) {
-+        add_wait_queue(&thread->waitQ, &wait);
-+        OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE);
-+        if ((Adapter->WakeupTries) ||
-+            (!Adapter->IntCounter && Adapter->ps_state == PS_STATE_PRE_SLEEP) ||
-+            (!priv->adapter->IntCounter
-+             && (priv->uap_dev.data_sent ||
-+                 skb_queue_empty(&priv->adapter->tx_queue))
-+             && (priv->uap_dev.cmd_sent || Adapter->cmd_pending ||
-+                 skb_queue_empty(&priv->adapter->cmd_queue))
-+            )) {
-+            PRINTM(INFO, "Main: Thread sleeping...\n");
-+            schedule();
-+        }
-+        OS_SET_THREAD_STATE(TASK_RUNNING);
-+        remove_wait_queue(&thread->waitQ, &wait);
-+        if (kthread_should_stop() || Adapter->SurpriseRemoved) {
-+            PRINTM(INFO, "main-thread: break from main thread: "
-+                   "SurpriseRemoved=0x%x\n", Adapter->SurpriseRemoved);
-+            /* Cancel pending command */
-+            if (Adapter->cmd_pending == TRUE) {
-+                /* Wake up cmd Q */
-+                Adapter->CmdWaitQWoken = TRUE;
-+                wake_up_interruptible(&Adapter->cmdwait_q);
-+            }
-+            break;
-+        }
-+
-+        PRINTM(INFO, "Main: Thread waking up...\n");
-+        if (priv->adapter->IntCounter) {
-+            OS_INT_DISABLE;
-+            Adapter->IntCounter = 0;
-+            OS_INT_RESTORE;
-+            sbi_get_int_status(priv, &ireg);
-+        } else if ((priv->adapter->ps_state == PS_STATE_SLEEP) &&
-+                   (!skb_queue_empty(&priv->adapter->cmd_queue) ||
-+                    !skb_queue_empty(&priv->adapter->tx_queue))) {
-+            priv->adapter->WakeupTries++;
-+            PRINTM(CMND, "%lu : Wakeup device...\n", os_time_get());
-+            sbi_wakeup_firmware(priv);
-+            continue;
-+        }
-+        if (Adapter->ps_state == PS_STATE_PRE_SLEEP)
-+            uap_ps_cond_check(priv);
-+
-+        /* The PS state is changed during processing of Sleep Request event
-+           above */
-+        if ((Adapter->ps_state == PS_STATE_SLEEP) ||
-+            (Adapter->ps_state == PS_STATE_PRE_SLEEP))
-+            continue;
-+        /* Execute the next command */
-+        if (!priv->uap_dev.cmd_sent && !Adapter->cmd_pending &&
-+            (Adapter->HardwareStatus == HWReady)) {
-+            if (!skb_queue_empty(&priv->adapter->cmd_queue)) {
-+                skb = skb_dequeue(&priv->adapter->cmd_queue);
-+                if (skb) {
-+                    Adapter->CmdSize = 0;
-+                    Adapter->cmd_pending = TRUE;
-+                    Adapter->cmd_wait_option = skb->cb[0];
-+                    if (sbi_host_to_card(priv, skb->data, skb->len)) {
-+                        PRINTM(ERROR, "Cmd:sbi_host_to_card failed!\n");
-+                        Adapter->cmd_pending = FALSE;
-+                        Adapter->dbg.num_cmd_host_to_card_failure++;
-+                        /* Wake up cmd Q */
-+                        Adapter->CmdWaitQWoken = TRUE;
-+                        wake_up_interruptible(&Adapter->cmdwait_q);
-+                    } else {
-+                        if (Adapter->cmd_wait_option ==
-+                            HostCmd_OPTION_WAITFORSEND) {
-+                            /* Wake up cmd Q */
-+                            Adapter->CmdWaitQWoken = TRUE;
-+                            wake_up_interruptible(&Adapter->cmdwait_q);
-+                            Adapter->cmd_wait_option = FALSE;
-+                        }
-+                    }
-+                    kfree_skb(skb);
-+                }
-+            }
-+        }
-+        if (!priv->uap_dev.data_sent && (Adapter->HardwareStatus == HWReady)) {
-+            if (!skb_queue_empty(&priv->adapter->tx_queue)) {
-+                skb = skb_dequeue(&priv->adapter->tx_queue);
-+                if (skb) {
-+                    if (uap_process_tx(priv, skb)) {
-+                        priv->stats.tx_dropped++;
-+                        priv->stats.tx_errors++;
-+                        os_start_queue(priv);
-+                    } else {
-+                        priv->stats.tx_packets++;
-+                        priv->stats.tx_bytes += skb->len;
-+                    }
-+
-+                }
-+            }
-+        }
-+    }
-+    uap_deactivate_thread(thread);
-+    LEAVE();
-+    return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ *  @brief uap hostcmd ioctl handler
-+ *
-+ *  @param dev      A pointer to net_device structure
-+ *  @param req      A pointer to ifreq structure
-+ *  @return         UAP_STATUS_SUCCESS --success, otherwise fail
-+ */
-+/*********  format of ifr_data *************/
-+/*    buf_len + Hostcmd_body             */
-+/*    buf_len: 4 bytes                     */
-+/*             the length of the buf which */
-+/*             can be used to return data  */
-+/*             to application            */
-+/*    Hostcmd_body                       */
-+/*******************************************/
-+static int
-+uap_hostcmd_ioctl(struct net_device *dev, struct ifreq *req)
-+{
-+    u32 buf_len;
-+    HostCmd_HEADER head;
-+    uap_private *priv = (uap_private *) netdev_priv(dev);
-+    uap_adapter *Adapter = priv->adapter;
-+    int ret = UAP_STATUS_SUCCESS;
-+    struct sk_buff *skb;
-+
-+    ENTER();
-+
-+    /* Sanity check */
-+    if (req->ifr_data == NULL) {
-+        PRINTM(ERROR, "uap_hostcmd_ioctl() corrupt data\n");
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    if (copy_from_user(&buf_len, req->ifr_data, sizeof(buf_len))) {
-+        PRINTM(ERROR, "Copy from user failed\n");
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    memset(&head, 0, sizeof(HostCmd_HEADER));
-+    /* Get the command size from user space */
-+    if (copy_from_user
-+        (&head, req->ifr_data + sizeof(buf_len), sizeof(HostCmd_HEADER))) {
-+        PRINTM(ERROR, "Copy from user failed\n");
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    head.Size = uap_le16_to_cpu(head.Size);
-+    if (head.Size > MRVDRV_SIZE_OF_CMD_BUFFER) {
-+        PRINTM(ERROR, "CmdSize too big=%d\n", head.Size);
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    PRINTM(CMND, "ioctl: hostcmd=%x, size=%d,buf_len=%d\n", head.Command,
-+           head.Size, buf_len);
-+    skb = dev_alloc_skb(head.Size + INTF_HEADER_LEN);
-+    if (!skb) {
-+        PRINTM(ERROR, "No free skb\n");
-+        LEAVE();
-+        return -ENOMEM;
-+    }
-+
-+    /* Get the command from user space */
-+    if (copy_from_user
-+        (skb->data + INTF_HEADER_LEN, req->ifr_data + sizeof(buf_len),
-+         head.Size)) {
-+        PRINTM(ERROR, "Copy from user failed\n");
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    skb_put(skb, head.Size + INTF_HEADER_LEN);
-+    if (UAP_STATUS_SUCCESS !=
-+        uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) {
-+        PRINTM(ERROR, "Fail to process cmd\n");
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    if (!Adapter->CmdSize) {
-+        PRINTM(ERROR, "Cmd Size is 0\n");
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    if (Adapter->CmdSize > buf_len) {
-+        PRINTM(ERROR, "buf_len is too small\n");
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    /* Copy to user */
-+    if (copy_to_user
-+        (req->ifr_data + sizeof(buf_len), Adapter->CmdBuf, Adapter->CmdSize)) {
-+        PRINTM(ERROR, "Copy to user failed!\n");
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief uap power mode ioctl handler
-+ *
-+ *  @param dev      A pointer to net_device structure
-+ *  @param req      A pointer to ifreq structure
-+ *  @return         UAP_STATUS_SUCCESS --success, otherwise fail
-+ */
-+static int
-+uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req)
-+{
-+    ps_mgmt pm_cfg;
-+    int ret = UAP_STATUS_SUCCESS;
-+    uap_private *priv = (uap_private *) netdev_priv(dev);
-+    uap_adapter *Adapter = priv->adapter;
-+    struct sk_buff *skb = NULL;
-+    HostCmd_DS_COMMAND *cmd;
-+    u32 CmdSize;
-+    u8 *tlv = NULL;
-+    MrvlIEtypes_sleep_param_t *sleep_tlv = NULL;
-+    MrvlIEtypes_inact_sleep_param_t *inact_tlv = NULL;
-+    u16 tlv_buf_left = 0;
-+    MrvlIEtypesHeader_t *tlvbuf = NULL;
-+    u16 tlv_type = 0;
-+    u16 tlv_len = 0;
-+
-+    ENTER();
-+
-+    /* Sanity check */
-+    if (req->ifr_data == NULL) {
-+        PRINTM(ERROR, "uap_power_mode_ioctl() corrupt data\n");
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+
-+    memset(&pm_cfg, 0, sizeof(ps_mgmt));
-+    if (copy_from_user(&pm_cfg, req->ifr_data, sizeof(ps_mgmt))) {
-+        PRINTM(ERROR, "Copy from user failed\n");
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    PRINTM(CMND,
-+           "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d "
-+           "inact_to=%d min_awake=%d max_awake=%d\n", pm_cfg.flags,
-+           (int) pm_cfg.ps_mode, (int) pm_cfg.sleep_param.ctrl_bitmap,
-+           (int) pm_cfg.sleep_param.min_sleep,
-+           (int) pm_cfg.sleep_param.max_sleep,
-+           (int) pm_cfg.inact_param.inactivity_to,
-+           (int) pm_cfg.inact_param.min_awake,
-+           (int) pm_cfg.inact_param.max_awake);
-+
-+    if (pm_cfg.
-+        flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM |
-+                  PS_FLAG_INACT_SLEEP_PARAM)) {
-+        PRINTM(ERROR, "Invalid parameter: flags = 0x%x\n", pm_cfg.flags);
-+        ret = -EINVAL;
-+        goto done;
-+    }
-+    if (pm_cfg.ps_mode > PS_MODE_INACTIVITY) {
-+        PRINTM(ERROR, "Invalid parameter: ps_mode = %d\n", (int) pm_cfg.flags);
-+        ret = -EINVAL;
-+        goto done;
-+    }
-+
-+    skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+    if (!skb) {
-+        PRINTM(INFO, "No free skb\n");
-+        ret = -ENOMEM;
-+        goto done;
-+    }
-+
-+    CmdSize = S_DS_GEN + sizeof(HostCmd_DS_POWER_MGMT_EXT);
-+
-+    cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
-+    cmd->Command = uap_cpu_to_le16(HOST_CMD_POWER_MGMT_EXT);
-+    if (!pm_cfg.flags) {
-+        cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_GET);
-+    } else {
-+        cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_SET);
-+        cmd->params.pm_cfg.power_mode = uap_cpu_to_le16(pm_cfg.ps_mode);
-+        tlv = (u8 *) & cmd->params.pm_cfg + sizeof(HostCmd_DS_POWER_MGMT_EXT);
-+
-+        if ((pm_cfg.ps_mode) && (pm_cfg.flags & PS_FLAG_SLEEP_PARAM)) {
-+            sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlv;
-+            sleep_tlv->header.Type = uap_cpu_to_le16(TLV_TYPE_AP_SLEEP_PARAM);
-+            sleep_tlv->header.Len =
-+                uap_cpu_to_le16(sizeof(MrvlIEtypes_sleep_param_t) -
-+                                sizeof(MrvlIEtypesHeader_t));
-+            sleep_tlv->ctrl_bitmap =
-+                uap_cpu_to_le32(pm_cfg.sleep_param.ctrl_bitmap);
-+            sleep_tlv->min_sleep =
-+                uap_cpu_to_le32(pm_cfg.sleep_param.min_sleep);
-+            sleep_tlv->max_sleep =
-+                uap_cpu_to_le32(pm_cfg.sleep_param.max_sleep);
-+            CmdSize += sizeof(MrvlIEtypes_sleep_param_t);
-+            tlv += sizeof(MrvlIEtypes_sleep_param_t);
-+        }
-+        if ((pm_cfg.ps_mode == PS_MODE_INACTIVITY) &&
-+            (pm_cfg.flags & PS_FLAG_INACT_SLEEP_PARAM)) {
-+            inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlv;
-+            inact_tlv->header.Type =
-+                uap_cpu_to_le16(TLV_TYPE_AP_INACT_SLEEP_PARAM);
-+            inact_tlv->header.Len =
-+                uap_cpu_to_le16(sizeof(MrvlIEtypes_inact_sleep_param_t) -
-+                                sizeof(MrvlIEtypesHeader_t));
-+            inact_tlv->inactivity_to =
-+                uap_cpu_to_le32(pm_cfg.inact_param.inactivity_to);
-+            inact_tlv->min_awake =
-+                uap_cpu_to_le32(pm_cfg.inact_param.min_awake);
-+            inact_tlv->max_awake =
-+                uap_cpu_to_le32(pm_cfg.inact_param.max_awake);
-+            CmdSize += sizeof(MrvlIEtypes_inact_sleep_param_t);
-+            tlv += sizeof(MrvlIEtypes_inact_sleep_param_t);
-+        }
-+    }
-+    cmd->Size = uap_cpu_to_le16(CmdSize);
-+    skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+    if (UAP_STATUS_SUCCESS !=
-+        uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) {
-+        PRINTM(ERROR, "Fail to process cmd POWER_MODE\n");
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+    if (!Adapter->CmdSize) {
-+        PRINTM(ERROR, "Cmd Size is 0\n");
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+    cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf;
-+    cmd->Result = uap_le16_to_cpu(cmd->Result);
-+    if (cmd->Result != UAP_STATUS_SUCCESS) {
-+        PRINTM(ERROR, "HOST_CMD_APCMD_POWER_MODE fail=%x\n", cmd->Result);
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+    if (pm_cfg.flags) {
-+        Adapter->psmode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode);
-+    } else {
-+        pm_cfg.flags = PS_FLAG_PS_MODE;
-+        pm_cfg.ps_mode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode);
-+        tlv_buf_left =
-+            cmd->Size - (sizeof(HostCmd_DS_POWER_MGMT_EXT) + S_DS_GEN);
-+        tlvbuf =
-+            (MrvlIEtypesHeader_t *) ((u8 *) & cmd->params.pm_cfg +
-+                                     sizeof(HostCmd_DS_POWER_MGMT_EXT));
-+        while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
-+            tlv_type = uap_le16_to_cpu(tlvbuf->Type);
-+            tlv_len = uap_le16_to_cpu(tlvbuf->Len);
-+            switch (tlv_type) {
-+            case TLV_TYPE_AP_SLEEP_PARAM:
-+                sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlvbuf;
-+                pm_cfg.flags |= PS_FLAG_SLEEP_PARAM;
-+                pm_cfg.sleep_param.ctrl_bitmap =
-+                    uap_le32_to_cpu(sleep_tlv->ctrl_bitmap);
-+                pm_cfg.sleep_param.min_sleep =
-+                    uap_le32_to_cpu(sleep_tlv->min_sleep);
-+                pm_cfg.sleep_param.max_sleep =
-+                    uap_le32_to_cpu(sleep_tlv->max_sleep);
-+                break;
-+            case TLV_TYPE_AP_INACT_SLEEP_PARAM:
-+                inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlvbuf;
-+                pm_cfg.flags |= PS_FLAG_INACT_SLEEP_PARAM;
-+                pm_cfg.inact_param.inactivity_to =
-+                    uap_le32_to_cpu(inact_tlv->inactivity_to);
-+                pm_cfg.inact_param.min_awake =
-+                    uap_le32_to_cpu(inact_tlv->min_awake);
-+                pm_cfg.inact_param.max_awake =
-+                    uap_le32_to_cpu(inact_tlv->max_awake);
-+                break;
-+            }
-+            tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
-+            tlvbuf =
-+                (MrvlIEtypesHeader_t *) ((u8 *) tlvbuf + tlv_len +
-+                                         sizeof(MrvlIEtypesHeader_t));
-+        }
-+        /* Copy to user */
-+        if (copy_to_user(req->ifr_data, &pm_cfg, sizeof(ps_mgmt))) {
-+            PRINTM(ERROR, "Copy to user failed!\n");
-+            LEAVE();
-+            return -EFAULT;
-+        }
-+    }
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function send bss_stop command to firmware
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS on success, otherwise failure code
-+ */
-+static int
-+uap_bss_stop(uap_private * priv)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    u32 CmdSize;
-+    HostCmd_DS_GEN *cmd;
-+    uap_adapter *Adapter = priv->adapter;
-+    struct sk_buff *skb;
-+    ENTER();
-+    if (Adapter->HardwareStatus != HWReady) {
-+        PRINTM(ERROR, "uap_bss_stop:Hardware is not ready!\n");
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+    skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+    if (!skb) {
-+        PRINTM(ERROR, "No free skb\n");
-+        ret = -ENOMEM;
-+        goto done;
-+    }
-+    CmdSize = sizeof(HostCmd_DS_GEN);
-+    cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
-+    cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_BSS_STOP);
-+    cmd->Size = uap_cpu_to_le16(CmdSize);
-+    skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+    PRINTM(CMND, "APCMD_BSS_STOP\n");
-+    if (UAP_STATUS_SUCCESS !=
-+        uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
-+        PRINTM(ERROR, "Fail to process cmd BSS_STOP\n");
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/********************************************************
-+              Global Functions
-+********************************************************/
-+/**
-+ *  @brief This function send soft_reset command to firmware
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS on success, otherwise failure code
-+ */
-+int
-+uap_soft_reset(uap_private * priv)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    u32 CmdSize;
-+    HostCmd_DS_GEN *cmd;
-+    uap_adapter *Adapter = priv->adapter;
-+    struct sk_buff *skb;
-+    ENTER();
-+    ret = uap_bss_stop(priv);
-+    if (ret != UAP_STATUS_SUCCESS)
-+        goto done;
-+    skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+    if (!skb) {
-+        PRINTM(ERROR, "No free skb\n");
-+        ret = -ENOMEM;
-+        goto done;
-+    }
-+    CmdSize = sizeof(HostCmd_DS_GEN);
-+    cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
-+    cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SOFT_RESET);
-+    cmd->Size = uap_cpu_to_le16(CmdSize);
-+    skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+    PRINTM(CMND, "APCMD_SOFT_RESET\n");
-+    if (UAP_STATUS_SUCCESS !=
-+        uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORSEND)) {
-+        PRINTM(ERROR, "Fail to process cmd SOFT_RESET\n");
-+        ret = -EFAULT;
-+        goto done;
-+    }
-+    Adapter->SurpriseRemoved = TRUE;
-+    /* delay to allow hardware complete reset */
-+    os_sched_timeout(5);
-+    if (priv->MediaConnected == TRUE) {
-+        os_stop_queue(priv);
-+        os_carrier_off(priv);
-+        priv->MediaConnected = FALSE;
-+    }
-+    Adapter->CmdSize = 0;
-+    Adapter->CmdWaitQWoken = TRUE;
-+    wake_up_interruptible(&Adapter->cmdwait_q);
-+    skb_queue_purge(&priv->adapter->tx_queue);
-+    skb_queue_purge(&priv->adapter->cmd_queue);
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function processes received packet and forwards it
-+ *  to kernel/upper layer
-+ *
-+ *  @param priv    A pointer to uap_private
-+ *  @param skb     A pointer to skb which includes the received packet
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+uap_process_rx_packet(uap_private * priv, struct sk_buff *skb)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    RxPD *pRxPD;
-+    ENTER();
-+    priv->adapter->ps_state = PS_STATE_AWAKE;
-+    pRxPD = (RxPD *) skb->data;
-+    endian_convert_RxPD(pRxPD);
-+    DBG_HEXDUMP(DAT_D, "Rx", skb->data, MIN(skb->len, DATA_DUMP_LEN));
-+    skb_pull(skb, pRxPD->RxPktOffset);
-+    priv->stats.rx_packets++;
-+    priv->stats.rx_bytes += skb->len;
-+    os_upload_rx_packet(priv, skb);
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function opens the network device
-+ *
-+ *  @param dev     A pointer to net_device structure
-+ *  @return        UAP_STATUS_SUCCESS
-+ */
-+static int
-+uap_open(struct net_device *dev)
-+{
-+    uap_private *priv = (uap_private *) (uap_private *) netdev_priv(dev);
-+    uap_adapter *Adapter = priv->adapter;
-+    int i = 0;
-+
-+    ENTER();
-+
-+    /* On some systems the device open handler will be called before HW ready. */
-+    /* Use the following flag check and wait function to work around the issue. */
-+    while ((Adapter->HardwareStatus != HWReady) &&
-+           (i < MAX_WAIT_DEVICE_READY_COUNT)) {
-+        i++;
-+        os_sched_timeout(100);
-+    }
-+    if (i >= MAX_WAIT_DEVICE_READY_COUNT) {
-+        PRINTM(FATAL, "HW not ready, uap_open() return failure\n");
-+        LEAVE();
-+        return UAP_STATUS_FAILURE;
-+    }
-+
-+    if (MODULE_GET == 0)
-+        return UAP_STATUS_FAILURE;
-+
-+    priv->open = TRUE;
-+    if (priv->MediaConnected == TRUE) {
-+        os_carrier_on(priv);
-+        os_start_queue(priv);
-+    } else {
-+        os_stop_queue(priv);
-+        os_carrier_off(priv);
-+    }
-+    LEAVE();
-+    return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ *  @brief This function closes the network device
-+ *
-+ *  @param dev     A pointer to net_device structure
-+ *  @return        UAP_STATUS_SUCCESS
-+ */
-+static int
-+uap_close(struct net_device *dev)
-+{
-+    uap_private *priv = (uap_private *) netdev_priv(dev);
-+
-+    ENTER();
-+    skb_queue_purge(&priv->adapter->tx_queue);
-+    os_stop_queue(priv);
-+    os_carrier_off(priv);
-+
-+    MODULE_PUT;
-+    priv->open = FALSE;
-+    LEAVE();
-+    return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ *  @brief This function returns the network statistics
-+ *
-+ *  @param dev     A pointer to uap_private structure
-+ *  @return        A pointer to net_device_stats structure
-+ */
-+static struct net_device_stats *
-+uap_get_stats(struct net_device *dev)
-+{
-+    uap_private *priv = (uap_private *) netdev_priv(dev);
-+
-+    return &priv->stats;
-+}
-+
-+/**
-+ *  @brief This function sets the MAC address to firmware.
-+ *
-+ *  @param dev     A pointer to uap_private structure
-+ *  @param addr    MAC address to set
-+ *  @return        UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_set_mac_address(struct net_device *dev, void *addr)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    uap_private *priv = (uap_private *) netdev_priv(dev);
-+    struct sockaddr *pHwAddr = (struct sockaddr *) addr;
-+    u32 CmdSize;
-+    HostCmd_DS_COMMAND *cmd;
-+    MrvlIEtypes_MacAddr_t *pMacAddrTlv;
-+    uap_adapter *Adapter = priv->adapter;
-+    struct sk_buff *skb;
-+
-+    ENTER();
-+
-+    /* Dump MAC address */
-+    DBG_HEXDUMP(CMD_D, "Original MAC addr", dev->dev_addr, ETH_ALEN);
-+    DBG_HEXDUMP(CMD_D, "New MAC addr", pHwAddr->sa_data, ETH_ALEN);
-+    if (priv->open && (priv->MediaConnected == TRUE)) {
-+        os_carrier_on(priv);
-+        os_start_queue(priv);
-+    }
-+    skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+    if (!skb) {
-+        PRINTM(ERROR, "No free skb\n");
-+        LEAVE();
-+        return -ENOMEM;
-+    }
-+    CmdSize =
-+        S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t);
-+    cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
-+    cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
-+    cmd->Size = uap_cpu_to_le16(CmdSize);
-+    cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_SET);
-+    pMacAddrTlv =
-+        (MrvlIEtypes_MacAddr_t *) ((u8 *) cmd + S_DS_GEN +
-+                                   sizeof(HostCmd_SYS_CONFIG));
-+    pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID);
-+    pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN);
-+    memcpy(pMacAddrTlv->ApMacAddr, pHwAddr->sa_data, ETH_ALEN);
-+    skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+    PRINTM(CMND, "set_mac_address\n");
-+    if (UAP_STATUS_SUCCESS !=
-+        uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
-+        PRINTM(ERROR, "Fail to set mac address\n");
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    if (!Adapter->CmdSize) {
-+        PRINTM(ERROR, "Cmd Size is 0\n");
-+        LEAVE();
-+        return -EFAULT;
-+    }
-+    cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf;
-+    cmd->Result = uap_cpu_to_le16(cmd->Result);
-+    if (cmd->Result != UAP_STATUS_SUCCESS) {
-+        PRINTM(ERROR, "set mac addrress fail,cmd result=%x\n", cmd->Result);
-+        ret = -EFAULT;
-+    } else
-+        memcpy(dev->dev_addr, pHwAddr->sa_data, ETH_ALEN);
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function handles the timeout of packet
-+ *  transmission
-+ *
-+ *  @param dev     A pointer to net_device structure
-+ *  @return        n/a
-+ */
-+static void
-+uap_tx_timeout(struct net_device *dev)
-+{
-+    uap_private *priv = (uap_private *) netdev_priv(dev);
-+
-+    ENTER();
-+
-+    PRINTM(DATA, "Tx timeout\n");
-+    UpdateTransStart(dev);
-+    priv->num_tx_timeout++;
-+    priv->adapter->IntCounter++;
-+    wake_up_interruptible(&priv->MainThread.waitQ);
-+
-+    LEAVE();
-+}
-+
-+/**
-+ *  @brief This function handles packet transmission
-+ *
-+ *  @param skb     A pointer to sk_buff structure
-+ *  @param dev     A pointer to net_device structure
-+ *  @return        UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+    uap_private *priv = (uap_private *) netdev_priv(dev);
-+    int ret = UAP_STATUS_SUCCESS;
-+
-+    ENTER();
-+    PRINTM(DATA, "Data <= kernel\n");
-+    DBG_HEXDUMP(DAT_D, "Tx", skb->data, MIN(skb->len, DATA_DUMP_LEN));
-+    /* skb sanity check */
-+    if (!skb->len || (skb->len > MRVDRV_MAXIMUM_ETH_PACKET_SIZE)) {
-+        PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len,
-+               MRVDRV_MAXIMUM_ETH_PACKET_SIZE);
-+        priv->stats.tx_dropped++;
-+        kfree(skb);
-+        goto done;
-+    }
-+    skb_queue_tail(&priv->adapter->tx_queue, skb);
-+    wake_up_interruptible(&priv->MainThread.waitQ);
-+    if (skb_queue_len(&priv->adapter->tx_queue) > TX_HIGH_WATERMARK) {
-+        UpdateTransStart(dev);
-+        os_stop_queue(priv);
-+    }
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief ioctl function - entry point
-+ *
-+ *  @param dev      A pointer to net_device structure
-+ *  @param req      A pointer to ifreq structure
-+ *  @param cmd      command
-+ *  @return         UAP_STATUS_SUCCESS--success, otherwise fail
-+ */
-+static int
-+uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+
-+    ENTER();
-+
-+    PRINTM(CMND, "uap_do_ioctl: ioctl cmd = 0x%x\n", cmd);
-+
-+    switch (cmd) {
-+    case UAPHOSTCMD:
-+        ret = uap_hostcmd_ioctl(dev, req);
-+        break;
-+    case UAP_POWER_MODE:
-+        ret = uap_power_mode_ioctl(dev, req);
-+        break;
-+    default:
-+        ret = -EINVAL;
-+        break;
-+    }
-+
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function handles events generated by firmware
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param payload A pointer to payload buffer
-+ *  @param len           Length of the payload
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+uap_process_event(uap_private * priv, u8 * payload, uint len)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    uap_adapter *Adapter = priv->adapter;
-+    struct sk_buff *skb = NULL;
-+    struct nlmsghdr *nlh = NULL;
-+    struct sock *sk = Adapter->nl_sk;
-+    AP_Event *pEvent;
-+
-+    ENTER();
-+    Adapter->ps_state = PS_STATE_AWAKE;
-+    if (len > NL_MAX_PAYLOAD) {
-+        PRINTM(ERROR, "event size is too big!!! len=%d\n", len);
-+        ret = UAP_STATUS_FAILURE;
-+        goto done;
-+    }
-+    pEvent = (AP_Event *) payload;
-+    PRINTM(CMND, "Event: %d\n", pEvent->EventId);
-+    switch (pEvent->EventId) {
-+    case MICRO_AP_EV_ID_BSS_START:
-+        memcpy(priv->uap_dev.netdev->dev_addr, pEvent->MacAddr, ETH_ALEN);
-+        DBG_HEXDUMP(CMD_D, "BSS MAC addr", priv->uap_dev.netdev->dev_addr,
-+                    ETH_ALEN);
-+        break;
-+    case MICRO_AP_EV_BSS_ACTIVE:
-+        // carrier on
-+        priv->MediaConnected = TRUE;
-+        os_carrier_on(priv);
-+        os_start_queue(priv);
-+        break;
-+    case MICRO_AP_EV_BSS_IDLE:
-+        os_stop_queue(priv);
-+        os_carrier_off(priv);
-+        priv->MediaConnected = FALSE;
-+        break;
-+    case EVENT_PS_AWAKE:
-+        PRINTM(CMND, "UAP: PS_AWAKE\n");
-+        Adapter->ps_state = PS_STATE_AWAKE;
-+        Adapter->WakeupTries = 0;
-+        break;
-+    case EVENT_PS_SLEEP:
-+        PRINTM(CMND, "UAP: PS_SLEEP\n");
-+        Adapter->ps_state = PS_STATE_PRE_SLEEP;
-+        break;
-+    default:
-+        break;
-+    }
-+    if ((pEvent->EventId == EVENT_PS_AWAKE) ||
-+        (pEvent->EventId == EVENT_PS_SLEEP))
-+        goto done;
-+    if (sk) {
-+        /* Allocate skb */
-+        if (!(skb = alloc_skb(NLMSG_SPACE(NL_MAX_PAYLOAD), GFP_ATOMIC))) {
-+            PRINTM(ERROR, "Could not allocate skb for netlink.\n");
-+            ret = UAP_STATUS_FAILURE;
-+            goto done;
-+        }
-+        nlh = (struct nlmsghdr *) skb->data;
-+        nlh->nlmsg_len = NLMSG_SPACE(len);
-+
-+        /* From kernel */
-+        nlh->nlmsg_pid = 0;
-+        nlh->nlmsg_flags = 0;
-+
-+        /* Data */
-+        skb_put(skb, nlh->nlmsg_len);
-+        memcpy(NLMSG_DATA(nlh), payload, len);
-+
-+        /* From Kernel */
-+        NETLINK_CB(skb).portid = 0;
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
-+        /* Multicast message */
-+        NETLINK_CB(skb).dst_pid = 0;
-+#endif
-+
-+        /* Multicast group number */
-+        NETLINK_CB(skb).dst_group = NL_MULTICAST_GROUP;
-+
-+        /* Send message */
-+        netlink_broadcast(sk, skb, 0, NL_MULTICAST_GROUP, GFP_KERNEL);
-+
-+        ret = UAP_STATUS_SUCCESS;
-+    } else {
-+        PRINTM(ERROR, "Could not send event through NETLINK. Link down.\n");
-+        ret = UAP_STATUS_FAILURE;
-+    }
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function handles the interrupt. it will change PS
-+ *  state if applicable. it will wake up main_thread to handle
-+ *  the interrupt event as well.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return        n/a
-+ */
-+void
-+uap_interrupt(uap_private * priv)
-+{
-+    ENTER();
-+    priv->adapter->IntCounter++;
-+    priv->adapter->WakeupTries = 0;
-+    PRINTM(INFO, "*\n");
-+    wake_up_interruptible(&priv->MainThread.waitQ);
-+
-+    LEAVE();
-+
-+}
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
-+/** Network device handlers */
-+static const struct net_device_ops uap_netdev_ops = {
-+    .ndo_open = uap_open,
-+    .ndo_start_xmit = uap_hard_start_xmit,
-+    .ndo_stop = uap_close,
-+    .ndo_do_ioctl = uap_do_ioctl,
-+    .ndo_set_mac_address = uap_set_mac_address,
-+    .ndo_tx_timeout = uap_tx_timeout,
-+    .ndo_get_stats = uap_get_stats,
-+};
-+#endif
-+
-+/**
-+ * @brief This function adds the card. it will probe the
-+ * card, allocate the uap_priv and initialize the device.
-+ *
-+ *  @param card    A pointer to card
-+ *  @return        A pointer to uap_private structure
-+ */
-+uap_private *
-+uap_add_card(void *card)
-+{
-+    struct net_device *dev = NULL;
-+    uap_private *priv = NULL;
-+
-+    ENTER();
-+
-+    if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
-+        goto exit_sem_err;
-+
-+    /* Allocate an Ethernet device */
-+    if (!(dev = alloc_etherdev(sizeof(uap_private)))) {
-+        PRINTM(FATAL, "Init ethernet device failed!\n");
-+        goto error;
-+    }
-+    priv = (uap_private *) netdev_priv(dev);
-+
-+    /* Allocate name */
-+    if (dev_alloc_name(dev, "uap%d") < 0) {
-+        PRINTM(ERROR, "Could not allocate device name!\n");
-+        goto error;
-+    }
-+
-+    /* Allocate buffer for uap_adapter */
-+    if (!(priv->adapter = kmalloc(sizeof(uap_adapter), GFP_KERNEL))) {
-+        PRINTM(FATAL, "Allocate buffer for uap_adapter failed!\n");
-+        goto error;
-+    }
-+    memset(priv->adapter, 0, sizeof(uap_adapter));
-+
-+    priv->uap_dev.netdev = dev;
-+    priv->uap_dev.card = card;
-+    priv->MediaConnected = FALSE;
-+    uappriv = priv;
-+    ((struct sdio_mmc_card *) card)->priv = priv;
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-+    SET_MODULE_OWNER(dev);
-+#endif
-+
-+    /* Setup the OS Interface to our functions */
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
-+    dev->open = uap_open;
-+    dev->stop = uap_close;
-+    dev->hard_start_xmit = uap_hard_start_xmit;
-+    dev->tx_timeout = uap_tx_timeout;
-+    dev->get_stats = uap_get_stats;
-+    dev->do_ioctl = uap_do_ioctl;
-+    dev->set_mac_address = uap_set_mac_address;
-+    dev->set_multicast_list = uap_set_multicast_list;
-+#else
-+    dev->netdev_ops = &uap_netdev_ops;
-+#endif
-+    dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT;
-+    dev->hard_header_len += sizeof(TxPD) + INTF_HEADER_LEN;
-+    dev->hard_header_len += HEADER_ALIGNMENT;
-+#define NETIF_F_DYNALLOC 16
-+    dev->features |= NETIF_F_DYNALLOC;
-+    dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
-+
-+    /* Init SW */
-+    if (uap_init_sw(priv)) {
-+        PRINTM(FATAL, "Software Init Failed\n");
-+        goto error;
-+    }
-+
-+    PRINTM(INFO, "Starting kthread...\n");
-+    priv->MainThread.priv = priv;
-+    spin_lock_init(&priv->driver_lock);
-+    uap_create_thread(uap_service_main_thread, &priv->MainThread,
-+                      "uap_main_service");
-+    while (priv->MainThread.pid == 0) {
-+        os_sched_timeout(2);
-+    }
-+
-+    /* Register the device */
-+    if (sbi_register_dev(priv) < 0) {
-+        PRINTM(FATAL, "Failed to register uap device!\n");
-+        goto err_registerdev;
-+    }
-+#ifdef FW_DNLD_NEEDED
-+    SET_NETDEV_DEV(dev, priv->hotplug_device);
-+#endif
-+
-+    /* Init FW and HW */
-+    if (uap_init_fw(priv)) {
-+        PRINTM(FATAL, "Firmware Init Failed\n");
-+        goto err_init_fw;
-+    }
-+
-+    priv->uap_dev.cmd_sent = FALSE;
-+    priv->uap_dev.data_sent = FALSE;
-+
-+    /* Get mac address from firmware */
-+    if (uap_get_mac_address(priv)) {
-+        PRINTM(FATAL, "Fail to get mac address\n");
-+        goto err_init_fw;
-+    }
-+    /* Register network device */
-+    if (register_netdev(dev)) {
-+        printk(KERN_ERR "Cannot register network device!\n");
-+        goto err_init_fw;
-+    }
-+#ifdef CONFIG_PROC_FS
-+    uap_proc_entry(priv, dev);
-+    uap_debug_entry(priv, dev);
-+#endif /* CPNFIG_PROC_FS */
-+    OS_REL_SEMAPHORE(&AddRemoveCardSem);
-+
-+    LEAVE();
-+    return priv;
-+  err_init_fw:
-+    sbi_unregister_dev(priv);
-+  err_registerdev:
-+    ((struct sdio_mmc_card *) card)->priv = NULL;
-+    /* Stop the thread servicing the interrupts */
-+    priv->adapter->SurpriseRemoved = TRUE;
-+    wake_up_interruptible(&priv->MainThread.waitQ);
-+    while (priv->MainThread.pid) {
-+        os_sched_timeout(1);
-+    }
-+  error:
-+    if (dev) {
-+        if (dev->reg_state == NETREG_REGISTERED)
-+            unregister_netdev(dev);
-+        if (priv->adapter)
-+            uap_free_adapter(priv);
-+        free_netdev(dev);
-+        uappriv = NULL;
-+    }
-+    OS_REL_SEMAPHORE(&AddRemoveCardSem);
-+  exit_sem_err:
-+    LEAVE();
-+    return NULL;
-+}
-+
-+/**
-+ *  @brief This function removes the card.
-+ *
-+ *  @param card    A pointer to card
-+ *  @return        UAP_STATUS_SUCCESS
-+ */
-+int
-+uap_remove_card(void *card)
-+{
-+    uap_private *priv = uappriv;
-+    uap_adapter *Adapter;
-+    struct net_device *dev;
-+
-+    ENTER();
-+
-+    if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
-+        goto exit_sem_err;
-+
-+    if (!priv || !(Adapter = priv->adapter)) {
-+        goto exit_remove;
-+    }
-+    Adapter->SurpriseRemoved = TRUE;
-+    if (Adapter->cmd_pending == TRUE) {
-+        /* Wake up cmd Q */
-+        Adapter->CmdWaitQWoken = TRUE;
-+        wake_up_interruptible(&Adapter->cmdwait_q);
-+    }
-+    dev = priv->uap_dev.netdev;
-+    if (priv->MediaConnected == TRUE) {
-+        os_stop_queue(priv);
-+        os_carrier_off(priv);
-+        priv->MediaConnected = FALSE;
-+    }
-+    Adapter->CmdSize = 0;
-+    Adapter->CmdWaitQWoken = TRUE;
-+    wake_up_interruptible(&Adapter->cmdwait_q);
-+    skb_queue_purge(&priv->adapter->tx_queue);
-+    skb_queue_purge(&priv->adapter->cmd_queue);
-+
-+    /* Disable interrupts on the card */
-+    sbi_disable_host_int(priv);
-+    PRINTM(INFO, "netdev_finish_unregister: %s%s.\n", dev->name,
-+           (dev->features & NETIF_F_DYNALLOC) ? "" : ", old style");
-+    unregister_netdev(dev);
-+    PRINTM(INFO, "Unregister finish\n");
-+    wake_up_interruptible(&priv->MainThread.waitQ);
-+    while (priv->MainThread.pid) {
-+        os_sched_timeout(1);
-+    }
-+
-+    if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) {
-+        sock_release((Adapter->nl_sk)->sk_socket);
-+        Adapter->nl_sk = NULL;
-+    }
-+#ifdef CONFIG_PROC_FS
-+    uap_debug_remove(priv);
-+    uap_proc_remove(priv);
-+#endif
-+    sbi_unregister_dev(priv);
-+    PRINTM(INFO, "Free Adapter\n");
-+    uap_free_adapter(priv);
-+    priv->uap_dev.netdev = NULL;
-+    free_netdev(dev);
-+    uappriv = NULL;
-+
-+  exit_remove:
-+    OS_REL_SEMAPHORE(&AddRemoveCardSem);
-+  exit_sem_err:
-+    LEAVE();
-+    return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ *  @brief This function initializes module.
-+ *
-+ *  @return    UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int __init
-+uap_init_module(void)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    ENTER();
-+
-+    OS_INIT_SEMAPHORE(&AddRemoveCardSem);
-+    ret = sbi_register();
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function cleans module
-+ *
-+ *  @return        n/a
-+ */
-+static void __exit
-+uap_cleanup_module(void)
-+{
-+    ENTER();
-+
-+    if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
-+        goto exit_sem_err;
-+
-+    if ((uappriv) && (uappriv->adapter)) {
-+        uap_func_shutdown(uappriv);
-+    }
-+    OS_REL_SEMAPHORE(&AddRemoveCardSem);
-+  exit_sem_err:
-+    sbi_unregister();
-+    LEAVE();
-+}
-+
-+module_init(uap_init_module);
-+module_exit(uap_cleanup_module);
-+module_param(helper_name, charp, 0);
-+MODULE_PARM_DESC(helper_name, "Helper name");
-+module_param(fw_name, charp, 0);
-+MODULE_PARM_DESC(fw_name, "Firmware name");
-+
-+MODULE_DESCRIPTION("M-UAP Driver");
-+MODULE_AUTHOR("Marvell International Ltd.");
-+MODULE_VERSION(DRIVER_VERSION);
-+MODULE_LICENSE("GPL");
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_proc.c backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_proc.c
---- backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_proc.c        1970-01-01 01:00:00.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_proc.c    2014-12-29 20:37:43.952431125 +0100
-@@ -0,0 +1,258 @@
-+/** @file uap_proc.c
-+  * @brief This file contains functions for proc file.
-+  *
-+  * Copyright (C) 2008-2009, Marvell International Ltd.
-+  *
-+  * This software file (the "File") is distributed by Marvell International
-+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+  * (the "License").  You may use, redistribute and/or modify this File in
-+  * accordance with the terms and conditions of the License, a copy of which
-+  * is available along with the File in the gpl.txt file or by writing to
-+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+  *
-+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
-+  * this warranty disclaimer.
-+  *
-+  */
-+#ifdef CONFIG_PROC_FS
-+#include <linux/proc_fs.h>
-+#include <linux/seq_file.h>
-+#include "uap_headers.h"
-+
-+/** /proc directory root */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
-+#define PROC_DIR NULL
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
-+#define PROC_DIR &proc_root
-+#else
-+#define PROC_DIR proc_net
-+#endif
-+
-+/********************************************************
-+              Local Variables
-+********************************************************/
-+
-+/********************************************************
-+              Global Variables
-+********************************************************/
-+
-+/********************************************************
-+              Local Functions
-+********************************************************/
-+
-+static int uap_info_proc_show(struct seq_file *s, void *data) {
-+    int i;
-+    struct net_device *netdev = (struct net_device*)s->private;
-+    struct netdev_hw_addr *ha;
-+    uap_private *priv = (uap_private *) netdev_priv(netdev);
-+
-+    seq_printf(s, "driver_name = " "\"uap\"\n");
-+    seq_printf(s, "driver_version = %s-(FP%s)", DRIVER_VERSION, FPNUM);
-+    seq_printf(s, "\nInterfaceName=\"%s\"\n", netdev->name);
-+
-+    seq_printf(s, "State=\"%s\"\n",
-+                 ((priv->MediaConnected ==
-+                   FALSE) ? "Disconnected" : "Connected"));
-+    seq_printf(s, "MACAddress=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
-+                 netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
-+                 netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
-+    i = 0;
-+    netdev_for_each_mc_addr(ha, netdev) {
-+        ++i;
-+    }
-+    seq_printf(s, "MCCount=\"%d\"\n", i);
-+
-+    /*
-+     * Put out the multicast list
-+     */
-+    i = 0;
-+    netdev_for_each_mc_addr(ha, netdev) {
-+        seq_printf(s,
-+                     "MCAddr[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
-+                     i++,
-+                     ha->addr[0], ha->addr[1],
-+                     ha->addr[2], ha->addr[3],
-+                     ha->addr[4], ha->addr[5]);
-+    }
-+
-+    seq_printf(s, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
-+    seq_printf(s, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
-+    seq_printf(s, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
-+    seq_printf(s, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
-+    seq_printf(s, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
-+    seq_printf(s, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
-+    seq_printf(s, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
-+    seq_printf(s, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
-+    seq_printf(s, "num_tx_timeout = %u\n", priv->num_tx_timeout);
-+    seq_printf(s, "carrier %s\n",
-+                 ((netif_carrier_ok(priv->uap_dev.netdev)) ? "on" : "off"));
-+    seq_printf(s, "tx queue %s\n",
-+                 ((netif_queue_stopped(priv->uap_dev.netdev)) ? "stopped" :
-+                  "started"));
-+
-+    return 0;
-+}
-+
-+static int uap_info_proc_open(struct inode *inode, struct file *file) {
-+      return single_open(file, uap_info_proc_show, PDE_DATA(inode));
-+}
-+
-+static int uap_hwstatus_proc_show(struct seq_file *s, void *data) {
-+    struct net_device *netdev = (struct net_device*)s->private;
-+    uap_private *priv = (uap_private *) netdev_priv(netdev);
-+
-+    MODULE_GET;
-+    seq_printf(s, "%d\n", priv->adapter->HardwareStatus);
-+    MODULE_PUT;
-+
-+    return 0;
-+}
-+
-+static int uap_hwstatus_proc_open(struct inode *inode, struct file *file) {
-+      return single_open(file, uap_hwstatus_proc_show, PDE_DATA(inode));
-+}
-+
-+static ssize_t uap_hwstatus_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *data) {
-+      struct net_device *netdev = (struct net_device *)PDE_DATA(file_inode(file));
-+      uap_private *priv = (uap_private *) netdev_priv(netdev);
-+
-+      int hwstatus;
-+      char value[10];
-+
-+      if (count > sizeof(value))
-+              return count;
-+
-+      if (copy_from_user(&value, buffer, count))
-+              return -EFAULT;
-+
-+      hwstatus = string_to_number(value);
-+      switch (hwstatus) {
-+      case HWReset:
-+              PRINTM(MSG, "reset hw\n");
-+              uap_soft_reset(priv);
-+              priv->adapter->HardwareStatus = HWReset;
-+              break;
-+      default:
-+              break;
-+      }
-+
-+      MODULE_PUT;
-+      return count;
-+}
-+
-+static const struct file_operations uap_info_proc_fops = {
-+      .owner   = THIS_MODULE,
-+      .open    = uap_info_proc_open,
-+      .read    = seq_read,
-+      .llseek  = seq_lseek,
-+      .release = single_release,
-+};
-+
-+static const struct file_operations uap_hwstatus_proc_fops = {
-+      .owner   = THIS_MODULE,
-+      .open    = uap_hwstatus_proc_open,
-+      .read    = seq_read,
-+      .llseek  = seq_lseek,
-+      .release = single_release,
-+      .write   = uap_hwstatus_proc_write,
-+};
-+
-+/********************************************************
-+              Global Functions
-+********************************************************/
-+/**
-+ *  @brief create uap proc file
-+ *
-+ *  @param priv          pointer uap_private
-+ *  @param dev     pointer net_device
-+ *  @return      N/A
-+ */
-+void
-+uap_proc_entry(uap_private * priv, struct net_device *dev)
-+{
-+    PRINTM(INFO, "Creating Proc Interface\n");
-+    /* Check if uap directory already exists */
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
-+    struct proc_dir_entry *r = PROC_DIR;
-+
-+    for (r = r->subdir; r; r = r->next) {
-+        if (r->namelen && !strcmp("uap", r->name)) {
-+            /* Directory exists */
-+            PRINTM(WARN, "proc directory already exists!\n");
-+            priv->proc_uap = r;
-+            break;
-+        }
-+    }
-+#endif
-+    if (!priv->proc_uap) {
-+        priv->proc_uap = proc_mkdir("uap", PROC_DIR);
-+        if (!priv->proc_uap)
-+            return;
-+    }
-+    priv->proc_entry = proc_mkdir(dev->name, priv->proc_uap);
-+
-+    if (priv->proc_entry) {
-+      proc_create_data("info", 0644, priv->proc_entry, &uap_info_proc_fops, dev);
-+      proc_create_data("hwinfo", 0644, priv->proc_entry, &uap_hwstatus_proc_fops, dev);
-+    }
-+}
-+
-+/**
-+ *  @brief remove proc file
-+ *
-+ *  @param priv          pointer uap_private
-+ *  @return      N/A
-+ */
-+void
-+uap_proc_remove(uap_private * priv)
-+{
-+    if (priv->proc_uap) {
-+        if (priv->proc_entry) {
-+            remove_proc_entry("info", priv->proc_entry);
-+            remove_proc_entry("hwstatus", priv->proc_entry);
-+        }
-+        remove_proc_entry(priv->uap_dev.netdev->name, priv->proc_uap);
-+    }
-+}
-+
-+/**
-+ *  @brief convert string to number
-+ *
-+ *  @param s     pointer to numbered string
-+ *  @return      converted number from string s
-+ */
-+int
-+string_to_number(char *s)
-+{
-+    int r = 0;
-+    int base = 0;
-+    int pn = 1;
-+
-+    if (strncmp(s, "-", 1) == 0) {
-+        pn = -1;
-+        s++;
-+    }
-+    if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) {
-+        base = 16;
-+        s += 2;
-+    } else
-+        base = 10;
-+
-+    for (s = s; *s != 0; s++) {
-+        if ((*s >= '0') && (*s <= '9'))
-+            r = (r * base) + (*s - '0');
-+        else if ((*s >= 'A') && (*s <= 'F'))
-+            r = (r * base) + (*s - 'A' + 10);
-+        else if ((*s >= 'a') && (*s <= 'f'))
-+            r = (r * base) + (*s - 'a' + 10);
-+        else
-+            break;
-+    }
-+
-+    return (r * pn);
-+}
-+
-+#endif
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c
---- backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c    1970-01-01 01:00:00.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c        2014-12-29 20:37:43.955764567 +0100
-@@ -0,0 +1,1428 @@
-+/** @file uap_sdio_mmc.c
-+ *  @brief This file contains SDIO IF (interface) module
-+ *  related functions.
-+ *
-+ * Copyright (C) 2007-2009, Marvell International Ltd.
-+ *
-+ * This software file (the "File") is distributed by Marvell International
-+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+ * (the "License").  You may use, redistribute and/or modify this File in
-+ * accordance with the terms and conditions of the License, a copy of which
-+ * is available along with the File in the gpl.txt file or by writing to
-+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+ *
-+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
-+ * this warranty disclaimer.
-+ *
-+ */
-+/****************************************************
-+Change log:
-+****************************************************/
-+
-+#include      "uap_sdio_mmc.h"
-+
-+#include <linux/firmware.h>
-+
-+/** define SDIO block size */
-+/* We support up to 480-byte block size due to FW buffer limitation. */
-+#define SD_BLOCK_SIZE         256
-+
-+/** define allocated buffer size */
-+#define ALLOC_BUF_SIZE                (((MAX(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, \
-+                                      MRVDRV_SIZE_OF_CMD_BUFFER) + INTF_HEADER_LEN \
-+                                      + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE)
-+
-+/** Max retry number of CMD53 write */
-+#define MAX_WRITE_IOMEM_RETRY 2
-+
-+/********************************************************
-+              Local Variables
-+********************************************************/
-+
-+/** SDIO Rx unit */
-+static u8 sdio_rx_unit = 0;
-+
-+/**Interrupt status */
-+static u8 sd_ireg = 0;
-+/********************************************************
-+              Global Variables
-+********************************************************/
-+extern u8 *helper_name;
-+extern u8 *fw_name;
-+/** Default helper name */
-+#define DEFAULT_HELPER_NAME "mrvl/helper_sd.bin"
-+/** Default firmware name */
-+#define DEFAULT_FW_NAME "mrvl/sd8688_ap.bin"
-+
-+/********************************************************
-+              Local Functions
-+********************************************************/
-+/**
-+ *  @brief This function reads the IO register.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param reg           register to be read
-+ *  @param dat           A pointer to variable that keeps returned value
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+sbi_read_ioreg(uap_private * priv, u32 reg, u8 * dat)
-+{
-+    struct sdio_mmc_card *card;
-+    int ret = UAP_STATUS_FAILURE;
-+
-+    ENTER();
-+
-+    card = priv->uap_dev.card;
-+    if (!card || !card->func) {
-+        PRINTM(ERROR, "sbi_read_ioreg(): card or function is NULL!\n");
-+        goto done;
-+    }
-+
-+    *dat = sdio_readb(card->func, reg, &ret);
-+    if (ret) {
-+        PRINTM(ERROR, "sbi_read_ioreg(): sdio_readb failed! ret=%d\n", ret);
-+        goto done;
-+    }
-+
-+    PRINTM(INFO, "sbi_read_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv,
-+           card->func->num, reg, *dat);
-+
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function writes the IO register.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param reg           register to be written
-+ *  @param dat           the value to be written
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+sbi_write_ioreg(uap_private * priv, u32 reg, u8 dat)
-+{
-+    struct sdio_mmc_card *card;
-+    int ret = UAP_STATUS_FAILURE;
-+
-+    ENTER();
-+
-+    card = priv->uap_dev.card;
-+    if (!card || !card->func) {
-+        PRINTM(ERROR, "sbi_write_ioreg(): card or function is NULL!\n");
-+        goto done;
-+    }
-+
-+    PRINTM(INFO, "sbi_write_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv,
-+           card->func->num, reg, dat);
-+
-+    sdio_writeb(card->func, dat, reg, &ret);
-+    if (ret) {
-+        PRINTM(ERROR, "sbi_write_ioreg(): sdio_readb failed! ret=%d\n", ret);
-+        goto done;
-+    }
-+
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function get rx_unit value
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+sd_get_rx_unit(uap_private * priv)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    u8 reg;
-+
-+    ENTER();
-+
-+    ret = sbi_read_ioreg(priv, CARD_RX_UNIT_REG, &reg);
-+    if (ret == UAP_STATUS_SUCCESS)
-+        sdio_rx_unit = reg;
-+
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function reads rx length
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param dat           A pointer to keep returned data
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+sd_read_rx_len(uap_private * priv, u16 * dat)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    u8 reg;
-+
-+    ENTER();
-+
-+    ret = sbi_read_ioreg(priv, CARD_RX_LEN_REG, &reg);
-+    if (ret == UAP_STATUS_SUCCESS)
-+        *dat = (u16) reg << sdio_rx_unit;
-+
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function reads fw status registers
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param dat           A pointer to keep returned data
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+sd_read_firmware_status(uap_private * priv, u16 * dat)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    u8 fws0;
-+    u8 fws1;
-+
-+    ENTER();
-+
-+    ret = sbi_read_ioreg(priv, CARD_FW_STATUS0_REG, &fws0);
-+    if (ret < 0) {
-+        LEAVE();
-+        return UAP_STATUS_FAILURE;
-+    }
-+
-+    ret = sbi_read_ioreg(priv, CARD_FW_STATUS1_REG, &fws1);
-+    if (ret < 0) {
-+        LEAVE();
-+        return UAP_STATUS_FAILURE;
-+    }
-+
-+    *dat = (((u16) fws1) << 8) | fws0;
-+
-+    LEAVE();
-+    return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ *  @brief This function polls the card status register.
-+ *
-+ *  @param priv       A pointer to uap_private structure
-+ *  @param bits       the bit mask
-+ *  @return           UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+mv_sdio_poll_card_status(uap_private * priv, u8 bits)
-+{
-+    int tries;
-+    u8 cs;
-+
-+    ENTER();
-+
-+    for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
-+        if (sbi_read_ioreg(priv, CARD_STATUS_REG, &cs) < 0)
-+            break;
-+        else if ((cs & bits) == bits) {
-+            LEAVE();
-+            return UAP_STATUS_SUCCESS;
-+        }
-+        udelay(10);
-+    }
-+
-+    PRINTM(WARN, "mv_sdio_poll_card_status failed, tries = %d\n", tries);
-+
-+    LEAVE();
-+    return UAP_STATUS_FAILURE;
-+}
-+
-+/**
-+ *  @brief This function set the sdio bus width.
-+ *
-+ *  @param priv       A pointer to uap_private structure
-+ *  @param mode       1--1 bit mode, 4--4 bit mode
-+ *  @return           UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+#if 0
-+static int
-+sdio_set_bus_width(uap_private * priv, u8 mode)
-+{
-+    ENTER();
-+    LEAVE();
-+    return UAP_STATUS_SUCCESS;
-+}
-+#endif
-+
-+/**
-+ *  @brief This function reads data from the card.
-+ *
-+ *  @param priv       A pointer to uap_private structure
-+ *  @return           UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+sd_card_to_host(uap_private * priv)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    u16 buf_len = 0;
-+    int buf_block_len;
-+    int blksz;
-+    struct sk_buff *skb = NULL;
-+    u16 type;
-+    u8 *payload = NULL;
-+    struct sdio_mmc_card *card = priv->uap_dev.card;
-+
-+    ENTER();
-+
-+    if (!card || !card->func) {
-+        PRINTM(ERROR, "card or function is NULL!\n");
-+        ret = UAP_STATUS_FAILURE;
-+        goto exit;
-+    }
-+
-+    /* Read the length of data to be transferred */
-+    ret = sd_read_rx_len(priv, &buf_len);
-+    if (ret < 0) {
-+        PRINTM(ERROR, "card_to_host, read scratch reg failed\n");
-+        ret = UAP_STATUS_FAILURE;
-+        goto exit;
-+    }
-+
-+    /* Allocate buffer */
-+    blksz = SD_BLOCK_SIZE;
-+    buf_block_len = (buf_len + blksz - 1) / blksz;
-+    if (buf_len <= INTF_HEADER_LEN || (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
-+        PRINTM(ERROR, "card_to_host, invalid packet length: %d\n", buf_len);
-+        ret = UAP_STATUS_FAILURE;
-+        goto exit;
-+    }
-+#ifdef PXA3XX_DMA_ALIGN
-+    skb = dev_alloc_skb(buf_block_len * blksz + PXA3XX_DMA_ALIGNMENT);
-+#else
-+    skb = dev_alloc_skb(buf_block_len * blksz);
-+#endif
-+    if (skb == NULL) {
-+        PRINTM(WARN, "No free skb\n");
-+        goto exit;
-+    }
-+#ifdef PXA3XX_DMA_ALIGN
-+    if ((u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)) {
-+        skb_put(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1));
-+        skb_pull(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1));
-+    }
-+#endif /* PXA3XX_DMA_ALIGN */
-+
-+    payload = skb->tail;
-+    ret = sdio_readsb(card->func, payload, priv->uap_dev.ioport,
-+                      buf_block_len * blksz);
-+    if (ret < 0) {
-+        PRINTM(ERROR, "card_to_host, read iomem failed: %d\n", ret);
-+        ret = UAP_STATUS_FAILURE;
-+        goto exit;
-+    }
-+    HEXDUMP("SDIO Blk Rd", payload, blksz * buf_block_len);
-+    /*
-+     * This is SDIO specific header
-+     *  u16 length,
-+     *  u16 type (MV_TYPE_DAT = 0, MV_TYPE_CMD = 1, MV_TYPE_EVENT = 3)
-+     */
-+    buf_len = uap_le16_to_cpu(*(u16 *) & payload[0]);
-+    type = uap_le16_to_cpu(*(u16 *) & payload[2]);
-+    switch (type) {
-+    case MV_TYPE_EVENT:
-+        skb_put(skb, buf_len);
-+        skb_pull(skb, INTF_HEADER_LEN);
-+        uap_process_event(priv, skb->data, skb->len);
-+        kfree_skb(skb);
-+        skb = NULL;
-+        break;
-+    case MV_TYPE_CMD:
-+        skb_put(skb, buf_len);
-+        skb_pull(skb, INTF_HEADER_LEN);
-+        priv->adapter->cmd_pending = FALSE;
-+        if (priv->adapter->cmd_wait_option ==
-+            HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM) {
-+            priv->adapter->cmd_wait_option = FALSE;
-+            uap_process_sleep_confirm_resp(priv, skb->data, skb->len);
-+        } else if (priv->adapter->cmd_wait_option) {
-+            memcpy(priv->adapter->CmdBuf, skb->data, skb->len);
-+            priv->adapter->CmdSize = skb->len;
-+            priv->adapter->cmd_wait_option = FALSE;
-+            priv->adapter->CmdWaitQWoken = TRUE;
-+            wake_up_interruptible(&priv->adapter->cmdwait_q);
-+        }
-+        kfree_skb(skb);
-+        skb = NULL;
-+        break;
-+    case MV_TYPE_DAT:
-+        skb_put(skb, buf_len);
-+        skb_pull(skb, INTF_HEADER_LEN);
-+        uap_process_rx_packet(priv, skb);
-+        break;
-+    default:
-+        priv->stats.rx_errors++;
-+        priv->stats.rx_dropped++;
-+        /* Driver specified event and command resp should be handle here */
-+        PRINTM(INFO, "Unknown PKT type:%d\n", type);
-+        kfree_skb(skb);
-+        skb = NULL;
-+        break;
-+    }
-+  exit:
-+    if (ret) {
-+        if (skb)
-+            kfree_skb(skb);
-+    }
-+
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function enables the host interrupts mask
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param mask          the interrupt mask
-+ *  @return      UAP_STATUS_SUCCESS
-+ */
-+static int
-+enable_host_int_mask(uap_private * priv, u8 mask)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+
-+    ENTER();
-+
-+    /* Simply write the mask to the register */
-+    ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, mask);
-+
-+    if (ret) {
-+        PRINTM(WARN, "Unable to enable the host interrupt!\n");
-+        ret = UAP_STATUS_FAILURE;
-+    }
-+
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**  @brief This function disables the host interrupts mask.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param mask          the interrupt mask
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+disable_host_int_mask(uap_private * priv, u8 mask)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    u8 host_int_mask;
-+
-+    ENTER();
-+
-+    /* Read back the host_int_mask register */
-+    ret = sbi_read_ioreg(priv, HOST_INT_MASK_REG, &host_int_mask);
-+    if (ret) {
-+        ret = UAP_STATUS_FAILURE;
-+        goto done;
-+    }
-+
-+    /* Update with the mask and write back to the register */
-+    host_int_mask &= ~mask;
-+    ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, host_int_mask);
-+    if (ret < 0) {
-+        PRINTM(WARN, "Unable to diable the host interrupt!\n");
-+        ret = UAP_STATUS_FAILURE;
-+        goto done;
-+    }
-+
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/********************************************************
-+              Global Functions
-+********************************************************/
-+
-+/**
-+ *  @brief This function handles the interrupt.
-+ *
-+ *  @param func          A pointer to sdio_func structure.
-+ *  @return      n/a
-+ */
-+static void
-+sbi_interrupt(struct sdio_func *func)
-+{
-+    struct sdio_mmc_card *card;
-+    uap_private *priv;
-+    u8 ireg = 0;
-+    int ret = UAP_STATUS_SUCCESS;
-+
-+    ENTER();
-+
-+    card = sdio_get_drvdata(func);
-+    if (!card || !card->priv) {
-+        PRINTM(MSG, "%s: sbi_interrupt(%p) card or priv is NULL, card=%p\n",
-+               __FUNCTION__, func, card);
-+        LEAVE();
-+        return;
-+    }
-+    priv = card->priv;
-+#ifdef FW_WAKEUP_TIME
-+    if ((priv->adapter->wt_pwrup_sending != 0L) &&
-+        (priv->adapter->wt_int == 0L))
-+        priv->adapter->wt_int = get_utimeofday();
-+#endif
-+
-+    ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
-+    if (ret) {
-+        PRINTM(WARN, "sdio_read_ioreg: read int status register failed\n");
-+        goto done;
-+    }
-+    if (ireg != 0) {
-+        /*
-+         * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
-+         * Clear the interrupt status register and re-enable the interrupt
-+         */
-+        PRINTM(INFO, "sdio_ireg = 0x%x\n", ireg);
-+        sdio_writeb(card->func,
-+                    ~(ireg) & (DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS),
-+                    HOST_INTSTATUS_REG, &ret);
-+        if (ret) {
-+            PRINTM(WARN,
-+                   "sdio_write_ioreg: clear int status register failed\n");
-+            goto done;
-+        }
-+    }
-+    OS_INT_DISABLE;
-+    sd_ireg |= ireg;
-+    OS_INT_RESTORE;
-+
-+    uap_interrupt(priv);
-+  done:
-+    LEAVE();
-+}
-+
-+/**
-+ *  @brief This function probe the card
-+ *
-+ *  @param func    A pointer to sdio_func structure
-+ *  @param id    A pointer to structure sd_device_id
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_probe(struct sdio_func *func, const struct sdio_device_id *id)
-+{
-+    int ret = UAP_STATUS_FAILURE;
-+    struct sdio_mmc_card *card = NULL;
-+
-+    ENTER();
-+
-+    PRINTM(MSG, "%s: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
-+           __FUNCTION__, func->vendor, func->device, func->class, func->num);
-+
-+    card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
-+    if (!card) {
-+        ret = -ENOMEM;
-+        goto done;
-+    }
-+
-+    card->func = func;
-+
-+    if (!uap_add_card(card)) {
-+        PRINTM(ERROR, "%s: uap_add_callback failed\n", __FUNCTION__);
-+        kfree(card);
-+        ret = UAP_STATUS_FAILURE;
-+        goto done;
-+    }
-+
-+    ret = UAP_STATUS_SUCCESS;
-+
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function removes the card
-+ *
-+ *  @param func    A pointer to sdio_func structure
-+ *  @return        N/A
-+ */
-+static void
-+uap_remove(struct sdio_func *func)
-+{
-+    struct sdio_mmc_card *card;
-+
-+    ENTER();
-+
-+    if (func) {
-+        card = sdio_get_drvdata(func);
-+        if (card) {
-+            uap_remove_card(card);
-+            kfree(card);
-+        }
-+    }
-+
-+    LEAVE();
-+}
-+
-+#ifdef CONFIG_PM
-+/**
-+ *  @brief This function handles client driver suspend
-+ *
-+ *  @param func    A pointer to sdio_func structure
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+uap_suspend(struct sdio_func *func)
-+{
-+    ENTER();
-+    LEAVE();
-+    return 0;
-+}
-+
-+/**
-+ *  @brief This function handles client driver resume
-+ *
-+ *  @param func    A pointer to sdio_func structure
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+uap_resume(struct sdio_func *func)
-+{
-+    ENTER();
-+    LEAVE();
-+    return 0;
-+}
-+#endif
-+
-+/** Device ID for SD8688 */
-+#define  SD_DEVICE_ID_8688_UAP 0x9104
-+/** UAP IDs */
-+static const struct sdio_device_id uap_ids[] = {
-+    {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SD_DEVICE_ID_8688_UAP)},
-+    {},
-+};
-+
-+MODULE_DEVICE_TABLE(sdio, uap_ids);
-+
-+static struct sdio_driver uap_sdio = {
-+    .name = "uap_sdio",
-+    .id_table = uap_ids,
-+    .probe = uap_probe,
-+    .remove = uap_remove,
-+#ifdef CONFIG_PM
-+/*    .suspend        = uap_suspend, */
-+/*    .resume = uap_resume, */
-+#endif
-+
-+};
-+
-+/**
-+ *  @brief This function registers the IF module in bus driver.
-+ *
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int __init
-+sbi_register()
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+
-+    ENTER();
-+
-+    /* SDIO Driver Registration */
-+    if (sdio_register_driver(&uap_sdio) != 0) {
-+        PRINTM(FATAL, "SDIO Driver Registration Failed \n");
-+        ret = UAP_STATUS_FAILURE;
-+    }
-+
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function de-registers the IF module in bus driver.
-+ *
-+ *  @return      n/a
-+ */
-+void __exit
-+sbi_unregister(void)
-+{
-+    ENTER();
-+
-+    /* SDIO Driver Unregistration */
-+    sdio_unregister_driver(&uap_sdio);
-+
-+    LEAVE();
-+}
-+
-+/**
-+ *  @brief This function checks the interrupt status and handle it accordingly.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param ireg    A pointer to variable that keeps returned value
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_get_int_status(uap_private * priv, u8 * ireg)
-+{
-+    int ret = UAP_STATUS_SUCCESS;
-+    u8 sdio_ireg = 0;
-+    struct sdio_mmc_card *card = priv->uap_dev.card;
-+
-+    ENTER();
-+
-+    *ireg = 0;
-+    OS_INT_DISABLE;
-+    sdio_ireg = sd_ireg;
-+    sd_ireg = 0;
-+    OS_INT_RESTORE;
-+
-+    sdio_claim_host(card->func);
-+
-+    if (sdio_ireg & DN_LD_HOST_INT_STATUS) {    /* tx_done INT */
-+        if (!priv->uap_dev.cmd_sent) {  /* tx_done already received */
-+            PRINTM(INFO,
-+                   "warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n",
-+                   priv->uap_dev.cmd_sent, sdio_ireg);
-+        } else {
-+            priv->uap_dev.cmd_sent = FALSE;
-+            priv->uap_dev.data_sent = FALSE;
-+            if ( (priv->uap_dev.netdev->reg_state == NETREG_REGISTERED) && (skb_queue_len(&priv->adapter->tx_queue) < TX_LOW_WATERMARK)) {
-+                os_start_queue(priv);
-+          }
-+        }
-+    }
-+    if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
-+        sd_card_to_host(priv);
-+    }
-+
-+    *ireg = sdio_ireg;
-+    ret = UAP_STATUS_SUCCESS;
-+    sdio_release_host(card->func);
-+
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function disables the host interrupts.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_disable_host_int(uap_private * priv)
-+{
-+    struct sdio_mmc_card *card = priv->uap_dev.card;
-+    int ret;
-+
-+    ENTER();
-+
-+    sdio_claim_host(card->func);
-+    ret = disable_host_int_mask(priv, HIM_DISABLE);
-+    sdio_release_host(card->func);
-+
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function enables the host interrupts.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS
-+ */
-+int
-+sbi_enable_host_int(uap_private * priv)
-+{
-+    struct sdio_mmc_card *card = priv->uap_dev.card;
-+    int ret;
-+
-+    ENTER();
-+
-+    sdio_claim_host(card->func);
-+    ret = enable_host_int_mask(priv, HIM_ENABLE);
-+    sdio_release_host(card->func);
-+
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function de-registers the device.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS
-+ */
-+int
-+sbi_unregister_dev(uap_private * priv)
-+{
-+    struct sdio_mmc_card *card = priv->uap_dev.card;
-+
-+    ENTER();
-+
-+    if (!card || !card->func) {
-+        PRINTM(ERROR, "Error: card or function is NULL!\n");
-+        goto done;
-+    }
-+
-+    sdio_claim_host(card->func);
-+    sdio_release_irq(card->func);
-+    sdio_disable_func(card->func);
-+    sdio_release_host(card->func);
-+
-+    sdio_set_drvdata(card->func, NULL);
-+
-+  done:
-+    LEAVE();
-+    return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ *  @brief This function registers the device.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_register_dev(uap_private * priv)
-+{
-+    int ret = UAP_STATUS_FAILURE;
-+    u8 reg;
-+    struct sdio_mmc_card *card = priv->uap_dev.card;
-+    struct sdio_func *func;
-+
-+    ENTER();
-+
-+    if (!card || !card->func) {
-+        PRINTM(ERROR, "Error: card or function is NULL!\n");
-+        goto done;
-+    }
-+
-+    func = card->func;
-+
-+    /* Initialize the private structure */
-+    priv->uap_dev.ioport = 0;
-+
-+    sdio_claim_host(func);
-+
-+    ret = sdio_enable_func(func);
-+    if (ret) {
-+        PRINTM(FATAL, "sdio_enable_func() failed: ret=%d\n", ret);
-+        goto release_host;
-+    }
-+
-+    ret = sdio_claim_irq(func, sbi_interrupt);
-+    if (ret) {
-+        PRINTM(FATAL, "sdio_claim_irq failed: ret=%d\n", ret);
-+        goto disable_func;
-+    }
-+
-+    /* Read the IO port */
-+    ret = sbi_read_ioreg(priv, IO_PORT_0_REG, &reg);
-+    if (ret)
-+        goto release_irq;
-+    else
-+        priv->uap_dev.ioport |= reg;
-+
-+    ret = sbi_read_ioreg(priv, IO_PORT_1_REG, &reg);
-+    if (ret)
-+        goto release_irq;
-+    else
-+        priv->uap_dev.ioport |= (reg << 8);
-+
-+    ret = sbi_read_ioreg(priv, IO_PORT_2_REG, &reg);
-+    if (ret)
-+        goto release_irq;
-+    else
-+        priv->uap_dev.ioport |= (reg << 16);
-+
-+    PRINTM(INFO, "SDIO FUNC #%d IO port: 0x%x\n", func->num,
-+           priv->uap_dev.ioport);
-+
-+    ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE);
-+    if (ret) {
-+        PRINTM(ERROR, "%s: cannot set SDIO block size\n", __FUNCTION__);
-+        ret = UAP_STATUS_FAILURE;
-+        goto release_irq;
-+    }
-+    priv->hotplug_device = &func->dev;
-+
-+    if (helper_name == NULL) {
-+        helper_name = DEFAULT_HELPER_NAME;
-+    }
-+    if (fw_name == NULL) {
-+        fw_name = DEFAULT_FW_NAME;
-+    }
-+    sdio_release_host(func);
-+
-+    sdio_set_drvdata(func, card);
-+
-+    ret = UAP_STATUS_SUCCESS;
-+    goto done;
-+
-+  release_irq:
-+    sdio_release_irq(func);
-+  disable_func:
-+    sdio_disable_func(func);
-+  release_host:
-+    sdio_release_host(func);
-+
-+  done:
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function sends data to the card.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param payload A pointer to the data/cmd buffer
-+ *  @param nb    the length of data/cmd
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb)
-+{
-+    struct sdio_mmc_card *card = priv->uap_dev.card;
-+    int ret = UAP_STATUS_SUCCESS;
-+    int buf_block_len;
-+    int blksz;
-+    int i = 0;
-+    u8 *buf = NULL;
-+#ifdef PXA3XX_DMA_ALIGN
-+    void *tmpbuf = NULL;
-+    int tmpbufsz;
-+#endif
-+
-+    ENTER();
-+
-+    if (!card || !card->func) {
-+        PRINTM(ERROR, "card or function is NULL!\n");
-+        LEAVE();
-+        return UAP_STATUS_FAILURE;
-+    }
-+    buf = payload;
-+#ifdef PXA3XX_DMA_ALIGN
-+    if ((u32) payload & (PXA3XX_DMA_ALIGNMENT - 1)) {
-+        tmpbufsz = ALIGN_SZ(nb, PXA3XX_DMA_ALIGNMENT);
-+        tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL);
-+        memset(tmpbuf, 0, tmpbufsz);
-+        /* Ensure 8-byte aligned CMD buffer */
-+        buf = (u8 *) ALIGN_ADDR(tmpbuf, PXA3XX_DMA_ALIGNMENT);
-+        memcpy(buf, payload, nb);
-+    }
-+#endif
-+    /* Allocate buffer and copy payload */
-+    blksz = SD_BLOCK_SIZE;
-+    buf_block_len = (nb + blksz - 1) / blksz;
-+    sdio_claim_host(card->func);
-+#define MAX_WRITE_IOMEM_RETRY 2
-+    priv->uap_dev.cmd_sent = TRUE;
-+    priv->uap_dev.data_sent = TRUE;
-+    do {
-+        /* Transfer data to card */
-+        ret = sdio_writesb(card->func, priv->uap_dev.ioport, buf,
-+                           buf_block_len * blksz);
-+        if (ret < 0) {
-+            i++;
-+            PRINTM(ERROR, "host_to_card, write iomem (%d) failed: %d\n", i,
-+                   ret);
-+            ret = UAP_STATUS_FAILURE;
-+            if (i > MAX_WRITE_IOMEM_RETRY)
-+                goto exit;
-+        } else {
-+            HEXDUMP("SDIO Blk Wr", payload, nb);
-+        }
-+    } while (ret == UAP_STATUS_FAILURE);
-+  exit:
-+    sdio_release_host(card->func);
-+#ifdef PXA3XX_DMA_ALIGN
-+    if (tmpbuf)
-+        kfree(tmpbuf);
-+#endif
-+    if (ret == UAP_STATUS_FAILURE) {
-+        priv->uap_dev.cmd_sent = FALSE;
-+        priv->uap_dev.data_sent = FALSE;
-+    }
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function reads CIS information.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param cisinfo A pointer to CIS information output buffer
-+ *  @param cislen  A pointer to length of CIS info output buffer
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+#if 0
-+static int
-+sbi_get_cis_info(uap_private * priv, void *cisinfo, int *cislen)
-+{
-+#define CIS_PTR (0x8000)
-+    struct sdio_mmc_card *card = priv->uap_dev.card;
-+    unsigned int i, cis_ptr = CIS_PTR;
-+    int ret = UAP_STATUS_FAILURE;
-+
-+    ENTER();
-+
-+    if (!card || !card->func) {
-+        PRINTM(ERROR, "sbi_get_cis_info(): card or function is NULL!\n");
-+        goto exit;
-+    }
-+#define MAX_SDIO_CIS_INFO_LEN (256)
-+    if (!cisinfo || (*cislen < MAX_SDIO_CIS_INFO_LEN)) {
-+        PRINTM(WARN, "ERROR! get_cis_info: insufficient buffer passed\n");
-+        goto exit;
-+    }
-+
-+    *cislen = MAX_SDIO_CIS_INFO_LEN;
-+
-+    sdio_claim_host(card->func);
-+
-+    PRINTM(INFO, "cis_ptr=%#x\n", cis_ptr);
-+
-+    /* Read the Tuple Data */
-+    for (i = 0; i < *cislen; i++) {
-+        ((unsigned char *) cisinfo)[i] =
-+            sdio_readb(card->func, cis_ptr + i, &ret);
-+        if (ret) {
-+            PRINTM(WARN, "get_cis_info error: ret=%d\n", ret);
-+            ret = UAP_STATUS_FAILURE;
-+            goto done;
-+        }
-+        PRINTM(INFO, "cisinfo[%d]=%#x\n", i, ((unsigned char *) cisinfo)[i]);
-+    }
-+
-+  done:
-+    sdio_release_host(card->func);
-+  exit:
-+    LEAVE();
-+    return ret;
-+}
-+#endif
-+/**
-+ *  @brief This function downloads helper image to the card.
-+ *
-+ *  @param priv       A pointer to uap_private structure
-+ *  @return           UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_prog_helper(uap_private * priv)
-+{
-+    struct sdio_mmc_card *card = priv->uap_dev.card;
-+    u8 *helper = NULL;
-+    int helperlen;
-+    int ret = UAP_STATUS_SUCCESS;
-+    void *tmphlprbuf = NULL;
-+    int tmphlprbufsz;
-+    u8 *hlprbuf;
-+    int hlprblknow;
-+    u32 tx_len;
-+#ifdef FW_DOWNLOAD_SPEED
-+    u32 tv1, tv2;
-+#endif
-+
-+    ENTER();
-+
-+    if (!card || !card->func) {
-+        PRINTM(ERROR, "sbi_prog_helper(): card or function is NULL!\n");
-+        goto done;
-+    }
-+
-+    if (priv->fw_helper) {
-+        helper = (u8 *) priv->fw_helper->data;
-+        helperlen = priv->fw_helper->size;
-+    } else {
-+        PRINTM(MSG, "No helper image found! Terminating download.\n");
-+        LEAVE();
-+        return UAP_STATUS_FAILURE;
-+    }
-+
-+    PRINTM(INFO, "Downloading helper image (%d bytes), block size %d bytes\n",
-+           helperlen, SD_BLOCK_SIZE);
-+
-+#ifdef FW_DOWNLOAD_SPEED
-+    tv1 = get_utimeofday();
-+#endif
-+
-+#ifdef PXA3XX_DMA_ALIGN
-+    tmphlprbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT);
-+#else /* !PXA3XX_DMA_ALIGN */
-+    tmphlprbufsz = UAP_UPLD_SIZE;
-+#endif /* !PXA3XX_DMA_ALIGN */
-+    tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL);
-+    if (!tmphlprbuf) {
-+        PRINTM(ERROR,
-+               "Unable to allocate buffer for helper. Terminating download\n");
-+        ret = UAP_STATUS_FAILURE;
-+        goto done;
-+    }
-+    memset(tmphlprbuf, 0, tmphlprbufsz);
-+#ifdef PXA3XX_DMA_ALIGN
-+    hlprbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, PXA3XX_DMA_ALIGNMENT);
-+#else /* !PXA3XX_DMA_ALIGN */
-+    hlprbuf = (u8 *) tmphlprbuf;
-+#endif /* !PXA3XX_DMA_ALIGN */
-+
-+    sdio_claim_host(card->func);
-+
-+    /* Perform helper data transfer */
-+    tx_len = (FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE) - INTF_HEADER_LEN;
-+    hlprblknow = 0;
-+    do {
-+        /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */
-+        ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
-+        if (ret < 0) {
-+            PRINTM(FATAL, "Helper download poll status timeout @ %d\n",
-+                   hlprblknow);
-+            goto done;
-+        }
-+
-+        /* More data? */
-+        if (hlprblknow >= helperlen)
-+            break;
-+
-+        /* Set blocksize to transfer - checking for last block */
-+        if (helperlen - hlprblknow < tx_len)
-+            tx_len = helperlen - hlprblknow;
-+
-+        /* Set length to the 4-byte header */
-+        *(u32 *) hlprbuf = uap_cpu_to_le32(tx_len);
-+
-+        /* Copy payload to buffer */
-+        memcpy(&hlprbuf[INTF_HEADER_LEN], &helper[hlprblknow], tx_len);
-+
-+        PRINTM(INFO, ".");
-+
-+        /* Send data */
-+        ret = sdio_writesb(card->func, priv->uap_dev.ioport,
-+                           hlprbuf, FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE);
-+
-+        if (ret < 0) {
-+            PRINTM(FATAL, "IO error during helper download @ %d\n", hlprblknow);
-+            goto done;
-+        }
-+
-+        hlprblknow += tx_len;
-+    } while (TRUE);
-+
-+#ifdef FW_DOWNLOAD_SPEED
-+    tv2 = get_utimeofday();
-+    PRINTM(INFO, "helper: %ld.%03ld.%03ld ", tv1 / 1000000,
-+           (tv1 % 1000000) / 1000, tv1 % 1000);
-+    PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, (tv2 % 1000000) / 1000,
-+           tv2 % 1000);
-+    tv2 -= tv1;
-+    PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, (tv2 % 1000000) / 1000,
-+           tv2 % 1000);
-+#endif
-+
-+    /* Write last EOF data */
-+    PRINTM(INFO, "\nTransferring helper image EOF block\n");
-+    memset(hlprbuf, 0x0, SD_BLOCK_SIZE);
-+    ret = sdio_writesb(card->func, priv->uap_dev.ioport,
-+                       hlprbuf, SD_BLOCK_SIZE);
-+
-+    if (ret < 0) {
-+        PRINTM(FATAL, "IO error in writing helper image EOF block\n");
-+        goto done;
-+    }
-+
-+    ret = UAP_STATUS_SUCCESS;
-+
-+  done:
-+    sdio_release_host(card->func);
-+    if (tmphlprbuf)
-+        kfree(tmphlprbuf);
-+
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function downloads firmware image to the card.
-+ *
-+ *  @param priv       A pointer to uap_private structure
-+ *  @return           UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_prog_fw_w_helper(uap_private * priv)
-+{
-+    struct sdio_mmc_card *card = priv->uap_dev.card;
-+    u8 *firmware = NULL;
-+    int firmwarelen;
-+    u8 base0;
-+    u8 base1;
-+    int ret = UAP_STATUS_SUCCESS;
-+    int offset;
-+    void *tmpfwbuf = NULL;
-+    int tmpfwbufsz;
-+    u8 *fwbuf;
-+    u16 len;
-+    int txlen = 0;
-+    int tx_blocks = 0;
-+    int i = 0;
-+    int tries = 0;
-+#ifdef FW_DOWNLOAD_SPEED
-+    u32 tv1, tv2;
-+#endif
-+
-+    ENTER();
-+
-+    if (!card || !card->func) {
-+        PRINTM(ERROR, "sbi_prog_fw_w_helper(): card or function is NULL!\n");
-+        goto done;
-+    }
-+
-+    if (priv->firmware) {
-+        firmware = (u8 *) priv->firmware->data;
-+        firmwarelen = priv->firmware->size;
-+    } else {
-+        PRINTM(MSG, "No firmware image found! Terminating download.\n");
-+        LEAVE();
-+        return UAP_STATUS_FAILURE;
-+    }
-+
-+    PRINTM(INFO, "Downloading FW image (%d bytes)\n", firmwarelen);
-+
-+#ifdef FW_DOWNLOAD_SPEED
-+    tv1 = get_utimeofday();
-+#endif
-+
-+#ifdef PXA3XX_DMA_ALIGN
-+    tmpfwbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT);
-+#else /* PXA3XX_DMA_ALIGN */
-+    tmpfwbufsz = UAP_UPLD_SIZE;
-+#endif /* PXA3XX_DMA_ALIGN */
-+    tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL);
-+    if (!tmpfwbuf) {
-+        PRINTM(ERROR,
-+               "Unable to allocate buffer for firmware. Terminating download.\n");
-+        ret = UAP_STATUS_FAILURE;
-+        goto done;
-+    }
-+    memset(tmpfwbuf, 0, tmpfwbufsz);
-+#ifdef PXA3XX_DMA_ALIGN
-+    /* Ensure 8-byte aligned firmware buffer */
-+    fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, PXA3XX_DMA_ALIGNMENT);
-+#else /* PXA3XX_DMA_ALIGN */
-+    fwbuf = (u8 *) tmpfwbuf;
-+#endif /* PXA3XX_DMA_ALIGN */
-+
-+    sdio_claim_host(card->func);
-+
-+    /* Perform firmware data transfer */
-+    offset = 0;
-+    do {
-+        /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */
-+        ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
-+        if (ret < 0) {
-+            PRINTM(FATAL, "FW download with helper poll status timeout @ %d\n",
-+                   offset);
-+            goto done;
-+        }
-+
-+        /* More data? */
-+        if (offset >= firmwarelen)
-+            break;
-+
-+        for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
-+            if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_0, &base0)) < 0) {
-+                PRINTM(WARN, "Dev BASE0 register read failed:"
-+                       " base0=0x%04X(%d). Terminating download.\n", base0,
-+                       base0);
-+                ret = UAP_STATUS_FAILURE;
-+                goto done;
-+            }
-+            if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_1, &base1)) < 0) {
-+                PRINTM(WARN, "Dev BASE1 register read failed:"
-+                       " base1=0x%04X(%d). Terminating download.\n", base1,
-+                       base1);
-+                ret = UAP_STATUS_FAILURE;
-+                goto done;
-+            }
-+            len = (((u16) base1) << 8) | base0;
-+
-+            /* For SD8688 wait until the length is not 0, 1 or 2 before
-+               downloading the first FW block, since BOOT code writes the
-+               register to indicate the helper/FW download winner, the value
-+               could be 1 or 2 (Func1 or Func2). */
-+            if ((len && offset) || (len > 2))
-+                break;
-+            udelay(10);
-+        }
-+
-+        if (len == 0)
-+            break;
-+        else if (len > UAP_UPLD_SIZE) {
-+            PRINTM(FATAL, "FW download failure @ %d, invalid length %d\n",
-+                   offset, len);
-+            ret = UAP_STATUS_FAILURE;
-+            goto done;
-+        }
-+
-+        txlen = len;
-+
-+        if (len & BIT(0)) {
-+            i++;
-+            if (i > MAX_WRITE_IOMEM_RETRY) {
-+                PRINTM(FATAL,
-+                       "FW download failure @ %d, over max retry count\n",
-+                       offset);
-+                ret = UAP_STATUS_FAILURE;
-+                goto done;
-+            }
-+            PRINTM(ERROR, "FW CRC error indicated by the helper:"
-+                   " len = 0x%04X, txlen = %d\n", len, txlen);
-+            len &= ~BIT(0);
-+            /* Setting this to 0 to resend from same offset */
-+            txlen = 0;
-+        } else {
-+            i = 0;
-+
-+            /* Set blocksize to transfer - checking for last block */
-+            if (firmwarelen - offset < txlen) {
-+                txlen = firmwarelen - offset;
-+            }
-+            PRINTM(INFO, ".");
-+
-+            tx_blocks = (txlen + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE;
-+
-+            /* Copy payload to buffer */
-+            memcpy(fwbuf, &firmware[offset], txlen);
-+        }
-+
-+        /* Send data */
-+        ret = sdio_writesb(card->func, priv->uap_dev.ioport,
-+                           fwbuf, tx_blocks * SD_BLOCK_SIZE);
-+
-+        if (ret < 0) {
-+            PRINTM(ERROR, "FW download, write iomem (%d) failed @ %d\n", i,
-+                   offset);
-+            if (sbi_write_ioreg(priv, CONFIGURATION_REG, 0x04) < 0) {
-+                PRINTM(ERROR, "write ioreg failed (CFG)\n");
-+            }
-+        }
-+
-+        offset += txlen;
-+    } while (TRUE);
-+
-+    PRINTM(INFO, "\nFW download over, size %d bytes\n", offset);
-+
-+    ret = UAP_STATUS_SUCCESS;
-+  done:
-+#ifdef FW_DOWNLOAD_SPEED
-+    tv2 = get_utimeofday();
-+    PRINTM(INFO, "FW: %ld.%03ld.%03ld ", tv1 / 1000000,
-+           (tv1 % 1000000) / 1000, tv1 % 1000);
-+    PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000,
-+           (tv2 % 1000000) / 1000, tv2 % 1000);
-+    tv2 -= tv1;
-+    PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000,
-+           (tv2 % 1000000) / 1000, tv2 % 1000);
-+#endif
-+    sdio_release_host(card->func);
-+    if (tmpfwbuf)
-+        kfree(tmpfwbuf);
-+
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function checks if the firmware is ready to accept
-+ *  command or not.
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param pollnum Poll number
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_check_fw_status(uap_private * priv, int pollnum)
-+{
-+    struct sdio_mmc_card *card = priv->uap_dev.card;
-+    int ret = UAP_STATUS_SUCCESS;
-+    u16 firmwarestat;
-+    int tries;
-+
-+    ENTER();
-+
-+    sdio_claim_host(card->func);
-+
-+    /* Wait for firmware initialization event */
-+    for (tries = 0; tries < pollnum; tries++) {
-+        if ((ret = sd_read_firmware_status(priv, &firmwarestat)) < 0)
-+            continue;
-+        if (firmwarestat == FIRMWARE_READY) {
-+            ret = UAP_STATUS_SUCCESS;
-+            break;
-+        } else {
-+            mdelay(10);
-+            ret = UAP_STATUS_FAILURE;
-+        }
-+    }
-+
-+    if (ret < 0)
-+        goto done;
-+
-+    ret = UAP_STATUS_SUCCESS;
-+    sd_get_rx_unit(priv);
-+
-+  done:
-+    sdio_release_host(card->func);
-+
-+    LEAVE();
-+    return ret;
-+}
-+
-+/**
-+ *  @brief This function set bus clock on/off
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @param option    TRUE--on , FALSE--off
-+ *  @return      UAP_STATUS_SUCCESS
-+ */
-+#if 0
-+static int
-+sbi_set_bus_clock(uap_private * priv, u8 option)
-+{
-+    ENTER();
-+    LEAVE();
-+    return UAP_STATUS_SUCCESS;
-+}
-+#endif
-+
-+/**
-+ *  @brief This function wakeup firmware
-+ *
-+ *  @param priv    A pointer to uap_private structure
-+ *  @return      UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_wakeup_firmware(uap_private * priv)
-+{
-+    struct sdio_mmc_card *card = priv->uap_dev.card;
-+    int ret = UAP_STATUS_SUCCESS;
-+
-+    ENTER();
-+
-+    if (!card || !card->func) {
-+        PRINTM(ERROR, "card or function is NULL!\n");
-+        LEAVE();
-+        return UAP_STATUS_FAILURE;
-+    }
-+    sdio_claim_host(card->func);
-+    sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
-+    sdio_release_host(card->func);
-+    LEAVE();
-+    return ret;
-+}
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h
---- backports-3.18.1-1.org/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h    1970-01-01 01:00:00.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h        2014-12-29 20:37:43.955764567 +0100
-@@ -0,0 +1,136 @@
-+/** @file uap_sdio_mmc.h
-+ *  @brief This file contains SDIO IF (interface) module
-+ *  related macros, enum, and structure.
-+ *
-+ * Copyright (C) 2007-2009, Marvell International Ltd.
-+ *
-+ * This software file (the "File") is distributed by Marvell International
-+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+ * (the "License").  You may use, redistribute and/or modify this File in
-+ * accordance with the terms and conditions of the License, a copy of which
-+ * is available along with the File in the gpl.txt file or by writing to
-+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+ *
-+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
-+ * this warranty disclaimer.
-+ *
-+ */
-+/****************************************************
-+Change log:
-+      10/10/07: initial version
-+****************************************************/
-+
-+#ifndef       _UAP_SDIO_MMC_H
-+#define       _UAP_SDIO_MMC_H
-+
-+#include      <linux/mmc/sdio.h>
-+#include      <linux/mmc/sdio_ids.h>
-+#include      <linux/mmc/sdio_func.h>
-+#include      <linux/mmc/card.h>
-+
-+#include      "uap_headers.h"
-+
-+/** The number of times to try when waiting for downloaded firmware to
-+     become active. (polling the scratch register). */
-+#define MAX_FIRMWARE_POLL_TRIES               100
-+
-+/** Firmware ready */
-+#define FIRMWARE_READY                        0xfedc
-+
-+/** Number of firmware blocks to transfer */
-+#define FIRMWARE_TRANSFER_NBLOCK      2
-+
-+/* Host Control Registers */
-+/** Host Control Registers : I/O port 0 */
-+#define IO_PORT_0_REG                 0x00
-+/** Host Control Registers : I/O port 1 */
-+#define IO_PORT_1_REG                 0x01
-+/** Host Control Registers : I/O port 2 */
-+#define IO_PORT_2_REG                 0x02
-+
-+/** Host Control Registers : Configuration */
-+#define CONFIGURATION_REG             0x03
-+/** Host Control Registers : Host without Command 53 finish host */
-+#define HOST_WO_CMD53_FINISH_HOST     (0x1U << 2)
-+/** Host Control Registers : Host power up */
-+#define HOST_POWER_UP                 (0x1U << 1)
-+/** Host Control Registers : Host power down */
-+#define HOST_POWER_DOWN                       (0x1U << 0)
-+
-+/** Host Control Registers : Host interrupt mask */
-+#define HOST_INT_MASK_REG             0x04
-+/** Host Control Registers : Upload host interrupt mask */
-+#define UP_LD_HOST_INT_MASK           (0x1U)
-+/** Host Control Registers : Download host interrupt mask */
-+#define DN_LD_HOST_INT_MASK           (0x2U)
-+/** Enable Host interrupt mask */
-+#define HIM_ENABLE                    (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK)
-+/** Disable Host interrupt mask */
-+#define       HIM_DISABLE                     0xff
-+
-+/** Host Control Registers : Host interrupt status */
-+#define HOST_INTSTATUS_REG            0x05
-+/** Host Control Registers : Upload host interrupt status */
-+#define UP_LD_HOST_INT_STATUS         (0x1U)
-+/** Host Control Registers : Download host interrupt status */
-+#define DN_LD_HOST_INT_STATUS         (0x2U)
-+
-+/** Host F1 read base 0 */
-+#define HOST_F1_RD_BASE_0             0x10
-+/** Host F1 read base 1 */
-+#define HOST_F1_RD_BASE_1             0x11
-+
-+/** Card Control Registers : Card status register */
-+#define CARD_STATUS_REG               0x20
-+/** Card Control Registers : Card I/O ready */
-+#define CARD_IO_READY                 (0x1U << 3)
-+/** Card Control Registers : CIS card ready */
-+#define CIS_CARD_RDY                  (0x1U << 2)
-+/** Card Control Registers : Upload card ready */
-+#define UP_LD_CARD_RDY                (0x1U << 1)
-+/** Card Control Registers : Download card ready */
-+#define DN_LD_CARD_RDY                (0x1U << 0)
-+
-+/** Card Control Registers : Card OCR 0 register */
-+#define CARD_OCR_0_REG                0x34
-+/** Card Control Registers : Card OCR 1 register */
-+#define CARD_OCR_1_REG                0x35
-+
-+/** Firmware status 0 register */
-+#define CARD_FW_STATUS0_REG           0x40
-+/** Firmware status 1 register */
-+#define CARD_FW_STATUS1_REG           0x41
-+/** Rx length register */
-+#define CARD_RX_LEN_REG                       0x42
-+/** Rx unit register */
-+#define CARD_RX_UNIT_REG              0x43
-+
-+/** Chip Id Register 0 */
-+#define CARD_CHIP_ID_0_REG            0x801c
-+/** Chip Id Register 1 */
-+#define CARD_CHIP_ID_1_REG            0x801d
-+
-+#ifdef PXA3XX_DMA_ALIGN
-+/** DMA alignment value for PXA3XX platforms */
-+#define PXA3XX_DMA_ALIGNMENT    8
-+/** Macros for Data Alignment : size */
-+#define ALIGN_SZ(p, a)  \
-+    (((p) + ((a) - 1)) & ~((a) - 1))
-+
-+/** Macros for Data Alignment : address */
-+#define ALIGN_ADDR(p, a)    \
-+    ((((u32)(p)) + (((u32)(a)) - 1)) & ~(((u32)(a)) - 1))
-+#endif /* PXA3XX_DMA_ALIGN */
-+
-+struct sdio_mmc_card
-+{
-+        /** sdio_func structure pointer */
-+    struct sdio_func *func;
-+        /** uap_private structure pointer */
-+    uap_private *priv;
-+};
-+
-+#endif /* _UAP_SDIO_MMC_H */
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/Makefile backports-3.18.1-1/drivers/net/wireless/Makefile
---- backports-3.18.1-1.org/drivers/net/wireless/Makefile       2014-12-21 22:37:15.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/Makefile   2014-12-29 20:40:33.632440784 +0100
-@@ -60,3 +60,5 @@
- obj-$(CPTCFG_CW1200)  += cw1200/
- obj-$(CPTCFG_RSI_91X) += rsi/
-+
-+obj-$(CPTCFG_LIBERTAS_UAP)    += libertas_uap/
diff --git a/src/patches/backports-3.18.1-1_no_dma_sgtable_on_x86_64.patch b/src/patches/backports-3.18.1-1_no_dma_sgtable_on_x86_64.patch
deleted file mode 100644 (file)
index 5a2d04e..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-diff -Naur backports-4.1.1-1.org/compat/dma-shared-helpers.c backports-4.1.1-1/compat/dma-shared-helpers.c
---- backports-4.1.1-1.org/compat/dma-shared-helpers.c  2015-07-01 23:10:37.000000000 +0200
-+++ backports-4.1.1-1/compat/dma-shared-helpers.c      2015-09-25 13:29:14.006762269 +0200
-@@ -20,22 +20,3 @@
- #endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0) */
- #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) */
--#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0)
--/*
-- * Create scatter-list for the already allocated DMA buffer.
-- */
--int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
--               void *cpu_addr, dma_addr_t handle, size_t size)
--{
--      struct page *page = virt_to_page(cpu_addr);
--      int ret;
--
--      ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
--      if (unlikely(ret))
--              return ret;
--
--      sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
--      return 0;
--}
--EXPORT_SYMBOL_GPL(dma_common_get_sgtable);
--#endif /* RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0) */
diff --git a/src/patches/backports-3.18.1-1_rt2x00usb_suppress_queue_warnings.patch b/src/patches/backports-3.18.1-1_rt2x00usb_suppress_queue_warnings.patch
deleted file mode 100644 (file)
index 3f9308e..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/rt2x00/rt2800usb.c backports-3.18.1-1/drivers/net/wireless/rt2x00/rt2800usb.c
---- backports-3.18.1-1.org/drivers/net/wireless/rt2x00/rt2800usb.c     2014-12-21 22:37:14.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/rt2x00/rt2800usb.c 2015-04-07 11:44:16.647963570 +0200
-@@ -444,7 +444,7 @@
-       rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
-       if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
--              rt2x00_warn(rt2x00dev, "TX HW queue 0 timed out, invoke forced kick\n");
-+              rt2x00_dbg(rt2x00dev, "TX HW queue 0 timed out, invoke forced kick\n");
-               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);
-@@ -459,7 +459,7 @@
-       rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
-       if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
--              rt2x00_warn(rt2x00dev, "TX HW queue 1 timed out, invoke forced kick\n");
-+              rt2x00_dbg(rt2x00dev, "TX HW queue 1 timed out, invoke forced kick\n");
-               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
-@@ -609,7 +609,7 @@
-               if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
-                            !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
--                      rt2x00_warn(rt2x00dev, "Data pending for entry %u in queue %u\n",
-+                      rt2x00_dbg(rt2x00dev, "Data pending for entry %u in queue %u\n",
-                                   entry->entry_idx, qid);
-                       break;
-               }
-diff -Naur backports-3.18.1-1.org/drivers/net/wireless/rt2x00/rt2x00usb.c backports-3.18.1-1/drivers/net/wireless/rt2x00/rt2x00usb.c
---- backports-3.18.1-1.org/drivers/net/wireless/rt2x00/rt2x00usb.c     2014-12-21 22:37:14.000000000 +0100
-+++ backports-3.18.1-1/drivers/net/wireless/rt2x00/rt2x00usb.c 2015-04-07 11:42:41.723492892 +0200
-@@ -524,7 +524,7 @@
- static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
- {
--      rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n",
-+      rt2x00_dbg(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced reset\n",
-                   queue->qid);
-       rt2x00queue_stop_queue(queue);
diff --git a/src/patches/backports-4.2.6-1-add_usbnet_modules.patch b/src/patches/backports-4.2.6-1-add_usbnet_modules.patch
deleted file mode 100644 (file)
index 7ee228d..0000000
+++ /dev/null
@@ -1,29007 +0,0 @@
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/asix_common.c backports-4.2.6-1/drivers/net/usb/asix_common.c
---- backports-4.2.6-1.org/drivers/net/usb/asix_common.c        1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/asix_common.c    2016-06-28 14:35:17.965307221 +0200
-@@ -0,0 +1,584 @@
-+/*
-+ * ASIX AX8817X based USB 2.0 Ethernet Devices
-+ * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com>
-+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
-+ * Copyright (C) 2006 James Painter <jamie.painter@iname.com>
-+ * Copyright (c) 2002-2003 TiVo 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 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include "asix.h"
-+
-+int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-+                u16 size, void *data)
-+{
-+      int ret;
-+      ret = usbnet_read_cmd(dev, cmd,
-+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+                             value, index, data, size);
-+
-+      if (ret != size && ret >= 0)
-+              return -EINVAL;
-+      return ret;
-+}
-+
-+int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-+                 u16 size, void *data)
-+{
-+      return usbnet_write_cmd(dev, cmd,
-+                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+                              value, index, data, size);
-+}
-+
-+void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-+                        u16 size, void *data)
-+{
-+      usbnet_write_cmd_async(dev, cmd,
-+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+                             value, index, data, size);
-+}
-+
-+int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb,
-+                         struct asix_rx_fixup_info *rx)
-+{
-+      int offset = 0;
-+
-+      while (offset + sizeof(u16) <= skb->len) {
-+              u16 remaining = 0;
-+              unsigned char *data;
-+
-+              if (!rx->size) {
-+                      if ((skb->len - offset == sizeof(u16)) ||
-+                          rx->split_head) {
-+                              if(!rx->split_head) {
-+                                      rx->header = get_unaligned_le16(
-+                                                      skb->data + offset);
-+                                      rx->split_head = true;
-+                                      offset += sizeof(u16);
-+                                      break;
-+                              } else {
-+                                      rx->header |= (get_unaligned_le16(
-+                                                      skb->data + offset)
-+                                                      << 16);
-+                                      rx->split_head = false;
-+                                      offset += sizeof(u16);
-+                              }
-+                      } else {
-+                              rx->header = get_unaligned_le32(skb->data +
-+                                                              offset);
-+                              offset += sizeof(u32);
-+                      }
-+
-+                      /* get the packet length */
-+                      rx->size = (u16) (rx->header & 0x7ff);
-+                      if (rx->size != ((~rx->header >> 16) & 0x7ff)) {
-+                              netdev_err(dev->net, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n",
-+                                         rx->header, offset);
-+                              rx->size = 0;
-+                              return 0;
-+                      }
-+                      rx->ax_skb = netdev_alloc_skb_ip_align(dev->net,
-+                                                             rx->size);
-+                      if (!rx->ax_skb)
-+                              return 0;
-+              }
-+
-+              if (rx->size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
-+                      netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
-+                                 rx->size);
-+                      kfree_skb(rx->ax_skb);
-+                      rx->ax_skb = NULL;
-+                      rx->size = 0U;
-+
-+                      return 0;
-+              }
-+
-+              if (rx->size > skb->len - offset) {
-+                      remaining = rx->size - (skb->len - offset);
-+                      rx->size = skb->len - offset;
-+              }
-+
-+              data = skb_put(rx->ax_skb, rx->size);
-+              memcpy(data, skb->data + offset, rx->size);
-+              if (!remaining)
-+                      usbnet_skb_return(dev, rx->ax_skb);
-+
-+              offset += (rx->size + 1) & 0xfffe;
-+              rx->size = remaining;
-+      }
-+
-+      if (skb->len != offset) {
-+              netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d, %d\n",
-+                         skb->len, offset);
-+              return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+int asix_rx_fixup_common(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      struct asix_common_private *dp = dev->driver_priv;
-+      struct asix_rx_fixup_info *rx = &dp->rx_fixup_info;
-+
-+      return asix_rx_fixup_internal(dev, skb, rx);
-+}
-+
-+struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
-+                            gfp_t flags)
-+{
-+      int padlen;
-+      int headroom = skb_headroom(skb);
-+      int tailroom = skb_tailroom(skb);
-+      u32 packet_len;
-+      u32 padbytes = 0xffff0000;
-+
-+      padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4;
-+
-+      /* We need to push 4 bytes in front of frame (packet_len)
-+       * and maybe add 4 bytes after the end (if padlen is 4)
-+       *
-+       * Avoid skb_copy_expand() expensive call, using following rules :
-+       * - We are allowed to push 4 bytes in headroom if skb_header_cloned()
-+       *   is false (and if we have 4 bytes of headroom)
-+       * - We are allowed to put 4 bytes at tail if skb_cloned()
-+       *   is false (and if we have 4 bytes of tailroom)
-+       *
-+       * TCP packets for example are cloned, but skb_header_release()
-+       * was called in tcp stack, allowing us to use headroom for our needs.
-+       */
-+      if (!skb_header_cloned(skb) &&
-+          !(padlen && skb_cloned(skb)) &&
-+          headroom + tailroom >= 4 + padlen) {
-+              /* following should not happen, but better be safe */
-+              if (headroom < 4 ||
-+                  tailroom < padlen) {
-+                      skb->data = memmove(skb->head + 4, skb->data, skb->len);
-+                      skb_set_tail_pointer(skb, skb->len);
-+              }
-+      } else {
-+              struct sk_buff *skb2;
-+
-+              skb2 = skb_copy_expand(skb, 4, padlen, flags);
-+              dev_kfree_skb_any(skb);
-+              skb = skb2;
-+              if (!skb)
-+                      return NULL;
-+      }
-+
-+      packet_len = ((skb->len ^ 0x0000ffff) << 16) + skb->len;
-+      skb_push(skb, 4);
-+      cpu_to_le32s(&packet_len);
-+      skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
-+
-+      if (padlen) {
-+              cpu_to_le32s(&padbytes);
-+              memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
-+              skb_put(skb, sizeof(padbytes));
-+      }
-+
-+      usbnet_set_skb_tx_stats(skb, 1, 0);
-+      return skb;
-+}
-+
-+int asix_set_sw_mii(struct usbnet *dev)
-+{
-+      int ret;
-+      ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
-+      if (ret < 0)
-+              netdev_err(dev->net, "Failed to enable software MII access\n");
-+      return ret;
-+}
-+
-+int asix_set_hw_mii(struct usbnet *dev)
-+{
-+      int ret;
-+      ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
-+      if (ret < 0)
-+              netdev_err(dev->net, "Failed to enable hardware MII access\n");
-+      return ret;
-+}
-+
-+int asix_read_phy_addr(struct usbnet *dev, int internal)
-+{
-+      int offset = (internal ? 1 : 0);
-+      u8 buf[2];
-+      int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
-+
-+      netdev_dbg(dev->net, "asix_get_phy_addr()\n");
-+
-+      if (ret < 0) {
-+              netdev_err(dev->net, "Error reading PHYID register: %02x\n", ret);
-+              goto out;
-+      }
-+      netdev_dbg(dev->net, "asix_get_phy_addr() returning 0x%04x\n",
-+                 *((__le16 *)buf));
-+      ret = buf[offset];
-+
-+out:
-+      return ret;
-+}
-+
-+int asix_get_phy_addr(struct usbnet *dev)
-+{
-+      /* return the address of the internal phy */
-+      return asix_read_phy_addr(dev, 1);
-+}
-+
-+
-+int asix_sw_reset(struct usbnet *dev, u8 flags)
-+{
-+      int ret;
-+
-+        ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
-+      if (ret < 0)
-+              netdev_err(dev->net, "Failed to send software reset: %02x\n", ret);
-+
-+      return ret;
-+}
-+
-+u16 asix_read_rx_ctl(struct usbnet *dev)
-+{
-+      __le16 v;
-+      int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v);
-+
-+      if (ret < 0) {
-+              netdev_err(dev->net, "Error reading RX_CTL register: %02x\n", ret);
-+              goto out;
-+      }
-+      ret = le16_to_cpu(v);
-+out:
-+      return ret;
-+}
-+
-+int asix_write_rx_ctl(struct usbnet *dev, u16 mode)
-+{
-+      int ret;
-+
-+      netdev_dbg(dev->net, "asix_write_rx_ctl() - mode = 0x%04x\n", mode);
-+      ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
-+      if (ret < 0)
-+              netdev_err(dev->net, "Failed to write RX_CTL mode to 0x%04x: %02x\n",
-+                         mode, ret);
-+
-+      return ret;
-+}
-+
-+u16 asix_read_medium_status(struct usbnet *dev)
-+{
-+      __le16 v;
-+      int ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v);
-+
-+      if (ret < 0) {
-+              netdev_err(dev->net, "Error reading Medium Status register: %02x\n",
-+                         ret);
-+              return ret;     /* TODO: callers not checking for error ret */
-+      }
-+
-+      return le16_to_cpu(v);
-+
-+}
-+
-+int asix_write_medium_mode(struct usbnet *dev, u16 mode)
-+{
-+      int ret;
-+
-+      netdev_dbg(dev->net, "asix_write_medium_mode() - mode = 0x%04x\n", mode);
-+      ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
-+      if (ret < 0)
-+              netdev_err(dev->net, "Failed to write Medium Mode mode to 0x%04x: %02x\n",
-+                         mode, ret);
-+
-+      return ret;
-+}
-+
-+int asix_write_gpio(struct usbnet *dev, u16 value, int sleep)
-+{
-+      int ret;
-+
-+      netdev_dbg(dev->net, "asix_write_gpio() - value = 0x%04x\n", value);
-+      ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL);
-+      if (ret < 0)
-+              netdev_err(dev->net, "Failed to write GPIO value 0x%04x: %02x\n",
-+                         value, ret);
-+
-+      if (sleep)
-+              msleep(sleep);
-+
-+      return ret;
-+}
-+
-+/*
-+ * AX88772 & AX88178 have a 16-bit RX_CTL value
-+ */
-+void asix_set_multicast(struct net_device *net)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct asix_data *data = (struct asix_data *)&dev->data;
-+      u16 rx_ctl = AX_DEFAULT_RX_CTL;
-+
-+      if (net->flags & IFF_PROMISC) {
-+              rx_ctl |= AX_RX_CTL_PRO;
-+      } else if (net->flags & IFF_ALLMULTI ||
-+                 netdev_mc_count(net) > AX_MAX_MCAST) {
-+              rx_ctl |= AX_RX_CTL_AMALL;
-+      } else if (netdev_mc_empty(net)) {
-+              /* just broadcast and directed */
-+      } else {
-+              /* We use the 20 byte dev->data
-+               * for our 8 byte filter buffer
-+               * to avoid allocating memory that
-+               * is tricky to free later */
-+              struct netdev_hw_addr *ha;
-+              u32 crc_bits;
-+
-+              memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
-+
-+              /* Build the multicast hash filter. */
-+              netdev_for_each_mc_addr(ha, net) {
-+                      crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
-+                      data->multi_filter[crc_bits >> 3] |=
-+                          1 << (crc_bits & 7);
-+              }
-+
-+              asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
-+                                 AX_MCAST_FILTER_SIZE, data->multi_filter);
-+
-+              rx_ctl |= AX_RX_CTL_AM;
-+      }
-+
-+      asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
-+}
-+
-+int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      __le16 res;
-+
-+      mutex_lock(&dev->phy_mutex);
-+      asix_set_sw_mii(dev);
-+      asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
-+                              (__u16)loc, 2, &res);
-+      asix_set_hw_mii(dev);
-+      mutex_unlock(&dev->phy_mutex);
-+
-+      netdev_dbg(dev->net, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
-+                 phy_id, loc, le16_to_cpu(res));
-+
-+      return le16_to_cpu(res);
-+}
-+
-+void asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      __le16 res = cpu_to_le16(val);
-+
-+      netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
-+                 phy_id, loc, val);
-+      mutex_lock(&dev->phy_mutex);
-+      asix_set_sw_mii(dev);
-+      asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res);
-+      asix_set_hw_mii(dev);
-+      mutex_unlock(&dev->phy_mutex);
-+}
-+
-+void asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      u8 opt;
-+
-+      if (asix_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
-+              wolinfo->supported = 0;
-+              wolinfo->wolopts = 0;
-+              return;
-+      }
-+      wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
-+      wolinfo->wolopts = 0;
-+      if (opt & AX_MONITOR_LINK)
-+              wolinfo->wolopts |= WAKE_PHY;
-+      if (opt & AX_MONITOR_MAGIC)
-+              wolinfo->wolopts |= WAKE_MAGIC;
-+}
-+
-+int asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      u8 opt = 0;
-+
-+      if (wolinfo->wolopts & WAKE_PHY)
-+              opt |= AX_MONITOR_LINK;
-+      if (wolinfo->wolopts & WAKE_MAGIC)
-+              opt |= AX_MONITOR_MAGIC;
-+
-+      if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
-+                            opt, 0, 0, NULL) < 0)
-+              return -EINVAL;
-+
-+      return 0;
-+}
-+
-+int asix_get_eeprom_len(struct net_device *net)
-+{
-+      return AX_EEPROM_LEN;
-+}
-+
-+int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
-+                  u8 *data)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      u16 *eeprom_buff;
-+      int first_word, last_word;
-+      int i;
-+
-+      if (eeprom->len == 0)
-+              return -EINVAL;
-+
-+      eeprom->magic = AX_EEPROM_MAGIC;
-+
-+      first_word = eeprom->offset >> 1;
-+      last_word = (eeprom->offset + eeprom->len - 1) >> 1;
-+
-+      eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
-+                            GFP_KERNEL);
-+      if (!eeprom_buff)
-+              return -ENOMEM;
-+
-+      /* ax8817x returns 2 bytes from eeprom on read */
-+      for (i = first_word; i <= last_word; i++) {
-+              if (asix_read_cmd(dev, AX_CMD_READ_EEPROM, i, 0, 2,
-+                                &(eeprom_buff[i - first_word])) < 0) {
-+                      kfree(eeprom_buff);
-+                      return -EIO;
-+              }
-+      }
-+
-+      memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
-+      kfree(eeprom_buff);
-+      return 0;
-+}
-+
-+int asix_set_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
-+                  u8 *data)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      u16 *eeprom_buff;
-+      int first_word, last_word;
-+      int i;
-+      int ret;
-+
-+      netdev_dbg(net, "write EEPROM len %d, offset %d, magic 0x%x\n",
-+                 eeprom->len, eeprom->offset, eeprom->magic);
-+
-+      if (eeprom->len == 0)
-+              return -EINVAL;
-+
-+      if (eeprom->magic != AX_EEPROM_MAGIC)
-+              return -EINVAL;
-+
-+      first_word = eeprom->offset >> 1;
-+      last_word = (eeprom->offset + eeprom->len - 1) >> 1;
-+
-+      eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
-+                            GFP_KERNEL);
-+      if (!eeprom_buff)
-+              return -ENOMEM;
-+
-+      /* align data to 16 bit boundaries, read the missing data from
-+         the EEPROM */
-+      if (eeprom->offset & 1) {
-+              ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, first_word, 0, 2,
-+                                  &(eeprom_buff[0]));
-+              if (ret < 0) {
-+                      netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", first_word);
-+                      goto free;
-+              }
-+      }
-+
-+      if ((eeprom->offset + eeprom->len) & 1) {
-+              ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, last_word, 0, 2,
-+                                  &(eeprom_buff[last_word - first_word]));
-+              if (ret < 0) {
-+                      netdev_err(net, "Failed to read EEPROM at offset 0x%02x.\n", last_word);
-+                      goto free;
-+              }
-+      }
-+
-+      memcpy((u8 *)eeprom_buff + (eeprom->offset & 1), data, eeprom->len);
-+
-+      /* write data to EEPROM */
-+      ret = asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0x0000, 0, 0, NULL);
-+      if (ret < 0) {
-+              netdev_err(net, "Failed to enable EEPROM write\n");
-+              goto free;
-+      }
-+      msleep(20);
-+
-+      for (i = first_word; i <= last_word; i++) {
-+              netdev_dbg(net, "write to EEPROM at offset 0x%02x, data 0x%04x\n",
-+                         i, eeprom_buff[i - first_word]);
-+              ret = asix_write_cmd(dev, AX_CMD_WRITE_EEPROM, i,
-+                                   eeprom_buff[i - first_word], 0, NULL);
-+              if (ret < 0) {
-+                      netdev_err(net, "Failed to write EEPROM at offset 0x%02x.\n",
-+                                 i);
-+                      goto free;
-+              }
-+              msleep(20);
-+      }
-+
-+      ret = asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0x0000, 0, 0, NULL);
-+      if (ret < 0) {
-+              netdev_err(net, "Failed to disable EEPROM write\n");
-+              goto free;
-+      }
-+
-+      ret = 0;
-+free:
-+      kfree(eeprom_buff);
-+      return ret;
-+}
-+
-+void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
-+{
-+      /* Inherit standard device info */
-+      usbnet_get_drvinfo(net, info);
-+      strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
-+      strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
-+      info->eedump_len = AX_EEPROM_LEN;
-+}
-+
-+int asix_set_mac_address(struct net_device *net, void *p)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct asix_data *data = (struct asix_data *)&dev->data;
-+      struct sockaddr *addr = p;
-+
-+      if (netif_running(net))
-+              return -EBUSY;
-+      if (!is_valid_ether_addr(addr->sa_data))
-+              return -EADDRNOTAVAIL;
-+
-+      memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
-+
-+      /* We use the 20 byte dev->data
-+       * for our 6 byte mac buffer
-+       * to avoid allocating memory that
-+       * is tricky to free later */
-+      memcpy(data->mac_addr, addr->sa_data, ETH_ALEN);
-+      asix_write_cmd_async(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
-+                                                      data->mac_addr);
-+
-+      return 0;
-+}
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/asix_devices.c backports-4.2.6-1/drivers/net/usb/asix_devices.c
---- backports-4.2.6-1.org/drivers/net/usb/asix_devices.c       1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/asix_devices.c   2016-06-28 14:35:17.965307221 +0200
-@@ -0,0 +1,1107 @@
-+/*
-+ * ASIX AX8817X based USB 2.0 Ethernet Devices
-+ * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com>
-+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
-+ * Copyright (C) 2006 James Painter <jamie.painter@iname.com>
-+ * Copyright (c) 2002-2003 TiVo 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 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include "asix.h"
-+
-+#define PHY_MODE_MARVELL      0x0000
-+#define MII_MARVELL_LED_CTRL  0x0018
-+#define MII_MARVELL_STATUS    0x001b
-+#define MII_MARVELL_CTRL      0x0014
-+
-+#define MARVELL_LED_MANUAL    0x0019
-+
-+#define MARVELL_STATUS_HWCFG  0x0004
-+
-+#define MARVELL_CTRL_TXDELAY  0x0002
-+#define MARVELL_CTRL_RXDELAY  0x0080
-+
-+#define       PHY_MODE_RTL8211CL      0x000C
-+
-+struct ax88172_int_data {
-+      __le16 res1;
-+      u8 link;
-+      __le16 res2;
-+      u8 status;
-+      __le16 res3;
-+} __packed;
-+
-+static void asix_status(struct usbnet *dev, struct urb *urb)
-+{
-+      struct ax88172_int_data *event;
-+      int link;
-+
-+      if (urb->actual_length < 8)
-+              return;
-+
-+      event = urb->transfer_buffer;
-+      link = event->link & 0x01;
-+      if (netif_carrier_ok(dev->net) != link) {
-+              usbnet_link_change(dev, link, 1);
-+              netdev_dbg(dev->net, "Link Status is: %d\n", link);
-+      }
-+}
-+
-+static void asix_set_netdev_dev_addr(struct usbnet *dev, u8 *addr)
-+{
-+      if (is_valid_ether_addr(addr)) {
-+              memcpy(dev->net->dev_addr, addr, ETH_ALEN);
-+      } else {
-+              netdev_info(dev->net, "invalid hw address, using random\n");
-+              eth_hw_addr_random(dev->net);
-+      }
-+}
-+
-+/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
-+static u32 asix_get_phyid(struct usbnet *dev)
-+{
-+      int phy_reg;
-+      u32 phy_id;
-+      int i;
-+
-+      /* 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;
-+
-+      phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2);
-+      if (phy_reg < 0)
-+              return 0;
-+
-+      phy_id |= (phy_reg & 0xffff);
-+
-+      return phy_id;
-+}
-+
-+static u32 asix_get_link(struct net_device *net)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+
-+      return mii_link_ok(&dev->mii);
-+}
-+
-+static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+
-+      return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
-+}
-+
-+/* We need to override some ethtool_ops so we require our
-+   own structure so we don't interfere with other usbnet
-+   devices that may be connected at the same time. */
-+static const struct ethtool_ops ax88172_ethtool_ops = {
-+      .get_drvinfo            = asix_get_drvinfo,
-+      .get_link               = asix_get_link,
-+      .get_msglevel           = usbnet_get_msglevel,
-+      .set_msglevel           = usbnet_set_msglevel,
-+      .get_wol                = asix_get_wol,
-+      .set_wol                = asix_set_wol,
-+      .get_eeprom_len         = asix_get_eeprom_len,
-+      .get_eeprom             = asix_get_eeprom,
-+      .set_eeprom             = asix_set_eeprom,
-+      .get_settings           = usbnet_get_settings,
-+      .set_settings           = usbnet_set_settings,
-+      .nway_reset             = usbnet_nway_reset,
-+};
-+
-+static void ax88172_set_multicast(struct net_device *net)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct asix_data *data = (struct asix_data *)&dev->data;
-+      u8 rx_ctl = 0x8c;
-+
-+      if (net->flags & IFF_PROMISC) {
-+              rx_ctl |= 0x01;
-+      } else if (net->flags & IFF_ALLMULTI ||
-+                 netdev_mc_count(net) > AX_MAX_MCAST) {
-+              rx_ctl |= 0x02;
-+      } else if (netdev_mc_empty(net)) {
-+              /* just broadcast and directed */
-+      } else {
-+              /* We use the 20 byte dev->data
-+               * for our 8 byte filter buffer
-+               * to avoid allocating memory that
-+               * is tricky to free later */
-+              struct netdev_hw_addr *ha;
-+              u32 crc_bits;
-+
-+              memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
-+
-+              /* Build the multicast hash filter. */
-+              netdev_for_each_mc_addr(ha, net) {
-+                      crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
-+                      data->multi_filter[crc_bits >> 3] |=
-+                          1 << (crc_bits & 7);
-+              }
-+
-+              asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
-+                                 AX_MCAST_FILTER_SIZE, data->multi_filter);
-+
-+              rx_ctl |= 0x10;
-+      }
-+
-+      asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
-+}
-+
-+static int ax88172_link_reset(struct usbnet *dev)
-+{
-+      u8 mode;
-+      struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
-+
-+      mii_check_media(&dev->mii, 1, 1);
-+      mii_ethtool_gset(&dev->mii, &ecmd);
-+      mode = AX88172_MEDIUM_DEFAULT;
-+
-+      if (ecmd.duplex != DUPLEX_FULL)
-+              mode |= ~AX88172_MEDIUM_FD;
-+
-+      netdev_dbg(dev->net, "ax88172_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n",
-+                 ethtool_cmd_speed(&ecmd), ecmd.duplex, mode);
-+
-+      asix_write_medium_mode(dev, mode);
-+
-+      return 0;
-+}
-+
-+static const struct net_device_ops ax88172_netdev_ops = {
-+      .ndo_open               = usbnet_open,
-+      .ndo_stop               = usbnet_stop,
-+      .ndo_start_xmit         = usbnet_start_xmit,
-+      .ndo_tx_timeout         = usbnet_tx_timeout,
-+      .ndo_change_mtu         = usbnet_change_mtu,
-+      .ndo_set_mac_address    = eth_mac_addr,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_do_ioctl           = asix_ioctl,
-+      .ndo_set_rx_mode        = ax88172_set_multicast,
-+};
-+
-+static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      int ret = 0;
-+      u8 buf[ETH_ALEN];
-+      int i;
-+      unsigned long gpio_bits = dev->driver_info->data;
-+
-+      usbnet_get_endpoints(dev,intf);
-+
-+      /* Toggle the GPIOs in a manufacturer/model specific way */
-+      for (i = 2; i >= 0; i--) {
-+              ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
-+                              (gpio_bits >> (i * 8)) & 0xff, 0, 0, NULL);
-+              if (ret < 0)
-+                      goto out;
-+              msleep(5);
-+      }
-+
-+      ret = asix_write_rx_ctl(dev, 0x80);
-+      if (ret < 0)
-+              goto out;
-+
-+      /* Get the MAC address */
-+      ret = asix_read_cmd(dev, AX88172_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf);
-+      if (ret < 0) {
-+              netdev_dbg(dev->net, "read AX_CMD_READ_NODE_ID failed: %d\n",
-+                         ret);
-+              goto out;
-+      }
-+
-+      asix_set_netdev_dev_addr(dev, buf);
-+
-+      /* Initialize MII structure */
-+      dev->mii.dev = dev->net;
-+      dev->mii.mdio_read = asix_mdio_read;
-+      dev->mii.mdio_write = asix_mdio_write;
-+      dev->mii.phy_id_mask = 0x3f;
-+      dev->mii.reg_num_mask = 0x1f;
-+      dev->mii.phy_id = asix_get_phy_addr(dev);
-+
-+      dev->net->netdev_ops = &ax88172_netdev_ops;
-+      dev->net->ethtool_ops = &ax88172_ethtool_ops;
-+      dev->net->needed_headroom = 4; /* cf asix_tx_fixup() */
-+      dev->net->needed_tailroom = 4; /* cf asix_tx_fixup() */
-+
-+      asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-+      asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
-+              ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
-+      mii_nway_restart(&dev->mii);
-+
-+      return 0;
-+
-+out:
-+      return ret;
-+}
-+
-+static const struct ethtool_ops ax88772_ethtool_ops = {
-+      .get_drvinfo            = asix_get_drvinfo,
-+      .get_link               = asix_get_link,
-+      .get_msglevel           = usbnet_get_msglevel,
-+      .set_msglevel           = usbnet_set_msglevel,
-+      .get_wol                = asix_get_wol,
-+      .set_wol                = asix_set_wol,
-+      .get_eeprom_len         = asix_get_eeprom_len,
-+      .get_eeprom             = asix_get_eeprom,
-+      .set_eeprom             = asix_set_eeprom,
-+      .get_settings           = usbnet_get_settings,
-+      .set_settings           = usbnet_set_settings,
-+      .nway_reset             = usbnet_nway_reset,
-+};
-+
-+static int ax88772_link_reset(struct usbnet *dev)
-+{
-+      u16 mode;
-+      struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
-+
-+      mii_check_media(&dev->mii, 1, 1);
-+      mii_ethtool_gset(&dev->mii, &ecmd);
-+      mode = AX88772_MEDIUM_DEFAULT;
-+
-+      if (ethtool_cmd_speed(&ecmd) != SPEED_100)
-+              mode &= ~AX_MEDIUM_PS;
-+
-+      if (ecmd.duplex != DUPLEX_FULL)
-+              mode &= ~AX_MEDIUM_FD;
-+
-+      netdev_dbg(dev->net, "ax88772_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n",
-+                 ethtool_cmd_speed(&ecmd), ecmd.duplex, mode);
-+
-+      asix_write_medium_mode(dev, mode);
-+
-+      return 0;
-+}
-+
-+static int ax88772_reset(struct usbnet *dev)
-+{
-+      struct asix_data *data = (struct asix_data *)&dev->data;
-+      int ret, embd_phy;
-+      u16 rx_ctl;
-+
-+      ret = asix_write_gpio(dev,
-+                      AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5);
-+      if (ret < 0)
-+              goto out;
-+
-+      embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
-+
-+      ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
-+      if (ret < 0) {
-+              netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
-+              goto out;
-+      }
-+
-+      ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL);
-+      if (ret < 0)
-+              goto out;
-+
-+      msleep(150);
-+
-+      ret = asix_sw_reset(dev, AX_SWRESET_CLEAR);
-+      if (ret < 0)
-+              goto out;
-+
-+      msleep(150);
-+
-+      if (embd_phy) {
-+              ret = asix_sw_reset(dev, AX_SWRESET_IPRL);
-+              if (ret < 0)
-+                      goto out;
-+      } else {
-+              ret = asix_sw_reset(dev, AX_SWRESET_PRTE);
-+              if (ret < 0)
-+                      goto out;
-+      }
-+
-+      msleep(150);
-+      rx_ctl = asix_read_rx_ctl(dev);
-+      netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl);
-+      ret = asix_write_rx_ctl(dev, 0x0000);
-+      if (ret < 0)
-+              goto out;
-+
-+      rx_ctl = asix_read_rx_ctl(dev);
-+      netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
-+
-+      ret = asix_sw_reset(dev, AX_SWRESET_PRL);
-+      if (ret < 0)
-+              goto out;
-+
-+      msleep(150);
-+
-+      ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL);
-+      if (ret < 0)
-+              goto out;
-+
-+      msleep(150);
-+
-+      asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-+      asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
-+                      ADVERTISE_ALL | ADVERTISE_CSMA);
-+      mii_nway_restart(&dev->mii);
-+
-+      ret = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT);
-+      if (ret < 0)
-+              goto out;
-+
-+      ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
-+                              AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
-+                              AX88772_IPG2_DEFAULT, 0, NULL);
-+      if (ret < 0) {
-+              netdev_dbg(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret);
-+              goto out;
-+      }
-+
-+      /* Rewrite MAC address */
-+      memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN);
-+      ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
-+                                                      data->mac_addr);
-+      if (ret < 0)
-+              goto out;
-+
-+      /* Set RX_CTL to default values with 2k buffer, and enable cactus */
-+      ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL);
-+      if (ret < 0)
-+              goto out;
-+
-+      rx_ctl = asix_read_rx_ctl(dev);
-+      netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n",
-+                 rx_ctl);
-+
-+      rx_ctl = asix_read_medium_status(dev);
-+      netdev_dbg(dev->net,
-+                 "Medium Status is 0x%04x after all initializations\n",
-+                 rx_ctl);
-+
-+      return 0;
-+
-+out:
-+      return ret;
-+
-+}
-+
-+static const struct net_device_ops ax88772_netdev_ops = {
-+      .ndo_open               = usbnet_open,
-+      .ndo_stop               = usbnet_stop,
-+      .ndo_start_xmit         = usbnet_start_xmit,
-+      .ndo_tx_timeout         = usbnet_tx_timeout,
-+      .ndo_change_mtu         = usbnet_change_mtu,
-+      .ndo_set_mac_address    = asix_set_mac_address,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_do_ioctl           = asix_ioctl,
-+      .ndo_set_rx_mode        = asix_set_multicast,
-+};
-+
-+static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      int ret, embd_phy, i;
-+      u8 buf[ETH_ALEN];
-+      u32 phyid;
-+
-+      usbnet_get_endpoints(dev,intf);
-+
-+      /* Get the MAC address */
-+      if (dev->driver_info->data & FLAG_EEPROM_MAC) {
-+              for (i = 0; i < (ETH_ALEN >> 1); i++) {
-+                      ret = asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x04 + i,
-+                                      0, 2, buf + i * 2);
-+                      if (ret < 0)
-+                              break;
-+              }
-+      } else {
-+              ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
-+                              0, 0, ETH_ALEN, buf);
-+      }
-+
-+      if (ret < 0) {
-+              netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
-+              return ret;
-+      }
-+
-+      asix_set_netdev_dev_addr(dev, buf);
-+
-+      /* Initialize MII structure */
-+      dev->mii.dev = dev->net;
-+      dev->mii.mdio_read = asix_mdio_read;
-+      dev->mii.mdio_write = asix_mdio_write;
-+      dev->mii.phy_id_mask = 0x1f;
-+      dev->mii.reg_num_mask = 0x1f;
-+      dev->mii.phy_id = asix_get_phy_addr(dev);
-+
-+      dev->net->netdev_ops = &ax88772_netdev_ops;
-+      dev->net->ethtool_ops = &ax88772_ethtool_ops;
-+      dev->net->needed_headroom = 4; /* cf asix_tx_fixup() */
-+      dev->net->needed_tailroom = 4; /* cf asix_tx_fixup() */
-+
-+      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) {
-+              netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ax88772_reset(dev);
-+
-+      /* Read PHYID register *AFTER* the PHY was reset properly */
-+      phyid = asix_get_phyid(dev);
-+      netdev_dbg(dev->net, "PHYID=0x%08x\n", 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
-+                 jumbo eth frames */
-+              dev->rx_urb_size = 2048;
-+      }
-+
-+      dev->driver_priv = kzalloc(sizeof(struct asix_common_private), GFP_KERNEL);
-+      if (!dev->driver_priv)
-+              return -ENOMEM;
-+
-+      return 0;
-+}
-+
-+static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      kfree(dev->driver_priv);
-+}
-+
-+static const struct ethtool_ops ax88178_ethtool_ops = {
-+      .get_drvinfo            = asix_get_drvinfo,
-+      .get_link               = asix_get_link,
-+      .get_msglevel           = usbnet_get_msglevel,
-+      .set_msglevel           = usbnet_set_msglevel,
-+      .get_wol                = asix_get_wol,
-+      .set_wol                = asix_set_wol,
-+      .get_eeprom_len         = asix_get_eeprom_len,
-+      .get_eeprom             = asix_get_eeprom,
-+      .set_eeprom             = asix_set_eeprom,
-+      .get_settings           = usbnet_get_settings,
-+      .set_settings           = usbnet_set_settings,
-+      .nway_reset             = usbnet_nway_reset,
-+};
-+
-+static int marvell_phy_init(struct usbnet *dev)
-+{
-+      struct asix_data *data = (struct asix_data *)&dev->data;
-+      u16 reg;
-+
-+      netdev_dbg(dev->net, "marvell_phy_init()\n");
-+
-+      reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_MARVELL_STATUS);
-+      netdev_dbg(dev->net, "MII_MARVELL_STATUS = 0x%04x\n", reg);
-+
-+      asix_mdio_write(dev->net, dev->mii.phy_id, MII_MARVELL_CTRL,
-+                      MARVELL_CTRL_RXDELAY | MARVELL_CTRL_TXDELAY);
-+
-+      if (data->ledmode) {
-+              reg = asix_mdio_read(dev->net, dev->mii.phy_id,
-+                      MII_MARVELL_LED_CTRL);
-+              netdev_dbg(dev->net, "MII_MARVELL_LED_CTRL (1) = 0x%04x\n", reg);
-+
-+              reg &= 0xf8ff;
-+              reg |= (1 + 0x0100);
-+              asix_mdio_write(dev->net, dev->mii.phy_id,
-+                      MII_MARVELL_LED_CTRL, reg);
-+
-+              reg = asix_mdio_read(dev->net, dev->mii.phy_id,
-+                      MII_MARVELL_LED_CTRL);
-+              netdev_dbg(dev->net, "MII_MARVELL_LED_CTRL (2) = 0x%04x\n", reg);
-+              reg &= 0xfc0f;
-+      }
-+
-+      return 0;
-+}
-+
-+static int rtl8211cl_phy_init(struct usbnet *dev)
-+{
-+      struct asix_data *data = (struct asix_data *)&dev->data;
-+
-+      netdev_dbg(dev->net, "rtl8211cl_phy_init()\n");
-+
-+      asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0x0005);
-+      asix_mdio_write (dev->net, dev->mii.phy_id, 0x0c, 0);
-+      asix_mdio_write (dev->net, dev->mii.phy_id, 0x01,
-+              asix_mdio_read (dev->net, dev->mii.phy_id, 0x01) | 0x0080);
-+      asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0);
-+
-+      if (data->ledmode == 12) {
-+              asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0x0002);
-+              asix_mdio_write (dev->net, dev->mii.phy_id, 0x1a, 0x00cb);
-+              asix_mdio_write (dev->net, dev->mii.phy_id, 0x1f, 0);
-+      }
-+
-+      return 0;
-+}
-+
-+static int marvell_led_status(struct usbnet *dev, u16 speed)
-+{
-+      u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL);
-+
-+      netdev_dbg(dev->net, "marvell_led_status() read 0x%04x\n", reg);
-+
-+      /* Clear out the center LED bits - 0x03F0 */
-+      reg &= 0xfc0f;
-+
-+      switch (speed) {
-+              case SPEED_1000:
-+                      reg |= 0x03e0;
-+                      break;
-+              case SPEED_100:
-+                      reg |= 0x03b0;
-+                      break;
-+              default:
-+                      reg |= 0x02f0;
-+      }
-+
-+      netdev_dbg(dev->net, "marvell_led_status() writing 0x%04x\n", reg);
-+      asix_mdio_write(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL, reg);
-+
-+      return 0;
-+}
-+
-+static int ax88178_reset(struct usbnet *dev)
-+{
-+      struct asix_data *data = (struct asix_data *)&dev->data;
-+      int ret;
-+      __le16 eeprom;
-+      u8 status;
-+      int gpio0 = 0;
-+      u32 phyid;
-+
-+      asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status);
-+      netdev_dbg(dev->net, "GPIO Status: 0x%04x\n", status);
-+
-+      asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL);
-+      asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom);
-+      asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL);
-+
-+      netdev_dbg(dev->net, "EEPROM index 0x17 is 0x%04x\n", eeprom);
-+
-+      if (eeprom == cpu_to_le16(0xffff)) {
-+              data->phymode = PHY_MODE_MARVELL;
-+              data->ledmode = 0;
-+              gpio0 = 1;
-+      } else {
-+              data->phymode = le16_to_cpu(eeprom) & 0x7F;
-+              data->ledmode = le16_to_cpu(eeprom) >> 8;
-+              gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1;
-+      }
-+      netdev_dbg(dev->net, "GPIO0: %d, PhyMode: %d\n", 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, 0x001c, 300);
-+              asix_write_gpio(dev, 0x003c, 30);
-+      } else {
-+              netdev_dbg(dev->net, "gpio phymode == 1 path\n");
-+              asix_write_gpio(dev, AX_GPIO_GPO1EN, 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);
-+      netdev_dbg(dev->net, "PHYID=0x%08x\n", 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);
-+
-+      asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD);
-+      msleep(150);
-+
-+      asix_write_rx_ctl(dev, 0);
-+
-+      if (data->phymode == PHY_MODE_MARVELL) {
-+              marvell_phy_init(dev);
-+              msleep(60);
-+      } else if (data->phymode == PHY_MODE_RTL8211CL)
-+              rtl8211cl_phy_init(dev);
-+
-+      asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
-+                      BMCR_RESET | BMCR_ANENABLE);
-+      asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
-+                      ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
-+      asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000,
-+                      ADVERTISE_1000FULL);
-+
-+      mii_nway_restart(&dev->mii);
-+
-+      ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* Rewrite MAC address */
-+      memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN);
-+      ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
-+                                                      data->mac_addr);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL);
-+      if (ret < 0)
-+              return ret;
-+
-+      return 0;
-+}
-+
-+static int ax88178_link_reset(struct usbnet *dev)
-+{
-+      u16 mode;
-+      struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
-+      struct asix_data *data = (struct asix_data *)&dev->data;
-+      u32 speed;
-+
-+      netdev_dbg(dev->net, "ax88178_link_reset()\n");
-+
-+      mii_check_media(&dev->mii, 1, 1);
-+      mii_ethtool_gset(&dev->mii, &ecmd);
-+      mode = AX88178_MEDIUM_DEFAULT;
-+      speed = ethtool_cmd_speed(&ecmd);
-+
-+      if (speed == SPEED_1000)
-+              mode |= AX_MEDIUM_GM;
-+      else if (speed == SPEED_100)
-+              mode |= AX_MEDIUM_PS;
-+      else
-+              mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM);
-+
-+      mode |= AX_MEDIUM_ENCK;
-+
-+      if (ecmd.duplex == DUPLEX_FULL)
-+              mode |= AX_MEDIUM_FD;
-+      else
-+              mode &= ~AX_MEDIUM_FD;
-+
-+      netdev_dbg(dev->net, "ax88178_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n",
-+                 speed, ecmd.duplex, mode);
-+
-+      asix_write_medium_mode(dev, mode);
-+
-+      if (data->phymode == PHY_MODE_MARVELL && data->ledmode)
-+              marvell_led_status(dev, speed);
-+
-+      return 0;
-+}
-+
-+static void ax88178_set_mfb(struct usbnet *dev)
-+{
-+      u16 mfb = AX_RX_CTL_MFB_16384;
-+      u16 rxctl;
-+      u16 medium;
-+      int old_rx_urb_size = dev->rx_urb_size;
-+
-+      if (dev->hard_mtu < 2048) {
-+              dev->rx_urb_size = 2048;
-+              mfb = AX_RX_CTL_MFB_2048;
-+      } else if (dev->hard_mtu < 4096) {
-+              dev->rx_urb_size = 4096;
-+              mfb = AX_RX_CTL_MFB_4096;
-+      } else if (dev->hard_mtu < 8192) {
-+              dev->rx_urb_size = 8192;
-+              mfb = AX_RX_CTL_MFB_8192;
-+      } else if (dev->hard_mtu < 16384) {
-+              dev->rx_urb_size = 16384;
-+              mfb = AX_RX_CTL_MFB_16384;
-+      }
-+
-+      rxctl = asix_read_rx_ctl(dev);
-+      asix_write_rx_ctl(dev, (rxctl & ~AX_RX_CTL_MFB_16384) | mfb);
-+
-+      medium = asix_read_medium_status(dev);
-+      if (dev->net->mtu > 1500)
-+              medium |= AX_MEDIUM_JFE;
-+      else
-+              medium &= ~AX_MEDIUM_JFE;
-+      asix_write_medium_mode(dev, medium);
-+
-+      if (dev->rx_urb_size > old_rx_urb_size)
-+              usbnet_unlink_rx_urbs(dev);
-+}
-+
-+static int ax88178_change_mtu(struct net_device *net, int new_mtu)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      int ll_mtu = new_mtu + net->hard_header_len + 4;
-+
-+      netdev_dbg(dev->net, "ax88178_change_mtu() new_mtu=%d\n", new_mtu);
-+
-+      if (new_mtu <= 0 || ll_mtu > 16384)
-+              return -EINVAL;
-+
-+      if ((ll_mtu % dev->maxpacket) == 0)
-+              return -EDOM;
-+
-+      net->mtu = new_mtu;
-+      dev->hard_mtu = net->mtu + net->hard_header_len;
-+      ax88178_set_mfb(dev);
-+
-+      /* max qlen depend on hard_mtu and rx_urb_size */
-+      usbnet_update_max_qlen(dev);
-+
-+      return 0;
-+}
-+
-+static const struct net_device_ops ax88178_netdev_ops = {
-+      .ndo_open               = usbnet_open,
-+      .ndo_stop               = usbnet_stop,
-+      .ndo_start_xmit         = usbnet_start_xmit,
-+      .ndo_tx_timeout         = usbnet_tx_timeout,
-+      .ndo_set_mac_address    = asix_set_mac_address,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_set_rx_mode        = asix_set_multicast,
-+      .ndo_do_ioctl           = asix_ioctl,
-+      .ndo_change_mtu         = ax88178_change_mtu,
-+};
-+
-+static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      int ret;
-+      u8 buf[ETH_ALEN];
-+
-+      usbnet_get_endpoints(dev,intf);
-+
-+      /* Get the MAC address */
-+      ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf);
-+      if (ret < 0) {
-+              netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
-+              return ret;
-+      }
-+
-+      asix_set_netdev_dev_addr(dev, buf);
-+
-+      /* Initialize MII structure */
-+      dev->mii.dev = dev->net;
-+      dev->mii.mdio_read = asix_mdio_read;
-+      dev->mii.mdio_write = asix_mdio_write;
-+      dev->mii.phy_id_mask = 0x1f;
-+      dev->mii.reg_num_mask = 0xff;
-+      dev->mii.supports_gmii = 1;
-+      dev->mii.phy_id = asix_get_phy_addr(dev);
-+
-+      dev->net->netdev_ops = &ax88178_netdev_ops;
-+      dev->net->ethtool_ops = &ax88178_ethtool_ops;
-+
-+      /* Blink LEDS so users know driver saw dongle */
-+      asix_sw_reset(dev, 0);
-+      msleep(150);
-+
-+      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) {
-+              /* hard_mtu  is still the default - the device does not support
-+                 jumbo eth frames */
-+              dev->rx_urb_size = 2048;
-+      }
-+
-+      dev->driver_priv = kzalloc(sizeof(struct asix_common_private), GFP_KERNEL);
-+      if (!dev->driver_priv)
-+                      return -ENOMEM;
-+
-+      return 0;
-+}
-+
-+static const struct driver_info ax8817x_info = {
-+      .description = "ASIX AX8817x USB 2.0 Ethernet",
-+      .bind = ax88172_bind,
-+      .status = asix_status,
-+      .link_reset = ax88172_link_reset,
-+      .reset = ax88172_link_reset,
-+      .flags =  FLAG_ETHER | FLAG_LINK_INTR,
-+      .data = 0x00130103,
-+};
-+
-+static const struct driver_info dlink_dub_e100_info = {
-+      .description = "DLink DUB-E100 USB Ethernet",
-+      .bind = ax88172_bind,
-+      .status = asix_status,
-+      .link_reset = ax88172_link_reset,
-+      .reset = ax88172_link_reset,
-+      .flags =  FLAG_ETHER | FLAG_LINK_INTR,
-+      .data = 0x009f9d9f,
-+};
-+
-+static const struct driver_info netgear_fa120_info = {
-+      .description = "Netgear FA-120 USB Ethernet",
-+      .bind = ax88172_bind,
-+      .status = asix_status,
-+      .link_reset = ax88172_link_reset,
-+      .reset = ax88172_link_reset,
-+      .flags =  FLAG_ETHER | FLAG_LINK_INTR,
-+      .data = 0x00130103,
-+};
-+
-+static const struct driver_info hawking_uf200_info = {
-+      .description = "Hawking UF200 USB Ethernet",
-+      .bind = ax88172_bind,
-+      .status = asix_status,
-+      .link_reset = ax88172_link_reset,
-+      .reset = ax88172_link_reset,
-+      .flags =  FLAG_ETHER | FLAG_LINK_INTR,
-+      .data = 0x001f1d1f,
-+};
-+
-+static const struct driver_info ax88772_info = {
-+      .description = "ASIX AX88772 USB 2.0 Ethernet",
-+      .bind = ax88772_bind,
-+      .unbind = ax88772_unbind,
-+      .status = asix_status,
-+      .link_reset = ax88772_link_reset,
-+      .reset = ax88772_link_reset,
-+      .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET,
-+      .rx_fixup = asix_rx_fixup_common,
-+      .tx_fixup = asix_tx_fixup,
-+};
-+
-+static const struct driver_info ax88772b_info = {
-+      .description = "ASIX AX88772B USB 2.0 Ethernet",
-+      .bind = ax88772_bind,
-+      .unbind = ax88772_unbind,
-+      .status = asix_status,
-+      .link_reset = ax88772_link_reset,
-+      .reset = ax88772_reset,
-+      .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
-+               FLAG_MULTI_PACKET,
-+      .rx_fixup = asix_rx_fixup_common,
-+      .tx_fixup = asix_tx_fixup,
-+      .data = FLAG_EEPROM_MAC,
-+};
-+
-+static const struct driver_info ax88178_info = {
-+      .description = "ASIX AX88178 USB 2.0 Ethernet",
-+      .bind = ax88178_bind,
-+      .unbind = ax88772_unbind,
-+      .status = asix_status,
-+      .link_reset = ax88178_link_reset,
-+      .reset = ax88178_reset,
-+      .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
-+               FLAG_MULTI_PACKET,
-+      .rx_fixup = asix_rx_fixup_common,
-+      .tx_fixup = asix_tx_fixup,
-+};
-+
-+/*
-+ * USBLINK 20F9 "USB 2.0 LAN" USB ethernet adapter, typically found in
-+ * no-name packaging.
-+ * USB device strings are:
-+ *   1: Manufacturer: USBLINK
-+ *   2: Product: HG20F9 USB2.0
-+ *   3: Serial: 000003
-+ * Appears to be compatible with Asix 88772B.
-+ */
-+static const struct driver_info hg20f9_info = {
-+      .description = "HG20F9 USB 2.0 Ethernet",
-+      .bind = ax88772_bind,
-+      .unbind = ax88772_unbind,
-+      .status = asix_status,
-+      .link_reset = ax88772_link_reset,
-+      .reset = ax88772_reset,
-+      .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
-+               FLAG_MULTI_PACKET,
-+      .rx_fixup = asix_rx_fixup_common,
-+      .tx_fixup = asix_tx_fixup,
-+      .data = FLAG_EEPROM_MAC,
-+};
-+
-+static const struct usb_device_id     products [] = {
-+{
-+      // Linksys USB200M
-+      USB_DEVICE (0x077b, 0x2226),
-+      .driver_info =  (unsigned long) &ax8817x_info,
-+}, {
-+      // Netgear FA120
-+      USB_DEVICE (0x0846, 0x1040),
-+      .driver_info =  (unsigned long) &netgear_fa120_info,
-+}, {
-+      // DLink DUB-E100
-+      USB_DEVICE (0x2001, 0x1a00),
-+      .driver_info =  (unsigned long) &dlink_dub_e100_info,
-+}, {
-+      // Intellinet, ST Lab USB Ethernet
-+      USB_DEVICE (0x0b95, 0x1720),
-+      .driver_info =  (unsigned long) &ax8817x_info,
-+}, {
-+      // Hawking UF200, TrendNet TU2-ET100
-+      USB_DEVICE (0x07b8, 0x420a),
-+      .driver_info =  (unsigned long) &hawking_uf200_info,
-+}, {
-+      // Billionton Systems, USB2AR
-+      USB_DEVICE (0x08dd, 0x90ff),
-+      .driver_info =  (unsigned long) &ax8817x_info,
-+}, {
-+      // ATEN UC210T
-+      USB_DEVICE (0x0557, 0x2009),
-+      .driver_info =  (unsigned long) &ax8817x_info,
-+}, {
-+      // Buffalo LUA-U2-KTX
-+      USB_DEVICE (0x0411, 0x003d),
-+      .driver_info =  (unsigned long) &ax8817x_info,
-+}, {
-+      // Buffalo LUA-U2-GT 10/100/1000
-+      USB_DEVICE (0x0411, 0x006e),
-+      .driver_info =  (unsigned long) &ax88178_info,
-+}, {
-+      // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter"
-+      USB_DEVICE (0x6189, 0x182d),
-+      .driver_info =  (unsigned long) &ax8817x_info,
-+}, {
-+      // Sitecom LN-031 "USB 2.0 10/100/1000 Ethernet adapter"
-+      USB_DEVICE (0x0df6, 0x0056),
-+      .driver_info =  (unsigned long) &ax88178_info,
-+}, {
-+      // Sitecom LN-028 "USB 2.0 10/100/1000 Ethernet adapter"
-+      USB_DEVICE (0x0df6, 0x061c),
-+      .driver_info =  (unsigned long) &ax88178_info,
-+}, {
-+      // corega FEther USB2-TX
-+      USB_DEVICE (0x07aa, 0x0017),
-+      .driver_info =  (unsigned long) &ax8817x_info,
-+}, {
-+      // Surecom EP-1427X-2
-+      USB_DEVICE (0x1189, 0x0893),
-+      .driver_info = (unsigned long) &ax8817x_info,
-+}, {
-+      // goodway corp usb gwusb2e
-+      USB_DEVICE (0x1631, 0x6200),
-+      .driver_info = (unsigned long) &ax8817x_info,
-+}, {
-+      // JVC MP-PRX1 Port Replicator
-+      USB_DEVICE (0x04f1, 0x3008),
-+      .driver_info = (unsigned long) &ax8817x_info,
-+}, {
-+      // Lenovo U2L100P 10/100
-+      USB_DEVICE (0x17ef, 0x7203),
-+      .driver_info = (unsigned long) &ax88772_info,
-+}, {
-+      // ASIX AX88772B 10/100
-+      USB_DEVICE (0x0b95, 0x772b),
-+      .driver_info = (unsigned long) &ax88772b_info,
-+}, {
-+      // ASIX AX88772 10/100
-+      USB_DEVICE (0x0b95, 0x7720),
-+      .driver_info = (unsigned long) &ax88772_info,
-+}, {
-+      // ASIX AX88178 10/100/1000
-+      USB_DEVICE (0x0b95, 0x1780),
-+      .driver_info = (unsigned long) &ax88178_info,
-+}, {
-+      // Logitec LAN-GTJ/U2A
-+      USB_DEVICE (0x0789, 0x0160),
-+      .driver_info = (unsigned long) &ax88178_info,
-+}, {
-+      // Linksys USB200M Rev 2
-+      USB_DEVICE (0x13b1, 0x0018),
-+      .driver_info = (unsigned long) &ax88772_info,
-+}, {
-+      // 0Q0 cable ethernet
-+      USB_DEVICE (0x1557, 0x7720),
-+      .driver_info = (unsigned long) &ax88772_info,
-+}, {
-+      // DLink DUB-E100 H/W Ver B1
-+      USB_DEVICE (0x07d1, 0x3c05),
-+      .driver_info = (unsigned long) &ax88772_info,
-+}, {
-+      // DLink DUB-E100 H/W Ver B1 Alternate
-+      USB_DEVICE (0x2001, 0x3c05),
-+      .driver_info = (unsigned long) &ax88772_info,
-+}, {
-+       // DLink DUB-E100 H/W Ver C1
-+       USB_DEVICE (0x2001, 0x1a02),
-+       .driver_info = (unsigned long) &ax88772_info,
-+}, {
-+      // Linksys USB1000
-+      USB_DEVICE (0x1737, 0x0039),
-+      .driver_info = (unsigned long) &ax88178_info,
-+}, {
-+      // IO-DATA ETG-US2
-+      USB_DEVICE (0x04bb, 0x0930),
-+      .driver_info = (unsigned long) &ax88178_info,
-+}, {
-+      // Belkin F5D5055
-+      USB_DEVICE(0x050d, 0x5055),
-+      .driver_info = (unsigned long) &ax88178_info,
-+}, {
-+      // Apple USB Ethernet Adapter
-+      USB_DEVICE(0x05ac, 0x1402),
-+      .driver_info = (unsigned long) &ax88772_info,
-+}, {
-+      // Cables-to-Go USB Ethernet Adapter
-+      USB_DEVICE(0x0b95, 0x772a),
-+      .driver_info = (unsigned long) &ax88772_info,
-+}, {
-+      // ABOCOM for pci
-+      USB_DEVICE(0x14ea, 0xab11),
-+      .driver_info = (unsigned long) &ax88178_info,
-+}, {
-+      // ASIX 88772a
-+      USB_DEVICE(0x0db0, 0xa877),
-+      .driver_info = (unsigned long) &ax88772_info,
-+}, {
-+      // Asus USB Ethernet Adapter
-+      USB_DEVICE (0x0b95, 0x7e2b),
-+      .driver_info = (unsigned long) &ax88772_info,
-+}, {
-+      /* ASIX 88172a demo board */
-+      USB_DEVICE(0x0b95, 0x172a),
-+      .driver_info = (unsigned long) &ax88172a_info,
-+}, {
-+      /*
-+       * USBLINK HG20F9 "USB 2.0 LAN"
-+       * Appears to have gazumped Linksys's manufacturer ID but
-+       * doesn't (yet) conflict with any known Linksys product.
-+       */
-+      USB_DEVICE(0x066b, 0x20f9),
-+      .driver_info = (unsigned long) &hg20f9_info,
-+},
-+      { },            // END
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver asix_driver = {
-+      .name =         DRIVER_NAME,
-+      .id_table =     products,
-+      .probe =        usbnet_probe,
-+      .suspend =      usbnet_suspend,
-+      .resume =       usbnet_resume,
-+      .disconnect =   usbnet_disconnect,
-+      .supports_autosuspend = 1,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(asix_driver);
-+
-+MODULE_AUTHOR("David Hollis");
-+MODULE_VERSION(DRIVER_VERSION);
-+MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices");
-+MODULE_LICENSE("GPL");
-+
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/asix.h backports-4.2.6-1/drivers/net/usb/asix.h
---- backports-4.2.6-1.org/drivers/net/usb/asix.h       1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/asix.h   2016-06-28 14:35:17.965307221 +0200
-@@ -0,0 +1,234 @@
-+/*
-+ * ASIX AX8817X based USB 2.0 Ethernet Devices
-+ * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com>
-+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
-+ * Copyright (C) 2006 James Painter <jamie.painter@iname.com>
-+ * Copyright (c) 2002-2003 TiVo 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 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#ifndef _ASIX_H
-+#define _ASIX_H
-+
-+// #define    DEBUG                   // error path messages, extra info
-+// #define    VERBOSE                 // more; success messages
-+
-+#include <linux/module.h>
-+#include <linux/kmod.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/workqueue.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/crc32.h>
-+#include <linux/usb/usbnet.h>
-+#include <linux/slab.h>
-+#include <linux/if_vlan.h>
-+
-+#define DRIVER_VERSION "22-Dec-2011"
-+#define DRIVER_NAME "asix"
-+
-+/* ASIX AX8817X based USB 2.0 Ethernet Devices */
-+
-+#define AX_CMD_SET_SW_MII             0x06
-+#define AX_CMD_READ_MII_REG           0x07
-+#define AX_CMD_WRITE_MII_REG          0x08
-+#define AX_CMD_SET_HW_MII             0x0a
-+#define AX_CMD_READ_EEPROM            0x0b
-+#define AX_CMD_WRITE_EEPROM           0x0c
-+#define AX_CMD_WRITE_ENABLE           0x0d
-+#define AX_CMD_WRITE_DISABLE          0x0e
-+#define AX_CMD_READ_RX_CTL            0x0f
-+#define AX_CMD_WRITE_RX_CTL           0x10
-+#define AX_CMD_READ_IPG012            0x11
-+#define AX_CMD_WRITE_IPG0             0x12
-+#define AX_CMD_WRITE_IPG1             0x13
-+#define AX_CMD_READ_NODE_ID           0x13
-+#define AX_CMD_WRITE_NODE_ID          0x14
-+#define AX_CMD_WRITE_IPG2             0x14
-+#define AX_CMD_WRITE_MULTI_FILTER     0x16
-+#define AX88172_CMD_READ_NODE_ID      0x17
-+#define AX_CMD_READ_PHY_ID            0x19
-+#define AX_CMD_READ_MEDIUM_STATUS     0x1a
-+#define AX_CMD_WRITE_MEDIUM_MODE      0x1b
-+#define AX_CMD_READ_MONITOR_MODE      0x1c
-+#define AX_CMD_WRITE_MONITOR_MODE     0x1d
-+#define AX_CMD_READ_GPIOS             0x1e
-+#define AX_CMD_WRITE_GPIOS            0x1f
-+#define AX_CMD_SW_RESET                       0x20
-+#define AX_CMD_SW_PHY_STATUS          0x21
-+#define AX_CMD_SW_PHY_SELECT          0x22
-+
-+#define AX_PHY_SELECT_MASK            (BIT(3) | BIT(2))
-+#define AX_PHY_SELECT_INTERNAL                0
-+#define AX_PHY_SELECT_EXTERNAL                BIT(2)
-+
-+#define AX_MONITOR_MODE                       0x01
-+#define AX_MONITOR_LINK                       0x02
-+#define AX_MONITOR_MAGIC              0x04
-+#define AX_MONITOR_HSFS                       0x10
-+
-+/* AX88172 Medium Status Register values */
-+#define AX88172_MEDIUM_FD             0x02
-+#define AX88172_MEDIUM_TX             0x04
-+#define AX88172_MEDIUM_FC             0x10
-+#define AX88172_MEDIUM_DEFAULT \
-+              ( AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC )
-+
-+#define AX_MCAST_FILTER_SIZE          8
-+#define AX_MAX_MCAST                  64
-+
-+#define AX_SWRESET_CLEAR              0x00
-+#define AX_SWRESET_RR                 0x01
-+#define AX_SWRESET_RT                 0x02
-+#define AX_SWRESET_PRTE                       0x04
-+#define AX_SWRESET_PRL                        0x08
-+#define AX_SWRESET_BZ                 0x10
-+#define AX_SWRESET_IPRL                       0x20
-+#define AX_SWRESET_IPPD                       0x40
-+
-+#define AX88772_IPG0_DEFAULT          0x15
-+#define AX88772_IPG1_DEFAULT          0x0c
-+#define AX88772_IPG2_DEFAULT          0x12
-+
-+/* AX88772 & AX88178 Medium Mode Register */
-+#define AX_MEDIUM_PF          0x0080
-+#define AX_MEDIUM_JFE         0x0040
-+#define AX_MEDIUM_TFC         0x0020
-+#define AX_MEDIUM_RFC         0x0010
-+#define AX_MEDIUM_ENCK                0x0008
-+#define AX_MEDIUM_AC          0x0004
-+#define AX_MEDIUM_FD          0x0002
-+#define AX_MEDIUM_GM          0x0001
-+#define AX_MEDIUM_SM          0x1000
-+#define AX_MEDIUM_SBP         0x0800
-+#define AX_MEDIUM_PS          0x0200
-+#define AX_MEDIUM_RE          0x0100
-+
-+#define AX88178_MEDIUM_DEFAULT        \
-+      (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
-+       AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
-+       AX_MEDIUM_RE)
-+
-+#define AX88772_MEDIUM_DEFAULT        \
-+      (AX_MEDIUM_FD | AX_MEDIUM_RFC | \
-+       AX_MEDIUM_TFC | AX_MEDIUM_PS | \
-+       AX_MEDIUM_AC | AX_MEDIUM_RE)
-+
-+/* AX88772 & AX88178 RX_CTL values */
-+#define AX_RX_CTL_SO          0x0080
-+#define AX_RX_CTL_AP          0x0020
-+#define AX_RX_CTL_AM          0x0010
-+#define AX_RX_CTL_AB          0x0008
-+#define AX_RX_CTL_SEP         0x0004
-+#define AX_RX_CTL_AMALL               0x0002
-+#define AX_RX_CTL_PRO         0x0001
-+#define AX_RX_CTL_MFB_2048    0x0000
-+#define AX_RX_CTL_MFB_4096    0x0100
-+#define AX_RX_CTL_MFB_8192    0x0200
-+#define AX_RX_CTL_MFB_16384   0x0300
-+
-+#define AX_DEFAULT_RX_CTL     (AX_RX_CTL_SO | AX_RX_CTL_AB)
-+
-+/* GPIO 0 .. 2 toggles */
-+#define AX_GPIO_GPO0EN                0x01    /* GPIO0 Output enable */
-+#define AX_GPIO_GPO_0         0x02    /* GPIO0 Output value */
-+#define AX_GPIO_GPO1EN                0x04    /* GPIO1 Output enable */
-+#define AX_GPIO_GPO_1         0x08    /* GPIO1 Output value */
-+#define AX_GPIO_GPO2EN                0x10    /* GPIO2 Output enable */
-+#define AX_GPIO_GPO_2         0x20    /* GPIO2 Output value */
-+#define AX_GPIO_RESERVED      0x40    /* Reserved */
-+#define AX_GPIO_RSE           0x80    /* Reload serial EEPROM */
-+
-+#define AX_EEPROM_MAGIC               0xdeadbeef
-+#define AX_EEPROM_LEN         0x200
-+
-+/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
-+struct asix_data {
-+      u8 multi_filter[AX_MCAST_FILTER_SIZE];
-+      u8 mac_addr[ETH_ALEN];
-+      u8 phymode;
-+      u8 ledmode;
-+      u8 res;
-+};
-+
-+struct asix_rx_fixup_info {
-+      struct sk_buff *ax_skb;
-+      u32 header;
-+      u16 size;
-+      bool split_head;
-+};
-+
-+struct asix_common_private {
-+      struct asix_rx_fixup_info rx_fixup_info;
-+};
-+
-+extern const struct driver_info ax88172a_info;
-+
-+/* ASIX specific flags */
-+#define FLAG_EEPROM_MAC               (1UL << 0)  /* init device MAC from eeprom */
-+
-+int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-+                u16 size, void *data);
-+
-+int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-+                 u16 size, void *data);
-+
-+void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value,
-+                        u16 index, u16 size, void *data);
-+
-+int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb,
-+                         struct asix_rx_fixup_info *rx);
-+int asix_rx_fixup_common(struct usbnet *dev, struct sk_buff *skb);
-+
-+struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
-+                            gfp_t flags);
-+
-+int asix_set_sw_mii(struct usbnet *dev);
-+int asix_set_hw_mii(struct usbnet *dev);
-+
-+int asix_read_phy_addr(struct usbnet *dev, int internal);
-+int asix_get_phy_addr(struct usbnet *dev);
-+
-+int asix_sw_reset(struct usbnet *dev, u8 flags);
-+
-+u16 asix_read_rx_ctl(struct usbnet *dev);
-+int asix_write_rx_ctl(struct usbnet *dev, u16 mode);
-+
-+u16 asix_read_medium_status(struct usbnet *dev);
-+int asix_write_medium_mode(struct usbnet *dev, u16 mode);
-+
-+int asix_write_gpio(struct usbnet *dev, u16 value, int sleep);
-+
-+void asix_set_multicast(struct net_device *net);
-+
-+int asix_mdio_read(struct net_device *netdev, int phy_id, int loc);
-+void asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val);
-+
-+void asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo);
-+int asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo);
-+
-+int asix_get_eeprom_len(struct net_device *net);
-+int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
-+                  u8 *data);
-+int asix_set_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
-+                  u8 *data);
-+
-+void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info);
-+
-+int asix_set_mac_address(struct net_device *net, void *p);
-+
-+#endif /* _ASIX_H */
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/ax88172a.c backports-4.2.6-1/drivers/net/usb/ax88172a.c
---- backports-4.2.6-1.org/drivers/net/usb/ax88172a.c   1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/ax88172a.c       2016-06-28 14:35:17.965307221 +0200
-@@ -0,0 +1,422 @@
-+/*
-+ * ASIX AX88172A based USB 2.0 Ethernet Devices
-+ * Copyright (C) 2012 OMICRON electronics GmbH
-+ *
-+ * Supports external PHYs via phylib. Based on the driver for the
-+ * AX88772. Original copyrights follow:
-+ *
-+ * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com>
-+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
-+ * Copyright (C) 2006 James Painter <jamie.painter@iname.com>
-+ * Copyright (c) 2002-2003 TiVo 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 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include "asix.h"
-+#include <linux/phy.h>
-+
-+struct ax88172a_private {
-+      struct mii_bus *mdio;
-+      struct phy_device *phydev;
-+      char phy_name[20];
-+      u16 phy_addr;
-+      u16 oldmode;
-+      int use_embdphy;
-+      struct asix_rx_fixup_info rx_fixup_info;
-+};
-+
-+/* MDIO read and write wrappers for phylib */
-+static int asix_mdio_bus_read(struct mii_bus *bus, int phy_id, int regnum)
-+{
-+      return asix_mdio_read(((struct usbnet *)bus->priv)->net, phy_id,
-+                            regnum);
-+}
-+
-+static int asix_mdio_bus_write(struct mii_bus *bus, int phy_id, int regnum,
-+                             u16 val)
-+{
-+      asix_mdio_write(((struct usbnet *)bus->priv)->net, phy_id, regnum, val);
-+      return 0;
-+}
-+
-+static int ax88172a_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
-+{
-+      if (!netif_running(net))
-+              return -EINVAL;
-+
-+      if (!net->phydev)
-+              return -ENODEV;
-+
-+      return phy_mii_ioctl(net->phydev, rq, cmd);
-+}
-+
-+/* set MAC link settings according to information from phylib */
-+static void ax88172a_adjust_link(struct net_device *netdev)
-+{
-+      struct phy_device *phydev = netdev->phydev;
-+      struct usbnet *dev = netdev_priv(netdev);
-+      struct ax88172a_private *priv = dev->driver_priv;
-+      u16 mode = 0;
-+
-+      if (phydev->link) {
-+              mode = AX88772_MEDIUM_DEFAULT;
-+
-+              if (phydev->duplex == DUPLEX_HALF)
-+                      mode &= ~AX_MEDIUM_FD;
-+
-+              if (phydev->speed != SPEED_100)
-+                      mode &= ~AX_MEDIUM_PS;
-+      }
-+
-+      if (mode != priv->oldmode) {
-+              asix_write_medium_mode(dev, mode);
-+              priv->oldmode = mode;
-+              netdev_dbg(netdev, "speed %u duplex %d, setting mode to 0x%04x\n",
-+                         phydev->speed, phydev->duplex, mode);
-+              phy_print_status(phydev);
-+      }
-+}
-+
-+static void ax88172a_status(struct usbnet *dev, struct urb *urb)
-+{
-+      /* link changes are detected by polling the phy */
-+}
-+
-+/* use phylib infrastructure */
-+static int ax88172a_init_mdio(struct usbnet *dev)
-+{
-+      struct ax88172a_private *priv = dev->driver_priv;
-+      int ret, i;
-+
-+      priv->mdio = mdiobus_alloc();
-+      if (!priv->mdio) {
-+              netdev_err(dev->net, "Could not allocate MDIO bus\n");
-+              return -ENOMEM;
-+      }
-+
-+      priv->mdio->priv = (void *)dev;
-+      priv->mdio->read = &asix_mdio_bus_read;
-+      priv->mdio->write = &asix_mdio_bus_write;
-+      priv->mdio->name = "Asix MDIO Bus";
-+      /* mii bus name is usb-<usb bus number>-<usb device number> */
-+      snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
-+               dev->udev->bus->busnum, dev->udev->devnum);
-+
-+      priv->mdio->irq = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
-+      if (!priv->mdio->irq) {
-+              ret = -ENOMEM;
-+              goto mfree;
-+      }
-+      for (i = 0; i < PHY_MAX_ADDR; i++)
-+              priv->mdio->irq[i] = PHY_POLL;
-+
-+      ret = mdiobus_register(priv->mdio);
-+      if (ret) {
-+              netdev_err(dev->net, "Could not register MDIO bus\n");
-+              goto ifree;
-+      }
-+
-+      netdev_info(dev->net, "registered mdio bus %s\n", priv->mdio->id);
-+      return 0;
-+
-+ifree:
-+      kfree(priv->mdio->irq);
-+mfree:
-+      mdiobus_free(priv->mdio);
-+      return ret;
-+}
-+
-+static void ax88172a_remove_mdio(struct usbnet *dev)
-+{
-+      struct ax88172a_private *priv = dev->driver_priv;
-+
-+      netdev_info(dev->net, "deregistering mdio bus %s\n", priv->mdio->id);
-+      mdiobus_unregister(priv->mdio);
-+      kfree(priv->mdio->irq);
-+      mdiobus_free(priv->mdio);
-+}
-+
-+static const struct net_device_ops ax88172a_netdev_ops = {
-+      .ndo_open               = usbnet_open,
-+      .ndo_stop               = usbnet_stop,
-+      .ndo_start_xmit         = usbnet_start_xmit,
-+      .ndo_tx_timeout         = usbnet_tx_timeout,
-+      .ndo_change_mtu         = usbnet_change_mtu,
-+      .ndo_set_mac_address    = asix_set_mac_address,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_do_ioctl           = ax88172a_ioctl,
-+      .ndo_set_rx_mode        = asix_set_multicast,
-+};
-+
-+static int ax88172a_get_settings(struct net_device *net,
-+                               struct ethtool_cmd *cmd)
-+{
-+      if (!net->phydev)
-+              return -ENODEV;
-+
-+      return phy_ethtool_gset(net->phydev, cmd);
-+}
-+
-+static int ax88172a_set_settings(struct net_device *net,
-+                               struct ethtool_cmd *cmd)
-+{
-+      if (!net->phydev)
-+              return -ENODEV;
-+
-+      return phy_ethtool_sset(net->phydev, cmd);
-+}
-+
-+static int ax88172a_nway_reset(struct net_device *net)
-+{
-+      if (!net->phydev)
-+              return -ENODEV;
-+
-+      return phy_start_aneg(net->phydev);
-+}
-+
-+static const struct ethtool_ops ax88172a_ethtool_ops = {
-+      .get_drvinfo            = asix_get_drvinfo,
-+      .get_link               = usbnet_get_link,
-+      .get_msglevel           = usbnet_get_msglevel,
-+      .set_msglevel           = usbnet_set_msglevel,
-+      .get_wol                = asix_get_wol,
-+      .set_wol                = asix_set_wol,
-+      .get_eeprom_len         = asix_get_eeprom_len,
-+      .get_eeprom             = asix_get_eeprom,
-+      .set_eeprom             = asix_set_eeprom,
-+      .get_settings           = ax88172a_get_settings,
-+      .set_settings           = ax88172a_set_settings,
-+      .nway_reset             = ax88172a_nway_reset,
-+};
-+
-+static int ax88172a_reset_phy(struct usbnet *dev, int embd_phy)
-+{
-+      int ret;
-+
-+      ret = asix_sw_reset(dev, AX_SWRESET_IPPD);
-+      if (ret < 0)
-+              goto err;
-+
-+      msleep(150);
-+      ret = asix_sw_reset(dev, AX_SWRESET_CLEAR);
-+      if (ret < 0)
-+              goto err;
-+
-+      msleep(150);
-+
-+      ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_IPPD);
-+      if (ret < 0)
-+              goto err;
-+
-+      return 0;
-+
-+err:
-+      return ret;
-+}
-+
-+
-+static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      int ret;
-+      u8 buf[ETH_ALEN];
-+      struct ax88172a_private *priv;
-+
-+      usbnet_get_endpoints(dev, intf);
-+
-+      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      dev->driver_priv = priv;
-+
-+      /* Get the MAC address */
-+      ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf);
-+      if (ret < 0) {
-+              netdev_err(dev->net, "Failed to read MAC address: %d\n", ret);
-+              goto free;
-+      }
-+      memcpy(dev->net->dev_addr, buf, ETH_ALEN);
-+
-+      dev->net->netdev_ops = &ax88172a_netdev_ops;
-+      dev->net->ethtool_ops = &ax88172a_ethtool_ops;
-+
-+      /* are we using the internal or the external phy? */
-+      ret = asix_read_cmd(dev, AX_CMD_SW_PHY_STATUS, 0, 0, 1, buf);
-+      if (ret < 0) {
-+              netdev_err(dev->net, "Failed to read software interface selection register: %d\n",
-+                         ret);
-+              goto free;
-+      }
-+
-+      netdev_dbg(dev->net, "AX_CMD_SW_PHY_STATUS = 0x%02x\n", buf[0]);
-+      switch (buf[0] & AX_PHY_SELECT_MASK) {
-+      case AX_PHY_SELECT_INTERNAL:
-+              netdev_dbg(dev->net, "use internal phy\n");
-+              priv->use_embdphy = 1;
-+              break;
-+      case AX_PHY_SELECT_EXTERNAL:
-+              netdev_dbg(dev->net, "use external phy\n");
-+              priv->use_embdphy = 0;
-+              break;
-+      default:
-+              netdev_err(dev->net, "Interface mode not supported by driver\n");
-+              ret = -ENOTSUPP;
-+              goto free;
-+      }
-+
-+      priv->phy_addr = asix_read_phy_addr(dev, priv->use_embdphy);
-+      ax88172a_reset_phy(dev, priv->use_embdphy);
-+
-+      /* 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
-+                 jumbo eth frames */
-+              dev->rx_urb_size = 2048;
-+      }
-+
-+      /* init MDIO bus */
-+      ret = ax88172a_init_mdio(dev);
-+      if (ret)
-+              goto free;
-+
-+      return 0;
-+
-+free:
-+      kfree(priv);
-+      return ret;
-+}
-+
-+static int ax88172a_stop(struct usbnet *dev)
-+{
-+      struct ax88172a_private *priv = dev->driver_priv;
-+
-+      netdev_dbg(dev->net, "Stopping interface\n");
-+
-+      if (priv->phydev) {
-+              netdev_info(dev->net, "Disconnecting from phy %s\n",
-+                          priv->phy_name);
-+              phy_stop(priv->phydev);
-+              phy_disconnect(priv->phydev);
-+      }
-+
-+      return 0;
-+}
-+
-+static void ax88172a_unbind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      struct ax88172a_private *priv = dev->driver_priv;
-+
-+      ax88172a_remove_mdio(dev);
-+      kfree(priv);
-+}
-+
-+static int ax88172a_reset(struct usbnet *dev)
-+{
-+      struct asix_data *data = (struct asix_data *)&dev->data;
-+      struct ax88172a_private *priv = dev->driver_priv;
-+      int ret;
-+      u16 rx_ctl;
-+
-+      ax88172a_reset_phy(dev, priv->use_embdphy);
-+
-+      msleep(150);
-+      rx_ctl = asix_read_rx_ctl(dev);
-+      netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl);
-+      ret = asix_write_rx_ctl(dev, 0x0000);
-+      if (ret < 0)
-+              goto out;
-+
-+      rx_ctl = asix_read_rx_ctl(dev);
-+      netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
-+
-+      msleep(150);
-+
-+      ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
-+                           AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
-+                           AX88772_IPG2_DEFAULT, 0, NULL);
-+      if (ret < 0) {
-+              netdev_err(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret);
-+              goto out;
-+      }
-+
-+      /* Rewrite MAC address */
-+      memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN);
-+      ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
-+                           data->mac_addr);
-+      if (ret < 0)
-+              goto out;
-+
-+      /* Set RX_CTL to default values with 2k buffer, and enable cactus */
-+      ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL);
-+      if (ret < 0)
-+              goto out;
-+
-+      rx_ctl = asix_read_rx_ctl(dev);
-+      netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n",
-+                 rx_ctl);
-+
-+      rx_ctl = asix_read_medium_status(dev);
-+      netdev_dbg(dev->net, "Medium Status is 0x%04x after all initializations\n",
-+                 rx_ctl);
-+
-+      /* Connect to PHY */
-+      snprintf(priv->phy_name, 20, PHY_ID_FMT,
-+               priv->mdio->id, priv->phy_addr);
-+
-+      priv->phydev = phy_connect(dev->net, priv->phy_name,
-+                                 &ax88172a_adjust_link,
-+                                 PHY_INTERFACE_MODE_MII);
-+      if (IS_ERR(priv->phydev)) {
-+              netdev_err(dev->net, "Could not connect to PHY device %s\n",
-+                         priv->phy_name);
-+              ret = PTR_ERR(priv->phydev);
-+              goto out;
-+      }
-+
-+      netdev_info(dev->net, "Connected to phy %s\n", priv->phy_name);
-+
-+      /* During power-up, the AX88172A set the power down (BMCR_PDOWN)
-+       * bit of the PHY. Bring the PHY up again.
-+       */
-+      genphy_resume(priv->phydev);
-+      phy_start(priv->phydev);
-+
-+      return 0;
-+
-+out:
-+      return ret;
-+
-+}
-+
-+static int ax88172a_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      struct ax88172a_private *dp = dev->driver_priv;
-+      struct asix_rx_fixup_info *rx = &dp->rx_fixup_info;
-+
-+      return asix_rx_fixup_internal(dev, skb, rx);
-+}
-+
-+const struct driver_info ax88172a_info = {
-+      .description = "ASIX AX88172A USB 2.0 Ethernet",
-+      .bind = ax88172a_bind,
-+      .reset = ax88172a_reset,
-+      .stop = ax88172a_stop,
-+      .unbind = ax88172a_unbind,
-+      .status = ax88172a_status,
-+      .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
-+               FLAG_MULTI_PACKET,
-+      .rx_fixup = ax88172a_rx_fixup,
-+      .tx_fixup = asix_tx_fixup,
-+};
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/ax88179_178a.c backports-4.2.6-1/drivers/net/usb/ax88179_178a.c
---- backports-4.2.6-1.org/drivers/net/usb/ax88179_178a.c       1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/ax88179_178a.c   2016-06-28 14:35:17.968640554 +0200
-@@ -0,0 +1,1756 @@
-+/*
-+ * ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet Devices
-+ *
-+ * Copyright (C) 2011-2013 ASIX
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/etherdevice.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/crc32.h>
-+#include <linux/usb/usbnet.h>
-+#include <uapi/linux/mdio.h>
-+#include <linux/mdio.h>
-+
-+#define AX88179_PHY_ID                                0x03
-+#define AX_EEPROM_LEN                         0x100
-+#define AX88179_EEPROM_MAGIC                  0x17900b95
-+#define AX_MCAST_FLTSIZE                      8
-+#define AX_MAX_MCAST                          64
-+#define AX_INT_PPLS_LINK                      ((u32)BIT(16))
-+#define AX_RXHDR_L4_TYPE_MASK                 0x1c
-+#define AX_RXHDR_L4_TYPE_UDP                  4
-+#define AX_RXHDR_L4_TYPE_TCP                  16
-+#define AX_RXHDR_L3CSUM_ERR                   2
-+#define AX_RXHDR_L4CSUM_ERR                   1
-+#define AX_RXHDR_CRC_ERR                      ((u32)BIT(29))
-+#define AX_RXHDR_DROP_ERR                     ((u32)BIT(31))
-+#define AX_ACCESS_MAC                         0x01
-+#define AX_ACCESS_PHY                         0x02
-+#define AX_ACCESS_EEPROM                      0x04
-+#define AX_ACCESS_EFUS                                0x05
-+#define AX_PAUSE_WATERLVL_HIGH                        0x54
-+#define AX_PAUSE_WATERLVL_LOW                 0x55
-+
-+#define PHYSICAL_LINK_STATUS                  0x02
-+      #define AX_USB_SS               0x04
-+      #define AX_USB_HS               0x02
-+
-+#define GENERAL_STATUS                                0x03
-+/* Check AX88179 version. UA1:Bit2 = 0,  UA2:Bit2 = 1 */
-+      #define AX_SECLD                0x04
-+
-+#define AX_SROM_ADDR                          0x07
-+#define AX_SROM_CMD                           0x0a
-+      #define EEP_RD                  0x04
-+      #define EEP_BUSY                0x10
-+
-+#define AX_SROM_DATA_LOW                      0x08
-+#define AX_SROM_DATA_HIGH                     0x09
-+
-+#define AX_RX_CTL                             0x0b
-+      #define AX_RX_CTL_DROPCRCERR    0x0100
-+      #define AX_RX_CTL_IPE           0x0200
-+      #define AX_RX_CTL_START         0x0080
-+      #define AX_RX_CTL_AP            0x0020
-+      #define AX_RX_CTL_AM            0x0010
-+      #define AX_RX_CTL_AB            0x0008
-+      #define AX_RX_CTL_AMALL         0x0002
-+      #define AX_RX_CTL_PRO           0x0001
-+      #define AX_RX_CTL_STOP          0x0000
-+
-+#define AX_NODE_ID                            0x10
-+#define AX_MULFLTARY                          0x16
-+
-+#define AX_MEDIUM_STATUS_MODE                 0x22
-+      #define AX_MEDIUM_GIGAMODE      0x01
-+      #define AX_MEDIUM_FULL_DUPLEX   0x02
-+      #define AX_MEDIUM_EN_125MHZ     0x08
-+      #define AX_MEDIUM_RXFLOW_CTRLEN 0x10
-+      #define AX_MEDIUM_TXFLOW_CTRLEN 0x20
-+      #define AX_MEDIUM_RECEIVE_EN    0x100
-+      #define AX_MEDIUM_PS            0x200
-+      #define AX_MEDIUM_JUMBO_EN      0x8040
-+
-+#define AX_MONITOR_MOD                                0x24
-+      #define AX_MONITOR_MODE_RWLC    0x02
-+      #define AX_MONITOR_MODE_RWMP    0x04
-+      #define AX_MONITOR_MODE_PMEPOL  0x20
-+      #define AX_MONITOR_MODE_PMETYPE 0x40
-+
-+#define AX_GPIO_CTRL                          0x25
-+      #define AX_GPIO_CTRL_GPIO3EN    0x80
-+      #define AX_GPIO_CTRL_GPIO2EN    0x40
-+      #define AX_GPIO_CTRL_GPIO1EN    0x20
-+
-+#define AX_PHYPWR_RSTCTL                      0x26
-+      #define AX_PHYPWR_RSTCTL_BZ     0x0010
-+      #define AX_PHYPWR_RSTCTL_IPRL   0x0020
-+      #define AX_PHYPWR_RSTCTL_AT     0x1000
-+
-+#define AX_RX_BULKIN_QCTRL                    0x2e
-+#define AX_CLK_SELECT                         0x33
-+      #define AX_CLK_SELECT_BCS       0x01
-+      #define AX_CLK_SELECT_ACS       0x02
-+      #define AX_CLK_SELECT_ULR       0x08
-+
-+#define AX_RXCOE_CTL                          0x34
-+      #define AX_RXCOE_IP             0x01
-+      #define AX_RXCOE_TCP            0x02
-+      #define AX_RXCOE_UDP            0x04
-+      #define AX_RXCOE_TCPV6          0x20
-+      #define AX_RXCOE_UDPV6          0x40
-+
-+#define AX_TXCOE_CTL                          0x35
-+      #define AX_TXCOE_IP             0x01
-+      #define AX_TXCOE_TCP            0x02
-+      #define AX_TXCOE_UDP            0x04
-+      #define AX_TXCOE_TCPV6          0x20
-+      #define AX_TXCOE_UDPV6          0x40
-+
-+#define AX_LEDCTRL                            0x73
-+
-+#define GMII_PHY_PHYSR                                0x11
-+      #define GMII_PHY_PHYSR_SMASK    0xc000
-+      #define GMII_PHY_PHYSR_GIGA     0x8000
-+      #define GMII_PHY_PHYSR_100      0x4000
-+      #define GMII_PHY_PHYSR_FULL     0x2000
-+      #define GMII_PHY_PHYSR_LINK     0x400
-+
-+#define GMII_LED_ACT                          0x1a
-+      #define GMII_LED_ACTIVE_MASK    0xff8f
-+      #define GMII_LED0_ACTIVE        BIT(4)
-+      #define GMII_LED1_ACTIVE        BIT(5)
-+      #define GMII_LED2_ACTIVE        BIT(6)
-+
-+#define GMII_LED_LINK                         0x1c
-+      #define GMII_LED_LINK_MASK      0xf888
-+      #define GMII_LED0_LINK_10       BIT(0)
-+      #define GMII_LED0_LINK_100      BIT(1)
-+      #define GMII_LED0_LINK_1000     BIT(2)
-+      #define GMII_LED1_LINK_10       BIT(4)
-+      #define GMII_LED1_LINK_100      BIT(5)
-+      #define GMII_LED1_LINK_1000     BIT(6)
-+      #define GMII_LED2_LINK_10       BIT(8)
-+      #define GMII_LED2_LINK_100      BIT(9)
-+      #define GMII_LED2_LINK_1000     BIT(10)
-+      #define LED0_ACTIVE             BIT(0)
-+      #define LED0_LINK_10            BIT(1)
-+      #define LED0_LINK_100           BIT(2)
-+      #define LED0_LINK_1000          BIT(3)
-+      #define LED0_FD                 BIT(4)
-+      #define LED0_USB3_MASK          0x001f
-+      #define LED1_ACTIVE             BIT(5)
-+      #define LED1_LINK_10            BIT(6)
-+      #define LED1_LINK_100           BIT(7)
-+      #define LED1_LINK_1000          BIT(8)
-+      #define LED1_FD                 BIT(9)
-+      #define LED1_USB3_MASK          0x03e0
-+      #define LED2_ACTIVE             BIT(10)
-+      #define LED2_LINK_1000          BIT(13)
-+      #define LED2_LINK_100           BIT(12)
-+      #define LED2_LINK_10            BIT(11)
-+      #define LED2_FD                 BIT(14)
-+      #define LED_VALID               BIT(15)
-+      #define LED2_USB3_MASK          0x7c00
-+
-+#define GMII_PHYPAGE                          0x1e
-+#define GMII_PHY_PAGE_SELECT                  0x1f
-+      #define GMII_PHY_PGSEL_EXT      0x0007
-+      #define GMII_PHY_PGSEL_PAGE0    0x0000
-+      #define GMII_PHY_PGSEL_PAGE3    0x0003
-+      #define GMII_PHY_PGSEL_PAGE5    0x0005
-+
-+struct ax88179_data {
-+      u8  eee_enabled;
-+      u8  eee_active;
-+      u16 rxctl;
-+      u16 reserved;
-+};
-+
-+struct ax88179_int_data {
-+      __le32 intdata1;
-+      __le32 intdata2;
-+};
-+
-+static const struct {
-+      unsigned char ctrl, timer_l, timer_h, size, ifg;
-+} AX88179_BULKIN_SIZE[] =     {
-+      {7, 0x4f, 0,    0x12, 0xff},
-+      {7, 0x20, 3,    0x16, 0xff},
-+      {7, 0xae, 7,    0x18, 0xff},
-+      {7, 0xcc, 0x4c, 0x18, 8},
-+};
-+
-+static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-+                            u16 size, void *data, int in_pm)
-+{
-+      int ret;
-+      int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
-+
-+      BUG_ON(!dev);
-+
-+      if (!in_pm)
-+              fn = usbnet_read_cmd;
-+      else
-+              fn = usbnet_read_cmd_nopm;
-+
-+      ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+               value, index, data, size);
-+
-+      if (unlikely(ret < 0))
-+              netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n",
-+                          index, ret);
-+
-+      return ret;
-+}
-+
-+static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-+                             u16 size, void *data, int in_pm)
-+{
-+      int ret;
-+      int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
-+
-+      BUG_ON(!dev);
-+
-+      if (!in_pm)
-+              fn = usbnet_write_cmd;
-+      else
-+              fn = usbnet_write_cmd_nopm;
-+
-+      ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+               value, index, data, size);
-+
-+      if (unlikely(ret < 0))
-+              netdev_warn(dev->net, "Failed to write reg index 0x%04x: %d\n",
-+                          index, ret);
-+
-+      return ret;
-+}
-+
-+static void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value,
-+                                  u16 index, u16 size, void *data)
-+{
-+      u16 buf;
-+
-+      if (2 == size) {
-+              buf = *((u16 *)data);
-+              cpu_to_le16s(&buf);
-+              usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR |
-+                                     USB_RECIP_DEVICE, value, index, &buf,
-+                                     size);
-+      } else {
-+              usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR |
-+                                     USB_RECIP_DEVICE, value, index, data,
-+                                     size);
-+      }
-+}
-+
-+static int ax88179_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
-+                               u16 index, u16 size, void *data)
-+{
-+      int ret;
-+
-+      if (2 == size) {
-+              u16 buf;
-+              ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1);
-+              le16_to_cpus(&buf);
-+              *((u16 *)data) = buf;
-+      } else if (4 == size) {
-+              u32 buf;
-+              ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1);
-+              le32_to_cpus(&buf);
-+              *((u32 *)data) = buf;
-+      } else {
-+              ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 1);
-+      }
-+
-+      return ret;
-+}
-+
-+static int ax88179_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value,
-+                                u16 index, u16 size, void *data)
-+{
-+      int ret;
-+
-+      if (2 == size) {
-+              u16 buf;
-+              buf = *((u16 *)data);
-+              cpu_to_le16s(&buf);
-+              ret = __ax88179_write_cmd(dev, cmd, value, index,
-+                                        size, &buf, 1);
-+      } else {
-+              ret = __ax88179_write_cmd(dev, cmd, value, index,
-+                                        size, data, 1);
-+      }
-+
-+      return ret;
-+}
-+
-+static int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-+                          u16 size, void *data)
-+{
-+      int ret;
-+
-+      if (2 == size) {
-+              u16 buf;
-+              ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0);
-+              le16_to_cpus(&buf);
-+              *((u16 *)data) = buf;
-+      } else if (4 == size) {
-+              u32 buf;
-+              ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0);
-+              le32_to_cpus(&buf);
-+              *((u32 *)data) = buf;
-+      } else {
-+              ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 0);
-+      }
-+
-+      return ret;
-+}
-+
-+static int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-+                           u16 size, void *data)
-+{
-+      int ret;
-+
-+      if (2 == size) {
-+              u16 buf;
-+              buf = *((u16 *)data);
-+              cpu_to_le16s(&buf);
-+              ret = __ax88179_write_cmd(dev, cmd, value, index,
-+                                        size, &buf, 0);
-+      } else {
-+              ret = __ax88179_write_cmd(dev, cmd, value, index,
-+                                        size, data, 0);
-+      }
-+
-+      return ret;
-+}
-+
-+static void ax88179_status(struct usbnet *dev, struct urb *urb)
-+{
-+      struct ax88179_int_data *event;
-+      u32 link;
-+
-+      if (urb->actual_length < 8)
-+              return;
-+
-+      event = urb->transfer_buffer;
-+      le32_to_cpus((void *)&event->intdata1);
-+
-+      link = (((__force u32)event->intdata1) & AX_INT_PPLS_LINK) >> 16;
-+
-+      if (netif_carrier_ok(dev->net) != link) {
-+              usbnet_link_change(dev, link, 1);
-+              netdev_info(dev->net, "ax88179 - Link status is: %d\n", link);
-+      }
-+}
-+
-+static int ax88179_mdio_read(struct net_device *netdev, int phy_id, int loc)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      u16 res;
-+
-+      ax88179_read_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res);
-+      return res;
-+}
-+
-+static void ax88179_mdio_write(struct net_device *netdev, int phy_id, int loc,
-+                             int val)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      u16 res = (u16) val;
-+
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res);
-+}
-+
-+static inline int ax88179_phy_mmd_indirect(struct usbnet *dev, u16 prtad,
-+                                         u16 devad)
-+{
-+      u16 tmp16;
-+      int ret;
-+
-+      tmp16 = devad;
-+      ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                              MII_MMD_CTRL, 2, &tmp16);
-+
-+      tmp16 = prtad;
-+      ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                              MII_MMD_DATA, 2, &tmp16);
-+
-+      tmp16 = devad | MII_MMD_CTRL_NOINCR;
-+      ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                              MII_MMD_CTRL, 2, &tmp16);
-+
-+      return ret;
-+}
-+
-+static int
-+ax88179_phy_read_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad)
-+{
-+      int ret;
-+      u16 tmp16;
-+
-+      ax88179_phy_mmd_indirect(dev, prtad, devad);
-+
-+      ret = ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                             MII_MMD_DATA, 2, &tmp16);
-+      if (ret < 0)
-+              return ret;
-+
-+      return tmp16;
-+}
-+
-+static int
-+ax88179_phy_write_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad,
-+                             u16 data)
-+{
-+      int ret;
-+
-+      ax88179_phy_mmd_indirect(dev, prtad, devad);
-+
-+      ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                              MII_MMD_DATA, 2, &data);
-+
-+      if (ret < 0)
-+              return ret;
-+
-+      return 0;
-+}
-+
-+static int ax88179_suspend(struct usb_interface *intf, pm_message_t message)
-+{
-+      struct usbnet *dev = usb_get_intfdata(intf);
-+      u16 tmp16;
-+      u8 tmp8;
-+
-+      usbnet_suspend(intf, message);
-+
-+      /* Disable RX path */
-+      ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
-+                            2, 2, &tmp16);
-+      tmp16 &= ~AX_MEDIUM_RECEIVE_EN;
-+      ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
-+                             2, 2, &tmp16);
-+
-+      /* Force bulk-in zero length */
-+      ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL,
-+                            2, 2, &tmp16);
-+
-+      tmp16 |= AX_PHYPWR_RSTCTL_BZ | AX_PHYPWR_RSTCTL_IPRL;
-+      ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL,
-+                             2, 2, &tmp16);
-+
-+      /* change clock */
-+      tmp8 = 0;
-+      ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8);
-+
-+      /* Configure RX control register => stop operation */
-+      tmp16 = AX_RX_CTL_STOP;
-+      ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16);
-+
-+      return 0;
-+}
-+
-+/* This function is used to enable the autodetach function. */
-+/* This function is determined by offset 0x43 of EEPROM */
-+static int ax88179_auto_detach(struct usbnet *dev, int in_pm)
-+{
-+      u16 tmp16;
-+      u8 tmp8;
-+      int (*fnr)(struct usbnet *, u8, u16, u16, u16, void *);
-+      int (*fnw)(struct usbnet *, u8, u16, u16, u16, void *);
-+
-+      if (!in_pm) {
-+              fnr = ax88179_read_cmd;
-+              fnw = ax88179_write_cmd;
-+      } else {
-+              fnr = ax88179_read_cmd_nopm;
-+              fnw = ax88179_write_cmd_nopm;
-+      }
-+
-+      if (fnr(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &tmp16) < 0)
-+              return 0;
-+
-+      if ((tmp16 == 0xFFFF) || (!(tmp16 & 0x0100)))
-+              return 0;
-+
-+      /* Enable Auto Detach bit */
-+      tmp8 = 0;
-+      fnr(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8);
-+      tmp8 |= AX_CLK_SELECT_ULR;
-+      fnw(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8);
-+
-+      fnr(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16);
-+      tmp16 |= AX_PHYPWR_RSTCTL_AT;
-+      fnw(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16);
-+
-+      return 0;
-+}
-+
-+static int ax88179_resume(struct usb_interface *intf)
-+{
-+      struct usbnet *dev = usb_get_intfdata(intf);
-+      u16 tmp16;
-+      u8 tmp8;
-+
-+      usbnet_link_change(dev, 0, 0);
-+
-+      /* Power up ethernet PHY */
-+      tmp16 = 0;
-+      ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL,
-+                             2, 2, &tmp16);
-+      udelay(1000);
-+
-+      tmp16 = AX_PHYPWR_RSTCTL_IPRL;
-+      ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL,
-+                             2, 2, &tmp16);
-+      msleep(200);
-+
-+      /* Ethernet PHY Auto Detach*/
-+      ax88179_auto_detach(dev, 1);
-+
-+      /* Enable clock */
-+      ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC,  AX_CLK_SELECT, 1, 1, &tmp8);
-+      tmp8 |= AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS;
-+      ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8);
-+      msleep(100);
-+
-+      /* Configure RX control register => start operation */
-+      tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START |
-+              AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB;
-+      ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16);
-+
-+      return usbnet_resume(intf);
-+}
-+
-+static void
-+ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      u8 opt;
-+
-+      if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD,
-+                           1, 1, &opt) < 0) {
-+              wolinfo->supported = 0;
-+              wolinfo->wolopts = 0;
-+              return;
-+      }
-+
-+      wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
-+      wolinfo->wolopts = 0;
-+      if (opt & AX_MONITOR_MODE_RWLC)
-+              wolinfo->wolopts |= WAKE_PHY;
-+      if (opt & AX_MONITOR_MODE_RWMP)
-+              wolinfo->wolopts |= WAKE_MAGIC;
-+}
-+
-+static int
-+ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      u8 opt = 0;
-+
-+      if (wolinfo->wolopts & WAKE_PHY)
-+              opt |= AX_MONITOR_MODE_RWLC;
-+      if (wolinfo->wolopts & WAKE_MAGIC)
-+              opt |= AX_MONITOR_MODE_RWMP;
-+
-+      if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD,
-+                            1, 1, &opt) < 0)
-+              return -EINVAL;
-+
-+      return 0;
-+}
-+
-+static int ax88179_get_eeprom_len(struct net_device *net)
-+{
-+      return AX_EEPROM_LEN;
-+}
-+
-+static int
-+ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
-+                 u8 *data)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      u16 *eeprom_buff;
-+      int first_word, last_word;
-+      int i, ret;
-+
-+      if (eeprom->len == 0)
-+              return -EINVAL;
-+
-+      eeprom->magic = AX88179_EEPROM_MAGIC;
-+
-+      first_word = eeprom->offset >> 1;
-+      last_word = (eeprom->offset + eeprom->len - 1) >> 1;
-+      eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
-+                            GFP_KERNEL);
-+      if (!eeprom_buff)
-+              return -ENOMEM;
-+
-+      /* ax88179/178A returns 2 bytes from eeprom on read */
-+      for (i = first_word; i <= last_word; i++) {
-+              ret = __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2,
-+                                       &eeprom_buff[i - first_word],
-+                                       0);
-+              if (ret < 0) {
-+                      kfree(eeprom_buff);
-+                      return -EIO;
-+              }
-+      }
-+
-+      memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
-+      kfree(eeprom_buff);
-+      return 0;
-+}
-+
-+static int ax88179_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      return mii_ethtool_gset(&dev->mii, cmd);
-+}
-+
-+static int ax88179_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      return mii_ethtool_sset(&dev->mii, cmd);
-+}
-+
-+static int
-+ax88179_ethtool_get_eee(struct usbnet *dev, struct ethtool_eee *data)
-+{
-+      int val;
-+
-+      /* Get Supported EEE */
-+      val = ax88179_phy_read_mmd_indirect(dev, MDIO_PCS_EEE_ABLE,
-+                                          MDIO_MMD_PCS);
-+      if (val < 0)
-+              return val;
-+      data->supported = mmd_eee_cap_to_ethtool_sup_t(val);
-+
-+      /* Get advertisement EEE */
-+      val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_ADV,
-+                                          MDIO_MMD_AN);
-+      if (val < 0)
-+              return val;
-+      data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
-+
-+      /* Get LP advertisement EEE */
-+      val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_LPABLE,
-+                                          MDIO_MMD_AN);
-+      if (val < 0)
-+              return val;
-+      data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
-+
-+      return 0;
-+}
-+
-+static int
-+ax88179_ethtool_set_eee(struct usbnet *dev, struct ethtool_eee *data)
-+{
-+      u16 tmp16 = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
-+
-+      return ax88179_phy_write_mmd_indirect(dev, MDIO_AN_EEE_ADV,
-+                                            MDIO_MMD_AN, tmp16);
-+}
-+
-+static int ax88179_chk_eee(struct usbnet *dev)
-+{
-+      struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
-+      struct ax88179_data *priv = (struct ax88179_data *)dev->data;
-+
-+      mii_ethtool_gset(&dev->mii, &ecmd);
-+
-+      if (ecmd.duplex & DUPLEX_FULL) {
-+              int eee_lp, eee_cap, eee_adv;
-+              u32 lp, cap, adv, supported = 0;
-+
-+              eee_cap = ax88179_phy_read_mmd_indirect(dev,
-+                                                      MDIO_PCS_EEE_ABLE,
-+                                                      MDIO_MMD_PCS);
-+              if (eee_cap < 0) {
-+                      priv->eee_active = 0;
-+                      return false;
-+              }
-+
-+              cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);
-+              if (!cap) {
-+                      priv->eee_active = 0;
-+                      return false;
-+              }
-+
-+              eee_lp = ax88179_phy_read_mmd_indirect(dev,
-+                                                     MDIO_AN_EEE_LPABLE,
-+                                                     MDIO_MMD_AN);
-+              if (eee_lp < 0) {
-+                      priv->eee_active = 0;
-+                      return false;
-+              }
-+
-+              eee_adv = ax88179_phy_read_mmd_indirect(dev,
-+                                                      MDIO_AN_EEE_ADV,
-+                                                      MDIO_MMD_AN);
-+
-+              if (eee_adv < 0) {
-+                      priv->eee_active = 0;
-+                      return false;
-+              }
-+
-+              adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);
-+              lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
-+              supported = (ecmd.speed == SPEED_1000) ?
-+                           SUPPORTED_1000baseT_Full :
-+                           SUPPORTED_100baseT_Full;
-+
-+              if (!(lp & adv & supported)) {
-+                      priv->eee_active = 0;
-+                      return false;
-+              }
-+
-+              priv->eee_active = 1;
-+              return true;
-+      }
-+
-+      priv->eee_active = 0;
-+      return false;
-+}
-+
-+static void ax88179_disable_eee(struct usbnet *dev)
-+{
-+      u16 tmp16;
-+
-+      tmp16 = GMII_PHY_PGSEL_PAGE3;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        GMII_PHY_PAGE_SELECT, 2, &tmp16);
-+
-+      tmp16 = 0x3246;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        MII_PHYADDR, 2, &tmp16);
-+
-+      tmp16 = GMII_PHY_PGSEL_PAGE0;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        GMII_PHY_PAGE_SELECT, 2, &tmp16);
-+}
-+
-+static void ax88179_enable_eee(struct usbnet *dev)
-+{
-+      u16 tmp16;
-+
-+      tmp16 = GMII_PHY_PGSEL_PAGE3;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        GMII_PHY_PAGE_SELECT, 2, &tmp16);
-+
-+      tmp16 = 0x3247;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        MII_PHYADDR, 2, &tmp16);
-+
-+      tmp16 = GMII_PHY_PGSEL_PAGE5;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        GMII_PHY_PAGE_SELECT, 2, &tmp16);
-+
-+      tmp16 = 0x0680;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        MII_BMSR, 2, &tmp16);
-+
-+      tmp16 = GMII_PHY_PGSEL_PAGE0;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        GMII_PHY_PAGE_SELECT, 2, &tmp16);
-+}
-+
-+static int ax88179_get_eee(struct net_device *net, struct ethtool_eee *edata)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct ax88179_data *priv = (struct ax88179_data *)dev->data;
-+
-+      edata->eee_enabled = priv->eee_enabled;
-+      edata->eee_active = priv->eee_active;
-+
-+      return ax88179_ethtool_get_eee(dev, edata);
-+}
-+
-+static int ax88179_set_eee(struct net_device *net, struct ethtool_eee *edata)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct ax88179_data *priv = (struct ax88179_data *)dev->data;
-+      int ret = -EOPNOTSUPP;
-+
-+      priv->eee_enabled = edata->eee_enabled;
-+      if (!priv->eee_enabled) {
-+              ax88179_disable_eee(dev);
-+      } else {
-+              priv->eee_enabled = ax88179_chk_eee(dev);
-+              if (!priv->eee_enabled)
-+                      return -EOPNOTSUPP;
-+
-+              ax88179_enable_eee(dev);
-+      }
-+
-+      ret = ax88179_ethtool_set_eee(dev, edata);
-+      if (ret)
-+              return ret;
-+
-+      mii_nway_restart(&dev->mii);
-+
-+      usbnet_link_change(dev, 0, 0);
-+
-+      return ret;
-+}
-+
-+static int ax88179_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
-+}
-+
-+static const struct ethtool_ops ax88179_ethtool_ops = {
-+      .get_link               = ethtool_op_get_link,
-+      .get_msglevel           = usbnet_get_msglevel,
-+      .set_msglevel           = usbnet_set_msglevel,
-+      .get_wol                = ax88179_get_wol,
-+      .set_wol                = ax88179_set_wol,
-+      .get_eeprom_len         = ax88179_get_eeprom_len,
-+      .get_eeprom             = ax88179_get_eeprom,
-+      .get_settings           = ax88179_get_settings,
-+      .set_settings           = ax88179_set_settings,
-+      .get_eee                = ax88179_get_eee,
-+      .set_eee                = ax88179_set_eee,
-+      .nway_reset             = usbnet_nway_reset,
-+};
-+
-+static void ax88179_set_multicast(struct net_device *net)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct ax88179_data *data = (struct ax88179_data *)dev->data;
-+      u8 *m_filter = ((u8 *)dev->data) + 12;
-+
-+      data->rxctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE);
-+
-+      if (net->flags & IFF_PROMISC) {
-+              data->rxctl |= AX_RX_CTL_PRO;
-+      } else if (net->flags & IFF_ALLMULTI ||
-+                 netdev_mc_count(net) > AX_MAX_MCAST) {
-+              data->rxctl |= AX_RX_CTL_AMALL;
-+      } else if (netdev_mc_empty(net)) {
-+              /* just broadcast and directed */
-+      } else {
-+              /* We use the 20 byte dev->data for our 8 byte filter buffer
-+               * to avoid allocating memory that is tricky to free later
-+               */
-+              u32 crc_bits;
-+              struct netdev_hw_addr *ha;
-+
-+              memset(m_filter, 0, AX_MCAST_FLTSIZE);
-+
-+              netdev_for_each_mc_addr(ha, net) {
-+                      crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
-+                      *(m_filter + (crc_bits >> 3)) |= (1 << (crc_bits & 7));
-+              }
-+
-+              ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_MULFLTARY,
-+                                      AX_MCAST_FLTSIZE, AX_MCAST_FLTSIZE,
-+                                      m_filter);
-+
-+              data->rxctl |= AX_RX_CTL_AM;
-+      }
-+
-+      ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_RX_CTL,
-+                              2, 2, &data->rxctl);
-+}
-+
-+static int
-+ax88179_set_features(struct net_device *net, netdev_features_t features)
-+{
-+      u8 tmp;
-+      struct usbnet *dev = netdev_priv(net);
-+      netdev_features_t changed = net->features ^ features;
-+
-+      if (changed & NETIF_F_IP_CSUM) {
-+              ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
-+              tmp ^= AX_TXCOE_TCP | AX_TXCOE_UDP;
-+              ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
-+      }
-+
-+      if (changed & NETIF_F_IPV6_CSUM) {
-+              ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
-+              tmp ^= AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6;
-+              ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp);
-+      }
-+
-+      if (changed & NETIF_F_RXCSUM) {
-+              ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp);
-+              tmp ^= AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP |
-+                     AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6;
-+              ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp);
-+      }
-+
-+      return 0;
-+}
-+
-+static int ax88179_change_mtu(struct net_device *net, int new_mtu)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      u16 tmp16;
-+
-+      if (new_mtu <= 0 || new_mtu > 4088)
-+              return -EINVAL;
-+
-+      net->mtu = new_mtu;
-+      dev->hard_mtu = net->mtu + net->hard_header_len;
-+
-+      if (net->mtu > 1500) {
-+              ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
-+                               2, 2, &tmp16);
-+              tmp16 |= AX_MEDIUM_JUMBO_EN;
-+              ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
-+                                2, 2, &tmp16);
-+      } else {
-+              ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
-+                               2, 2, &tmp16);
-+              tmp16 &= ~AX_MEDIUM_JUMBO_EN;
-+              ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
-+                                2, 2, &tmp16);
-+      }
-+
-+      /* max qlen depend on hard_mtu and rx_urb_size */
-+      usbnet_update_max_qlen(dev);
-+
-+      return 0;
-+}
-+
-+static int ax88179_set_mac_addr(struct net_device *net, void *p)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct sockaddr *addr = p;
-+      int ret;
-+
-+      if (netif_running(net))
-+              return -EBUSY;
-+      if (!is_valid_ether_addr(addr->sa_data))
-+              return -EADDRNOTAVAIL;
-+
-+      memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
-+
-+      /* Set the MAC address */
-+      ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN,
-+                               ETH_ALEN, net->dev_addr);
-+      if (ret < 0)
-+              return ret;
-+
-+      return 0;
-+}
-+
-+static const struct net_device_ops ax88179_netdev_ops = {
-+      .ndo_open               = usbnet_open,
-+      .ndo_stop               = usbnet_stop,
-+      .ndo_start_xmit         = usbnet_start_xmit,
-+      .ndo_tx_timeout         = usbnet_tx_timeout,
-+      .ndo_change_mtu         = ax88179_change_mtu,
-+      .ndo_set_mac_address    = ax88179_set_mac_addr,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_do_ioctl           = ax88179_ioctl,
-+      .ndo_set_rx_mode        = ax88179_set_multicast,
-+      .ndo_set_features       = ax88179_set_features,
-+};
-+
-+static int ax88179_check_eeprom(struct usbnet *dev)
-+{
-+      u8 i, buf, eeprom[20];
-+      u16 csum, delay = HZ / 10;
-+      unsigned long jtimeout;
-+
-+      /* Read EEPROM content */
-+      for (i = 0; i < 6; i++) {
-+              buf = i;
-+              if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR,
-+                                    1, 1, &buf) < 0)
-+                      return -EINVAL;
-+
-+              buf = EEP_RD;
-+              if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD,
-+                                    1, 1, &buf) < 0)
-+                      return -EINVAL;
-+
-+              jtimeout = jiffies + delay;
-+              do {
-+                      ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD,
-+                                       1, 1, &buf);
-+
-+                      if (time_after(jiffies, jtimeout))
-+                              return -EINVAL;
-+
-+              } while (buf & EEP_BUSY);
-+
-+              __ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW,
-+                                 2, 2, &eeprom[i * 2], 0);
-+
-+              if ((i == 0) && (eeprom[0] == 0xFF))
-+                      return -EINVAL;
-+      }
-+
-+      csum = eeprom[6] + eeprom[7] + eeprom[8] + eeprom[9];
-+      csum = (csum >> 8) + (csum & 0xff);
-+      if ((csum + eeprom[10]) != 0xff)
-+              return -EINVAL;
-+
-+      return 0;
-+}
-+
-+static int ax88179_check_efuse(struct usbnet *dev, u16 *ledmode)
-+{
-+      u8      i;
-+      u8      efuse[64];
-+      u16     csum = 0;
-+
-+      if (ax88179_read_cmd(dev, AX_ACCESS_EFUS, 0, 64, 64, efuse) < 0)
-+              return -EINVAL;
-+
-+      if (*efuse == 0xFF)
-+              return -EINVAL;
-+
-+      for (i = 0; i < 64; i++)
-+              csum = csum + efuse[i];
-+
-+      while (csum > 255)
-+              csum = (csum & 0x00FF) + ((csum >> 8) & 0x00FF);
-+
-+      if (csum != 0xFF)
-+              return -EINVAL;
-+
-+      *ledmode = (efuse[51] << 8) | efuse[52];
-+
-+      return 0;
-+}
-+
-+static int ax88179_convert_old_led(struct usbnet *dev, u16 *ledvalue)
-+{
-+      u16 led;
-+
-+      /* Loaded the old eFuse LED Mode */
-+      if (ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x3C, 1, 2, &led) < 0)
-+              return -EINVAL;
-+
-+      led >>= 8;
-+      switch (led) {
-+      case 0xFF:
-+              led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 |
-+                    LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 |
-+                    LED2_LINK_100 | LED2_LINK_1000 | LED_VALID;
-+              break;
-+      case 0xFE:
-+              led = LED0_ACTIVE | LED1_LINK_1000 | LED2_LINK_100 | LED_VALID;
-+              break;
-+      case 0xFD:
-+              led = LED0_ACTIVE | LED1_LINK_1000 | LED2_LINK_100 |
-+                    LED2_LINK_10 | LED_VALID;
-+              break;
-+      case 0xFC:
-+              led = LED0_ACTIVE | LED1_ACTIVE | LED1_LINK_1000 | LED2_ACTIVE |
-+                    LED2_LINK_100 | LED2_LINK_10 | LED_VALID;
-+              break;
-+      default:
-+              led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 |
-+                    LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 |
-+                    LED2_LINK_100 | LED2_LINK_1000 | LED_VALID;
-+              break;
-+      }
-+
-+      *ledvalue = led;
-+
-+      return 0;
-+}
-+
-+static int ax88179_led_setting(struct usbnet *dev)
-+{
-+      u8 ledfd, value = 0;
-+      u16 tmp, ledact, ledlink, ledvalue = 0, delay = HZ / 10;
-+      unsigned long jtimeout;
-+
-+      /* Check AX88179 version. UA1 or UA2*/
-+      ax88179_read_cmd(dev, AX_ACCESS_MAC, GENERAL_STATUS, 1, 1, &value);
-+
-+      if (!(value & AX_SECLD)) {      /* UA1 */
-+              value = AX_GPIO_CTRL_GPIO3EN | AX_GPIO_CTRL_GPIO2EN |
-+                      AX_GPIO_CTRL_GPIO1EN;
-+              if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_GPIO_CTRL,
-+                                    1, 1, &value) < 0)
-+                      return -EINVAL;
-+      }
-+
-+      /* Check EEPROM */
-+      if (!ax88179_check_eeprom(dev)) {
-+              value = 0x42;
-+              if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR,
-+                                    1, 1, &value) < 0)
-+                      return -EINVAL;
-+
-+              value = EEP_RD;
-+              if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD,
-+                                    1, 1, &value) < 0)
-+                      return -EINVAL;
-+
-+              jtimeout = jiffies + delay;
-+              do {
-+                      ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD,
-+                                       1, 1, &value);
-+
-+                      if (time_after(jiffies, jtimeout))
-+                              return -EINVAL;
-+
-+              } while (value & EEP_BUSY);
-+
-+              ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_HIGH,
-+                               1, 1, &value);
-+              ledvalue = (value << 8);
-+
-+              ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW,
-+                               1, 1, &value);
-+              ledvalue |= value;
-+
-+              /* load internal ROM for defaule setting */
-+              if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0))
-+                      ax88179_convert_old_led(dev, &ledvalue);
-+
-+      } else if (!ax88179_check_efuse(dev, &ledvalue)) {
-+              if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0))
-+                      ax88179_convert_old_led(dev, &ledvalue);
-+      } else {
-+              ax88179_convert_old_led(dev, &ledvalue);
-+      }
-+
-+      tmp = GMII_PHY_PGSEL_EXT;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        GMII_PHY_PAGE_SELECT, 2, &tmp);
-+
-+      tmp = 0x2c;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        GMII_PHYPAGE, 2, &tmp);
-+
-+      ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                       GMII_LED_ACT, 2, &ledact);
-+
-+      ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                       GMII_LED_LINK, 2, &ledlink);
-+
-+      ledact &= GMII_LED_ACTIVE_MASK;
-+      ledlink &= GMII_LED_LINK_MASK;
-+
-+      if (ledvalue & LED0_ACTIVE)
-+              ledact |= GMII_LED0_ACTIVE;
-+
-+      if (ledvalue & LED1_ACTIVE)
-+              ledact |= GMII_LED1_ACTIVE;
-+
-+      if (ledvalue & LED2_ACTIVE)
-+              ledact |= GMII_LED2_ACTIVE;
-+
-+      if (ledvalue & LED0_LINK_10)
-+              ledlink |= GMII_LED0_LINK_10;
-+
-+      if (ledvalue & LED1_LINK_10)
-+              ledlink |= GMII_LED1_LINK_10;
-+
-+      if (ledvalue & LED2_LINK_10)
-+              ledlink |= GMII_LED2_LINK_10;
-+
-+      if (ledvalue & LED0_LINK_100)
-+              ledlink |= GMII_LED0_LINK_100;
-+
-+      if (ledvalue & LED1_LINK_100)
-+              ledlink |= GMII_LED1_LINK_100;
-+
-+      if (ledvalue & LED2_LINK_100)
-+              ledlink |= GMII_LED2_LINK_100;
-+
-+      if (ledvalue & LED0_LINK_1000)
-+              ledlink |= GMII_LED0_LINK_1000;
-+
-+      if (ledvalue & LED1_LINK_1000)
-+              ledlink |= GMII_LED1_LINK_1000;
-+
-+      if (ledvalue & LED2_LINK_1000)
-+              ledlink |= GMII_LED2_LINK_1000;
-+
-+      tmp = ledact;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        GMII_LED_ACT, 2, &tmp);
-+
-+      tmp = ledlink;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        GMII_LED_LINK, 2, &tmp);
-+
-+      tmp = GMII_PHY_PGSEL_PAGE0;
-+      ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                        GMII_PHY_PAGE_SELECT, 2, &tmp);
-+
-+      /* LED full duplex setting */
-+      ledfd = 0;
-+      if (ledvalue & LED0_FD)
-+              ledfd |= 0x01;
-+      else if ((ledvalue & LED0_USB3_MASK) == 0)
-+              ledfd |= 0x02;
-+
-+      if (ledvalue & LED1_FD)
-+              ledfd |= 0x04;
-+      else if ((ledvalue & LED1_USB3_MASK) == 0)
-+              ledfd |= 0x08;
-+
-+      if (ledvalue & LED2_FD)
-+              ledfd |= 0x10;
-+      else if ((ledvalue & LED2_USB3_MASK) == 0)
-+              ledfd |= 0x20;
-+
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_LEDCTRL, 1, 1, &ledfd);
-+
-+      return 0;
-+}
-+
-+static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      u8 buf[5];
-+      u16 *tmp16;
-+      u8 *tmp;
-+      struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
-+      struct ethtool_eee eee_data;
-+
-+      usbnet_get_endpoints(dev, intf);
-+
-+      tmp16 = (u16 *)buf;
-+      tmp = (u8 *)buf;
-+
-+      memset(ax179_data, 0, sizeof(*ax179_data));
-+
-+      /* Power up ethernet PHY */
-+      *tmp16 = 0;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16);
-+      *tmp16 = AX_PHYPWR_RSTCTL_IPRL;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16);
-+      msleep(200);
-+
-+      *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp);
-+      msleep(100);
-+
-+      ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN,
-+                       ETH_ALEN, dev->net->dev_addr);
-+      memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
-+
-+      /* RX bulk configuration */
-+      memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5);
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp);
-+
-+      dev->rx_urb_size = 1024 * 20;
-+
-+      *tmp = 0x34;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp);
-+
-+      *tmp = 0x52;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH,
-+                        1, 1, tmp);
-+
-+      dev->net->netdev_ops = &ax88179_netdev_ops;
-+      dev->net->ethtool_ops = &ax88179_ethtool_ops;
-+      dev->net->needed_headroom = 8;
-+
-+      /* Initialize MII structure */
-+      dev->mii.dev = dev->net;
-+      dev->mii.mdio_read = ax88179_mdio_read;
-+      dev->mii.mdio_write = ax88179_mdio_write;
-+      dev->mii.phy_id_mask = 0xff;
-+      dev->mii.reg_num_mask = 0xff;
-+      dev->mii.phy_id = 0x03;
-+      dev->mii.supports_gmii = 1;
-+
-+      dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-+                            NETIF_F_RXCSUM;
-+
-+      dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-+                               NETIF_F_RXCSUM;
-+
-+      /* Enable checksum offload */
-+      *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP |
-+             AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp);
-+
-+      *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP |
-+             AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp);
-+
-+      /* Configure RX control register => start operation */
-+      *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START |
-+               AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16);
-+
-+      *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL |
-+             AX_MONITOR_MODE_RWMP;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp);
-+
-+      /* Configure default medium type => giga */
-+      *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN |
-+               AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX |
-+               AX_MEDIUM_GIGAMODE;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
-+                        2, 2, tmp16);
-+
-+      ax88179_led_setting(dev);
-+
-+      ax179_data->eee_enabled = 0;
-+      ax179_data->eee_active = 0;
-+
-+      ax88179_disable_eee(dev);
-+
-+      ax88179_ethtool_get_eee(dev, &eee_data);
-+      eee_data.advertised = 0;
-+      ax88179_ethtool_set_eee(dev, &eee_data);
-+
-+      /* Restart autoneg */
-+      mii_nway_restart(&dev->mii);
-+
-+      usbnet_link_change(dev, 0, 0);
-+
-+      return 0;
-+}
-+
-+static void ax88179_unbind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      u16 tmp16;
-+
-+      /* Configure RX control register => stop operation */
-+      tmp16 = AX_RX_CTL_STOP;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16);
-+
-+      tmp16 = 0;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp16);
-+
-+      /* Power down ethernet PHY */
-+      tmp16 = 0;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16);
-+}
-+
-+static void
-+ax88179_rx_checksum(struct sk_buff *skb, u32 *pkt_hdr)
-+{
-+      skb->ip_summed = CHECKSUM_NONE;
-+
-+      /* checksum error bit is set */
-+      if ((*pkt_hdr & AX_RXHDR_L3CSUM_ERR) ||
-+          (*pkt_hdr & AX_RXHDR_L4CSUM_ERR))
-+              return;
-+
-+      /* It must be a TCP or UDP packet with a valid checksum */
-+      if (((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_TCP) ||
-+          ((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_UDP))
-+              skb->ip_summed = CHECKSUM_UNNECESSARY;
-+}
-+
-+static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      struct sk_buff *ax_skb;
-+      int pkt_cnt;
-+      u32 rx_hdr;
-+      u16 hdr_off;
-+      u32 *pkt_hdr;
-+
-+      /* This check is no longer done by usbnet */
-+      if (skb->len < dev->net->hard_header_len)
-+              return 0;
-+
-+      skb_trim(skb, skb->len - 4);
-+      memcpy(&rx_hdr, skb_tail_pointer(skb), 4);
-+      le32_to_cpus(&rx_hdr);
-+
-+      pkt_cnt = (u16)rx_hdr;
-+      hdr_off = (u16)(rx_hdr >> 16);
-+      pkt_hdr = (u32 *)(skb->data + hdr_off);
-+
-+      while (pkt_cnt--) {
-+              u16 pkt_len;
-+
-+              le32_to_cpus(pkt_hdr);
-+              pkt_len = (*pkt_hdr >> 16) & 0x1fff;
-+
-+              /* Check CRC or runt packet */
-+              if ((*pkt_hdr & AX_RXHDR_CRC_ERR) ||
-+                  (*pkt_hdr & AX_RXHDR_DROP_ERR)) {
-+                      skb_pull(skb, (pkt_len + 7) & 0xFFF8);
-+                      pkt_hdr++;
-+                      continue;
-+              }
-+
-+              if (pkt_cnt == 0) {
-+                      /* Skip IP alignment psudo header */
-+                      skb_pull(skb, 2);
-+                      skb->len = pkt_len;
-+                      skb_set_tail_pointer(skb, pkt_len);
-+                      skb->truesize = pkt_len + sizeof(struct sk_buff);
-+                      ax88179_rx_checksum(skb, pkt_hdr);
-+                      return 1;
-+              }
-+
-+              ax_skb = skb_clone(skb, GFP_ATOMIC);
-+              if (ax_skb) {
-+                      ax_skb->len = pkt_len;
-+                      ax_skb->data = skb->data + 2;
-+                      skb_set_tail_pointer(ax_skb, pkt_len);
-+                      ax_skb->truesize = pkt_len + sizeof(struct sk_buff);
-+                      ax88179_rx_checksum(ax_skb, pkt_hdr);
-+                      usbnet_skb_return(dev, ax_skb);
-+              } else {
-+                      return 0;
-+              }
-+
-+              skb_pull(skb, (pkt_len + 7) & 0xFFF8);
-+              pkt_hdr++;
-+      }
-+      return 1;
-+}
-+
-+static struct sk_buff *
-+ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
-+{
-+      u32 tx_hdr1, tx_hdr2;
-+      int frame_size = dev->maxpacket;
-+      int mss = skb_shinfo(skb)->gso_size;
-+      int headroom;
-+
-+      tx_hdr1 = skb->len;
-+      tx_hdr2 = mss;
-+      if (((skb->len + 8) % frame_size) == 0)
-+              tx_hdr2 |= 0x80008000;  /* Enable padding */
-+
-+      headroom = skb_headroom(skb) - 8;
-+
-+      if ((skb_header_cloned(skb) || headroom < 0) &&
-+          pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) {
-+              dev_kfree_skb_any(skb);
-+              return NULL;
-+      }
-+
-+      skb_push(skb, 4);
-+      cpu_to_le32s(&tx_hdr2);
-+      skb_copy_to_linear_data(skb, &tx_hdr2, 4);
-+
-+      skb_push(skb, 4);
-+      cpu_to_le32s(&tx_hdr1);
-+      skb_copy_to_linear_data(skb, &tx_hdr1, 4);
-+
-+      return skb;
-+}
-+
-+static int ax88179_link_reset(struct usbnet *dev)
-+{
-+      struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
-+      u8 tmp[5], link_sts;
-+      u16 mode, tmp16, delay = HZ / 10;
-+      u32 tmp32 = 0x40000000;
-+      unsigned long jtimeout;
-+
-+      jtimeout = jiffies + delay;
-+      while (tmp32 & 0x40000000) {
-+              mode = 0;
-+              ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &mode);
-+              ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2,
-+                                &ax179_data->rxctl);
-+
-+              /*link up, check the usb device control TX FIFO full or empty*/
-+              ax88179_read_cmd(dev, 0x81, 0x8c, 0, 4, &tmp32);
-+
-+              if (time_after(jiffies, jtimeout))
-+                      return 0;
-+      }
-+
-+      mode = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN |
-+             AX_MEDIUM_RXFLOW_CTRLEN;
-+
-+      ax88179_read_cmd(dev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS,
-+                       1, 1, &link_sts);
-+
-+      ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
-+                       GMII_PHY_PHYSR, 2, &tmp16);
-+
-+      if (!(tmp16 & GMII_PHY_PHYSR_LINK)) {
-+              return 0;
-+      } else if (GMII_PHY_PHYSR_GIGA == (tmp16 & GMII_PHY_PHYSR_SMASK)) {
-+              mode |= AX_MEDIUM_GIGAMODE | AX_MEDIUM_EN_125MHZ;
-+              if (dev->net->mtu > 1500)
-+                      mode |= AX_MEDIUM_JUMBO_EN;
-+
-+              if (link_sts & AX_USB_SS)
-+                      memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5);
-+              else if (link_sts & AX_USB_HS)
-+                      memcpy(tmp, &AX88179_BULKIN_SIZE[1], 5);
-+              else
-+                      memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5);
-+      } else if (GMII_PHY_PHYSR_100 == (tmp16 & GMII_PHY_PHYSR_SMASK)) {
-+              mode |= AX_MEDIUM_PS;
-+
-+              if (link_sts & (AX_USB_SS | AX_USB_HS))
-+                      memcpy(tmp, &AX88179_BULKIN_SIZE[2], 5);
-+              else
-+                      memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5);
-+      } else {
-+              memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5);
-+      }
-+
-+      /* RX bulk configuration */
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp);
-+
-+      dev->rx_urb_size = (1024 * (tmp[3] + 2));
-+
-+      if (tmp16 & GMII_PHY_PHYSR_FULL)
-+              mode |= AX_MEDIUM_FULL_DUPLEX;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
-+                        2, 2, &mode);
-+
-+      ax179_data->eee_enabled = ax88179_chk_eee(dev);
-+
-+      netif_carrier_on(dev->net);
-+
-+      return 0;
-+}
-+
-+static int ax88179_reset(struct usbnet *dev)
-+{
-+      u8 buf[5];
-+      u16 *tmp16;
-+      u8 *tmp;
-+      struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
-+      struct ethtool_eee eee_data;
-+
-+      tmp16 = (u16 *)buf;
-+      tmp = (u8 *)buf;
-+
-+      /* Power up ethernet PHY */
-+      *tmp16 = 0;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16);
-+
-+      *tmp16 = AX_PHYPWR_RSTCTL_IPRL;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16);
-+      msleep(200);
-+
-+      *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp);
-+      msleep(100);
-+
-+      /* Ethernet PHY Auto Detach*/
-+      ax88179_auto_detach(dev, 0);
-+
-+      ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, ETH_ALEN,
-+                       dev->net->dev_addr);
-+      memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN);
-+
-+      /* RX bulk configuration */
-+      memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5);
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp);
-+
-+      dev->rx_urb_size = 1024 * 20;
-+
-+      *tmp = 0x34;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp);
-+
-+      *tmp = 0x52;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH,
-+                        1, 1, tmp);
-+
-+      dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-+                            NETIF_F_RXCSUM;
-+
-+      dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-+                               NETIF_F_RXCSUM;
-+
-+      /* Enable checksum offload */
-+      *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP |
-+             AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp);
-+
-+      *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP |
-+             AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp);
-+
-+      /* Configure RX control register => start operation */
-+      *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START |
-+               AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16);
-+
-+      *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL |
-+             AX_MONITOR_MODE_RWMP;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp);
-+
-+      /* Configure default medium type => giga */
-+      *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN |
-+               AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX |
-+               AX_MEDIUM_GIGAMODE;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
-+                        2, 2, tmp16);
-+
-+      ax88179_led_setting(dev);
-+
-+      ax179_data->eee_enabled = 0;
-+      ax179_data->eee_active = 0;
-+
-+      ax88179_disable_eee(dev);
-+
-+      ax88179_ethtool_get_eee(dev, &eee_data);
-+      eee_data.advertised = 0;
-+      ax88179_ethtool_set_eee(dev, &eee_data);
-+
-+      /* Restart autoneg */
-+      mii_nway_restart(&dev->mii);
-+
-+      usbnet_link_change(dev, 0, 0);
-+
-+      return 0;
-+}
-+
-+static int ax88179_stop(struct usbnet *dev)
-+{
-+      u16 tmp16;
-+
-+      ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
-+                       2, 2, &tmp16);
-+      tmp16 &= ~AX_MEDIUM_RECEIVE_EN;
-+      ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
-+                        2, 2, &tmp16);
-+
-+      return 0;
-+}
-+
-+static const struct driver_info ax88179_info = {
-+      .description = "ASIX AX88179 USB 3.0 Gigabit Ethernet",
-+      .bind = ax88179_bind,
-+      .unbind = ax88179_unbind,
-+      .status = ax88179_status,
-+      .link_reset = ax88179_link_reset,
-+      .reset = ax88179_reset,
-+      .stop = ax88179_stop,
-+      .flags = FLAG_ETHER | FLAG_FRAMING_AX,
-+      .rx_fixup = ax88179_rx_fixup,
-+      .tx_fixup = ax88179_tx_fixup,
-+};
-+
-+static const struct driver_info ax88178a_info = {
-+      .description = "ASIX AX88178A USB 2.0 Gigabit Ethernet",
-+      .bind = ax88179_bind,
-+      .unbind = ax88179_unbind,
-+      .status = ax88179_status,
-+      .link_reset = ax88179_link_reset,
-+      .reset = ax88179_reset,
-+      .stop = ax88179_stop,
-+      .flags = FLAG_ETHER | FLAG_FRAMING_AX,
-+      .rx_fixup = ax88179_rx_fixup,
-+      .tx_fixup = ax88179_tx_fixup,
-+};
-+
-+static const struct driver_info dlink_dub1312_info = {
-+      .description = "D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter",
-+      .bind = ax88179_bind,
-+      .unbind = ax88179_unbind,
-+      .status = ax88179_status,
-+      .link_reset = ax88179_link_reset,
-+      .reset = ax88179_reset,
-+      .stop = ax88179_stop,
-+      .flags = FLAG_ETHER | FLAG_FRAMING_AX,
-+      .rx_fixup = ax88179_rx_fixup,
-+      .tx_fixup = ax88179_tx_fixup,
-+};
-+
-+static const struct driver_info sitecom_info = {
-+      .description = "Sitecom USB 3.0 to Gigabit Adapter",
-+      .bind = ax88179_bind,
-+      .unbind = ax88179_unbind,
-+      .status = ax88179_status,
-+      .link_reset = ax88179_link_reset,
-+      .reset = ax88179_reset,
-+      .stop = ax88179_stop,
-+      .flags = FLAG_ETHER | FLAG_FRAMING_AX,
-+      .rx_fixup = ax88179_rx_fixup,
-+      .tx_fixup = ax88179_tx_fixup,
-+};
-+
-+static const struct driver_info samsung_info = {
-+      .description = "Samsung USB Ethernet Adapter",
-+      .bind = ax88179_bind,
-+      .unbind = ax88179_unbind,
-+      .status = ax88179_status,
-+      .link_reset = ax88179_link_reset,
-+      .reset = ax88179_reset,
-+      .stop = ax88179_stop,
-+      .flags = FLAG_ETHER | FLAG_FRAMING_AX,
-+      .rx_fixup = ax88179_rx_fixup,
-+      .tx_fixup = ax88179_tx_fixup,
-+};
-+
-+static const struct driver_info lenovo_info = {
-+      .description = "Lenovo OneLinkDock Gigabit LAN",
-+      .bind = ax88179_bind,
-+      .unbind = ax88179_unbind,
-+      .status = ax88179_status,
-+      .link_reset = ax88179_link_reset,
-+      .reset = ax88179_reset,
-+      .stop = ax88179_stop,
-+      .flags = FLAG_ETHER | FLAG_FRAMING_AX,
-+      .rx_fixup = ax88179_rx_fixup,
-+      .tx_fixup = ax88179_tx_fixup,
-+};
-+
-+static const struct usb_device_id products[] = {
-+{
-+      /* ASIX AX88179 10/100/1000 */
-+      USB_DEVICE(0x0b95, 0x1790),
-+      .driver_info = (unsigned long)&ax88179_info,
-+}, {
-+      /* ASIX AX88178A 10/100/1000 */
-+      USB_DEVICE(0x0b95, 0x178a),
-+      .driver_info = (unsigned long)&ax88178a_info,
-+}, {
-+      /* D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter */
-+      USB_DEVICE(0x2001, 0x4a00),
-+      .driver_info = (unsigned long)&dlink_dub1312_info,
-+}, {
-+      /* Sitecom USB 3.0 to Gigabit Adapter */
-+      USB_DEVICE(0x0df6, 0x0072),
-+      .driver_info = (unsigned long)&sitecom_info,
-+}, {
-+      /* Samsung USB Ethernet Adapter */
-+      USB_DEVICE(0x04e8, 0xa100),
-+      .driver_info = (unsigned long)&samsung_info,
-+}, {
-+      /* Lenovo OneLinkDock Gigabit LAN */
-+      USB_DEVICE(0x17ef, 0x304b),
-+      .driver_info = (unsigned long)&lenovo_info,
-+},
-+      { },
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver ax88179_178a_driver = {
-+      .name =         "ax88179_178a",
-+      .id_table =     products,
-+      .probe =        usbnet_probe,
-+      .suspend =      ax88179_suspend,
-+      .resume =       ax88179_resume,
-+      .reset_resume = ax88179_resume,
-+      .disconnect =   usbnet_disconnect,
-+      .supports_autosuspend = 1,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(ax88179_178a_driver);
-+
-+MODULE_DESCRIPTION("ASIX AX88179/178A based USB 3.0/2.0 Gigabit Ethernet Devices");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/catc.c backports-4.2.6-1/drivers/net/usb/catc.c
---- backports-4.2.6-1.org/drivers/net/usb/catc.c       1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/catc.c   2016-06-28 14:35:17.975307221 +0200
-@@ -0,0 +1,965 @@
-+/*
-+ *  Copyright (c) 2001 Vojtech Pavlik
-+ *
-+ *  CATC EL1210A NetMate USB Ethernet driver
-+ *
-+ *  Sponsored by SuSE
-+ *
-+ *  Based on the work of
-+ *            Donald Becker
-+ * 
-+ *  Old chipset support added by Simon Evans <spse@secret.org.uk> 2002
-+ *    - adds support for Belkin F5U011
-+ */
-+
-+/*
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ * 
-+ * Should you need to contact me, the author, you can do so either by
-+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
-+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/string.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#include <linux/spinlock.h>
-+#include <linux/ethtool.h>
-+#include <linux/crc32.h>
-+#include <linux/bitops.h>
-+#include <linux/gfp.h>
-+#include <asm/uaccess.h>
-+
-+#undef DEBUG
-+
-+#include <linux/usb.h>
-+
-+/*
-+ * Version information.
-+ */
-+
-+#define DRIVER_VERSION "v2.8"
-+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
-+#define DRIVER_DESC "CATC EL1210A NetMate USB Ethernet driver"
-+#define SHORT_DRIVER_DESC "EL1210A NetMate USB Ethernet"
-+
-+MODULE_AUTHOR(DRIVER_AUTHOR);
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_LICENSE("GPL");
-+
-+static const char driver_name[] = "catc";
-+
-+/*
-+ * Some defines.
-+ */ 
-+
-+#define STATS_UPDATE          (HZ)    /* Time between stats updates */
-+#define TX_TIMEOUT            (5*HZ)  /* Max time the queue can be stopped */
-+#define PKT_SZ                        1536    /* Max Ethernet packet size */
-+#define RX_MAX_BURST          15      /* Max packets per rx buffer (> 0, < 16) */
-+#define TX_MAX_BURST          15      /* Max full sized packets per tx buffer (> 0) */
-+#define CTRL_QUEUE            16      /* Max control requests in flight (power of two) */
-+#define RX_PKT_SZ             1600    /* Max size of receive packet for F5U011 */
-+
-+/*
-+ * Control requests.
-+ */
-+
-+enum control_requests {
-+      ReadMem =       0xf1,
-+      GetMac =        0xf2,
-+      Reset =         0xf4,
-+      SetMac =        0xf5,
-+      SetRxMode =     0xf5,  /* F5U011 only */
-+      WriteROM =      0xf8,
-+      SetReg =        0xfa,
-+      GetReg =        0xfb,
-+      WriteMem =      0xfc,
-+      ReadROM =       0xfd,
-+};
-+
-+/*
-+ * Registers.
-+ */
-+
-+enum register_offsets {
-+      TxBufCount =    0x20,
-+      RxBufCount =    0x21,
-+      OpModes =       0x22,
-+      TxQed =         0x23,
-+      RxQed =         0x24,
-+      MaxBurst =      0x25,
-+      RxUnit =        0x60,
-+      EthStatus =     0x61,
-+      StationAddr0 =  0x67,
-+      EthStats =      0x69,
-+      LEDCtrl =       0x81,
-+};
-+
-+enum eth_stats {
-+      TxSingleColl =  0x00,
-+        TxMultiColl = 0x02,
-+        TxExcessColl =        0x04,
-+        RxFramErr =   0x06,
-+};
-+
-+enum op_mode_bits {
-+      Op3MemWaits =   0x03,
-+      OpLenInclude =  0x08,
-+      OpRxMerge =     0x10,
-+      OpTxMerge =     0x20,
-+      OpWin95bugfix = 0x40,
-+      OpLoopback =    0x80,
-+};
-+
-+enum rx_filter_bits {
-+      RxEnable =      0x01,
-+      RxPolarity =    0x02,
-+      RxForceOK =     0x04,
-+      RxMultiCast =   0x08,
-+      RxPromisc =     0x10,
-+      AltRxPromisc =  0x20, /* F5U011 uses different bit */
-+};
-+
-+enum led_values {
-+      LEDFast =       0x01,
-+      LEDSlow =       0x02,
-+      LEDFlash =      0x03,
-+      LEDPulse =      0x04,
-+      LEDLink =       0x08,
-+};
-+
-+enum link_status {
-+      LinkNoChange = 0,
-+      LinkGood     = 1,
-+      LinkBad      = 2
-+};
-+
-+/*
-+ * The catc struct.
-+ */
-+
-+#define CTRL_RUNNING  0
-+#define RX_RUNNING    1
-+#define TX_RUNNING    2
-+
-+struct catc {
-+      struct net_device *netdev;
-+      struct usb_device *usbdev;
-+
-+      unsigned long flags;
-+
-+      unsigned int tx_ptr, tx_idx;
-+      unsigned int ctrl_head, ctrl_tail;
-+      spinlock_t tx_lock, ctrl_lock;
-+
-+      u8 tx_buf[2][TX_MAX_BURST * (PKT_SZ + 2)];
-+      u8 rx_buf[RX_MAX_BURST * (PKT_SZ + 2)];
-+      u8 irq_buf[2];
-+      u8 ctrl_buf[64];
-+      struct usb_ctrlrequest ctrl_dr;
-+
-+      struct timer_list timer;
-+      u8 stats_buf[8];
-+      u16 stats_vals[4];
-+      unsigned long last_stats;
-+
-+      u8 multicast[64];
-+
-+      struct ctrl_queue {
-+              u8 dir;
-+              u8 request;
-+              u16 value;
-+              u16 index;
-+              void *buf;
-+              int len;
-+              void (*callback)(struct catc *catc, struct ctrl_queue *q);
-+      } ctrl_queue[CTRL_QUEUE];
-+
-+      struct urb *tx_urb, *rx_urb, *irq_urb, *ctrl_urb;
-+
-+      u8 is_f5u011;   /* Set if device is an F5U011 */
-+      u8 rxmode[2];   /* Used for F5U011 */
-+      atomic_t recq_sz; /* Used for F5U011 - counter of waiting rx packets */
-+};
-+
-+/*
-+ * Useful macros.
-+ */
-+
-+#define catc_get_mac(catc, mac)                               catc_ctrl_msg(catc, USB_DIR_IN,  GetMac, 0, 0, mac,  6)
-+#define catc_reset(catc)                              catc_ctrl_msg(catc, USB_DIR_OUT, Reset, 0, 0, NULL, 0)
-+#define catc_set_reg(catc, reg, val)                  catc_ctrl_msg(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0)
-+#define catc_get_reg(catc, reg, buf)                  catc_ctrl_msg(catc, USB_DIR_IN,  GetReg, 0, reg, buf, 1)
-+#define catc_write_mem(catc, addr, buf, size)         catc_ctrl_msg(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size)
-+#define catc_read_mem(catc, addr, buf, size)          catc_ctrl_msg(catc, USB_DIR_IN,  ReadMem, 0, addr, buf, size)
-+
-+#define f5u011_rxmode(catc, rxmode)                   catc_ctrl_msg(catc, USB_DIR_OUT, SetRxMode, 0, 1, rxmode, 2)
-+#define f5u011_rxmode_async(catc, rxmode)             catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 1, &rxmode, 2, NULL)
-+#define f5u011_mchash_async(catc, hash)                       catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 2, &hash, 8, NULL)
-+
-+#define catc_set_reg_async(catc, reg, val)            catc_ctrl_async(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0, NULL)
-+#define catc_get_reg_async(catc, reg, cb)             catc_ctrl_async(catc, USB_DIR_IN, GetReg, 0, reg, NULL, 1, cb)
-+#define catc_write_mem_async(catc, addr, buf, size)   catc_ctrl_async(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size, NULL)
-+
-+/*
-+ * Receive routines.
-+ */
-+
-+static void catc_rx_done(struct urb *urb)
-+{
-+      struct catc *catc = urb->context;
-+      u8 *pkt_start = urb->transfer_buffer;
-+      struct sk_buff *skb;
-+      int pkt_len, pkt_offset = 0;
-+      int status = urb->status;
-+
-+      if (!catc->is_f5u011) {
-+              clear_bit(RX_RUNNING, &catc->flags);
-+              pkt_offset = 2;
-+      }
-+
-+      if (status) {
-+              dev_dbg(&urb->dev->dev, "rx_done, status %d, length %d\n",
-+                      status, urb->actual_length);
-+              return;
-+      }
-+
-+      do {
-+              if(!catc->is_f5u011) {
-+                      pkt_len = le16_to_cpup((__le16*)pkt_start);
-+                      if (pkt_len > urb->actual_length) {
-+                              catc->netdev->stats.rx_length_errors++;
-+                              catc->netdev->stats.rx_errors++;
-+                              break;
-+                      }
-+              } else {
-+                      pkt_len = urb->actual_length;
-+              }
-+
-+              if (!(skb = dev_alloc_skb(pkt_len)))
-+                      return;
-+
-+              skb_copy_to_linear_data(skb, pkt_start + pkt_offset, pkt_len);
-+              skb_put(skb, pkt_len);
-+
-+              skb->protocol = eth_type_trans(skb, catc->netdev);
-+              netif_rx(skb);
-+
-+              catc->netdev->stats.rx_packets++;
-+              catc->netdev->stats.rx_bytes += pkt_len;
-+
-+              /* F5U011 only does one packet per RX */
-+              if (catc->is_f5u011)
-+                      break;
-+              pkt_start += (((pkt_len + 1) >> 6) + 1) << 6;
-+
-+      } while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length);
-+
-+      if (catc->is_f5u011) {
-+              if (atomic_read(&catc->recq_sz)) {
-+                      int state;
-+                      atomic_dec(&catc->recq_sz);
-+                      netdev_dbg(catc->netdev, "getting extra packet\n");
-+                      urb->dev = catc->usbdev;
-+                      if ((state = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-+                              netdev_dbg(catc->netdev,
-+                                         "submit(rx_urb) status %d\n", state);
-+                      }
-+              } else {
-+                      clear_bit(RX_RUNNING, &catc->flags);
-+              }
-+      }
-+}
-+
-+static void catc_irq_done(struct urb *urb)
-+{
-+      struct catc *catc = urb->context;
-+      u8 *data = urb->transfer_buffer;
-+      int status = urb->status;
-+      unsigned int hasdata = 0, linksts = LinkNoChange;
-+      int res;
-+
-+      if (!catc->is_f5u011) {
-+              hasdata = data[1] & 0x80;
-+              if (data[1] & 0x40)
-+                      linksts = LinkGood;
-+              else if (data[1] & 0x20)
-+                      linksts = LinkBad;
-+      } else {
-+              hasdata = (unsigned int)(be16_to_cpup((__be16*)data) & 0x0fff);
-+              if (data[0] == 0x90)
-+                      linksts = LinkGood;
-+              else if (data[0] == 0xA0)
-+                      linksts = LinkBad;
-+      }
-+
-+      switch (status) {
-+      case 0:                 /* success */
-+              break;
-+      case -ECONNRESET:       /* unlink */
-+      case -ENOENT:
-+      case -ESHUTDOWN:
-+              return;
-+      /* -EPIPE:  should clear the halt */
-+      default:                /* error */
-+              dev_dbg(&urb->dev->dev,
-+                      "irq_done, status %d, data %02x %02x.\n",
-+                      status, data[0], data[1]);
-+              goto resubmit;
-+      }
-+
-+      if (linksts == LinkGood) {
-+              netif_carrier_on(catc->netdev);
-+              netdev_dbg(catc->netdev, "link ok\n");
-+      }
-+
-+      if (linksts == LinkBad) {
-+              netif_carrier_off(catc->netdev);
-+              netdev_dbg(catc->netdev, "link bad\n");
-+      }
-+
-+      if (hasdata) {
-+              if (test_and_set_bit(RX_RUNNING, &catc->flags)) {
-+                      if (catc->is_f5u011)
-+                              atomic_inc(&catc->recq_sz);
-+              } else {
-+                      catc->rx_urb->dev = catc->usbdev;
-+                      if ((res = usb_submit_urb(catc->rx_urb, GFP_ATOMIC)) < 0) {
-+                              dev_err(&catc->usbdev->dev,
-+                                      "submit(rx_urb) status %d\n", res);
-+                      }
-+              } 
-+      }
-+resubmit:
-+      res = usb_submit_urb (urb, GFP_ATOMIC);
-+      if (res)
-+              dev_err(&catc->usbdev->dev,
-+                      "can't resubmit intr, %s-%s, status %d\n",
-+                      catc->usbdev->bus->bus_name,
-+                      catc->usbdev->devpath, res);
-+}
-+
-+/*
-+ * Transmit routines.
-+ */
-+
-+static int catc_tx_run(struct catc *catc)
-+{
-+      int status;
-+
-+      if (catc->is_f5u011)
-+              catc->tx_ptr = (catc->tx_ptr + 63) & ~63;
-+
-+      catc->tx_urb->transfer_buffer_length = catc->tx_ptr;
-+      catc->tx_urb->transfer_buffer = catc->tx_buf[catc->tx_idx];
-+      catc->tx_urb->dev = catc->usbdev;
-+
-+      if ((status = usb_submit_urb(catc->tx_urb, GFP_ATOMIC)) < 0)
-+              dev_err(&catc->usbdev->dev, "submit(tx_urb), status %d\n",
-+                      status);
-+
-+      catc->tx_idx = !catc->tx_idx;
-+      catc->tx_ptr = 0;
-+
-+      catc->netdev->trans_start = jiffies;
-+      return status;
-+}
-+
-+static void catc_tx_done(struct urb *urb)
-+{
-+      struct catc *catc = urb->context;
-+      unsigned long flags;
-+      int r, status = urb->status;
-+
-+      if (status == -ECONNRESET) {
-+              dev_dbg(&urb->dev->dev, "Tx Reset.\n");
-+              urb->status = 0;
-+              catc->netdev->trans_start = jiffies;
-+              catc->netdev->stats.tx_errors++;
-+              clear_bit(TX_RUNNING, &catc->flags);
-+              netif_wake_queue(catc->netdev);
-+              return;
-+      }
-+
-+      if (status) {
-+              dev_dbg(&urb->dev->dev, "tx_done, status %d, length %d\n",
-+                      status, urb->actual_length);
-+              return;
-+      }
-+
-+      spin_lock_irqsave(&catc->tx_lock, flags);
-+
-+      if (catc->tx_ptr) {
-+              r = catc_tx_run(catc);
-+              if (unlikely(r < 0))
-+                      clear_bit(TX_RUNNING, &catc->flags);
-+      } else {
-+              clear_bit(TX_RUNNING, &catc->flags);
-+      }
-+
-+      netif_wake_queue(catc->netdev);
-+
-+      spin_unlock_irqrestore(&catc->tx_lock, flags);
-+}
-+
-+static netdev_tx_t catc_start_xmit(struct sk_buff *skb,
-+                                       struct net_device *netdev)
-+{
-+      struct catc *catc = netdev_priv(netdev);
-+      unsigned long flags;
-+      int r = 0;
-+      char *tx_buf;
-+
-+      spin_lock_irqsave(&catc->tx_lock, flags);
-+
-+      catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
-+      tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
-+      if (catc->is_f5u011)
-+              *(__be16 *)tx_buf = cpu_to_be16(skb->len);
-+      else
-+              *(__le16 *)tx_buf = cpu_to_le16(skb->len);
-+      skb_copy_from_linear_data(skb, tx_buf + 2, skb->len);
-+      catc->tx_ptr += skb->len + 2;
-+
-+      if (!test_and_set_bit(TX_RUNNING, &catc->flags)) {
-+              r = catc_tx_run(catc);
-+              if (r < 0)
-+                      clear_bit(TX_RUNNING, &catc->flags);
-+      }
-+
-+      if ((catc->is_f5u011 && catc->tx_ptr) ||
-+          (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))))
-+              netif_stop_queue(netdev);
-+
-+      spin_unlock_irqrestore(&catc->tx_lock, flags);
-+
-+      if (r >= 0) {
-+              catc->netdev->stats.tx_bytes += skb->len;
-+              catc->netdev->stats.tx_packets++;
-+      }
-+
-+      dev_kfree_skb(skb);
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+static void catc_tx_timeout(struct net_device *netdev)
-+{
-+      struct catc *catc = netdev_priv(netdev);
-+
-+      dev_warn(&netdev->dev, "Transmit timed out.\n");
-+      usb_unlink_urb(catc->tx_urb);
-+}
-+
-+/*
-+ * Control messages.
-+ */
-+
-+static int catc_ctrl_msg(struct catc *catc, u8 dir, u8 request, u16 value, u16 index, void *buf, int len)
-+{
-+        int retval = usb_control_msg(catc->usbdev,
-+              dir ? usb_rcvctrlpipe(catc->usbdev, 0) : usb_sndctrlpipe(catc->usbdev, 0),
-+               request, 0x40 | dir, value, index, buf, len, 1000);
-+        return retval < 0 ? retval : 0;
-+}
-+
-+static void catc_ctrl_run(struct catc *catc)
-+{
-+      struct ctrl_queue *q = catc->ctrl_queue + catc->ctrl_tail;
-+      struct usb_device *usbdev = catc->usbdev;
-+      struct urb *urb = catc->ctrl_urb;
-+      struct usb_ctrlrequest *dr = &catc->ctrl_dr;
-+      int status;
-+
-+      dr->bRequest = q->request;
-+      dr->bRequestType = 0x40 | q->dir;
-+      dr->wValue = cpu_to_le16(q->value);
-+      dr->wIndex = cpu_to_le16(q->index);
-+      dr->wLength = cpu_to_le16(q->len);
-+
-+        urb->pipe = q->dir ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0);
-+      urb->transfer_buffer_length = q->len;
-+      urb->transfer_buffer = catc->ctrl_buf;
-+      urb->setup_packet = (void *) dr;
-+      urb->dev = usbdev;
-+
-+      if (!q->dir && q->buf && q->len)
-+              memcpy(catc->ctrl_buf, q->buf, q->len);
-+
-+      if ((status = usb_submit_urb(catc->ctrl_urb, GFP_ATOMIC)))
-+              dev_err(&catc->usbdev->dev, "submit(ctrl_urb) status %d\n",
-+                      status);
-+}
-+
-+static void catc_ctrl_done(struct urb *urb)
-+{
-+      struct catc *catc = urb->context;
-+      struct ctrl_queue *q;
-+      unsigned long flags;
-+      int status = urb->status;
-+
-+      if (status)
-+              dev_dbg(&urb->dev->dev, "ctrl_done, status %d, len %d.\n",
-+                      status, urb->actual_length);
-+
-+      spin_lock_irqsave(&catc->ctrl_lock, flags);
-+
-+      q = catc->ctrl_queue + catc->ctrl_tail;
-+
-+      if (q->dir) {
-+              if (q->buf && q->len)
-+                      memcpy(q->buf, catc->ctrl_buf, q->len);
-+              else
-+                      q->buf = catc->ctrl_buf;
-+      }
-+
-+      if (q->callback)
-+              q->callback(catc, q);
-+
-+      catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1);
-+
-+      if (catc->ctrl_head != catc->ctrl_tail)
-+              catc_ctrl_run(catc);
-+      else
-+              clear_bit(CTRL_RUNNING, &catc->flags);
-+
-+      spin_unlock_irqrestore(&catc->ctrl_lock, flags);
-+}
-+
-+static int catc_ctrl_async(struct catc *catc, u8 dir, u8 request, u16 value,
-+      u16 index, void *buf, int len, void (*callback)(struct catc *catc, struct ctrl_queue *q))
-+{
-+      struct ctrl_queue *q;
-+      int retval = 0;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&catc->ctrl_lock, flags);
-+      
-+      q = catc->ctrl_queue + catc->ctrl_head;
-+
-+      q->dir = dir;
-+      q->request = request;
-+      q->value = value;
-+      q->index = index;
-+      q->buf = buf;
-+      q->len = len;
-+      q->callback = callback;
-+
-+      catc->ctrl_head = (catc->ctrl_head + 1) & (CTRL_QUEUE - 1);
-+
-+      if (catc->ctrl_head == catc->ctrl_tail) {
-+              dev_err(&catc->usbdev->dev, "ctrl queue full\n");
-+              catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1);
-+              retval = -1;
-+      }
-+
-+      if (!test_and_set_bit(CTRL_RUNNING, &catc->flags))
-+              catc_ctrl_run(catc);
-+
-+      spin_unlock_irqrestore(&catc->ctrl_lock, flags);
-+
-+      return retval;
-+}
-+
-+/*
-+ * Statistics.
-+ */
-+
-+static void catc_stats_done(struct catc *catc, struct ctrl_queue *q)
-+{
-+      int index = q->index - EthStats;
-+      u16 data, last;
-+
-+      catc->stats_buf[index] = *((char *)q->buf);
-+
-+      if (index & 1)
-+              return;
-+
-+      data = ((u16)catc->stats_buf[index] << 8) | catc->stats_buf[index + 1];
-+      last = catc->stats_vals[index >> 1];
-+
-+      switch (index) {
-+              case TxSingleColl:
-+              case TxMultiColl:
-+                      catc->netdev->stats.collisions += data - last;
-+                      break;
-+              case TxExcessColl:
-+                      catc->netdev->stats.tx_aborted_errors += data - last;
-+                      catc->netdev->stats.tx_errors += data - last;
-+                      break;
-+              case RxFramErr:
-+                      catc->netdev->stats.rx_frame_errors += data - last;
-+                      catc->netdev->stats.rx_errors += data - last;
-+                      break;
-+      }
-+
-+      catc->stats_vals[index >> 1] = data;
-+}
-+
-+static void catc_stats_timer(unsigned long data)
-+{
-+      struct catc *catc = (void *) data;
-+      int i;
-+
-+      for (i = 0; i < 8; i++)
-+              catc_get_reg_async(catc, EthStats + 7 - i, catc_stats_done);
-+
-+      mod_timer(&catc->timer, jiffies + STATS_UPDATE);
-+}
-+
-+/*
-+ * Receive modes. Broadcast, Multicast, Promisc.
-+ */
-+
-+static void catc_multicast(unsigned char *addr, u8 *multicast)
-+{
-+      u32 crc;
-+
-+      crc = ether_crc_le(6, addr);
-+      multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
-+}
-+
-+static void catc_set_multicast_list(struct net_device *netdev)
-+{
-+      struct catc *catc = netdev_priv(netdev);
-+      struct netdev_hw_addr *ha;
-+      u8 broadcast[ETH_ALEN];
-+      u8 rx = RxEnable | RxPolarity | RxMultiCast;
-+
-+      eth_broadcast_addr(broadcast);
-+      memset(catc->multicast, 0, 64);
-+
-+      catc_multicast(broadcast, catc->multicast);
-+      catc_multicast(netdev->dev_addr, catc->multicast);
-+
-+      if (netdev->flags & IFF_PROMISC) {
-+              memset(catc->multicast, 0xff, 64);
-+              rx |= (!catc->is_f5u011) ? RxPromisc : AltRxPromisc;
-+      } 
-+
-+      if (netdev->flags & IFF_ALLMULTI) {
-+              memset(catc->multicast, 0xff, 64);
-+      } else {
-+              netdev_for_each_mc_addr(ha, netdev) {
-+                      u32 crc = ether_crc_le(6, ha->addr);
-+                      if (!catc->is_f5u011) {
-+                              catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
-+                      } else {
-+                              catc->multicast[7-(crc >> 29)] |= 1 << ((crc >> 26) & 7);
-+                      }
-+              }
-+      }
-+      if (!catc->is_f5u011) {
-+              catc_set_reg_async(catc, RxUnit, rx);
-+              catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);
-+      } else {
-+              f5u011_mchash_async(catc, catc->multicast);
-+              if (catc->rxmode[0] != rx) {
-+                      catc->rxmode[0] = rx;
-+                      netdev_dbg(catc->netdev,
-+                                 "Setting RX mode to %2.2X %2.2X\n",
-+                                 catc->rxmode[0], catc->rxmode[1]);
-+                      f5u011_rxmode_async(catc, catc->rxmode);
-+              }
-+      }
-+}
-+
-+static void catc_get_drvinfo(struct net_device *dev,
-+                           struct ethtool_drvinfo *info)
-+{
-+      struct catc *catc = netdev_priv(dev);
-+      strlcpy(info->driver, driver_name, sizeof(info->driver));
-+      strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
-+      usb_make_path(catc->usbdev, info->bus_info, sizeof(info->bus_info));
-+}
-+
-+static int catc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-+{
-+      struct catc *catc = netdev_priv(dev);
-+      if (!catc->is_f5u011)
-+              return -EOPNOTSUPP;
-+
-+      cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_TP;
-+      cmd->advertising = ADVERTISED_10baseT_Half | ADVERTISED_TP;
-+      ethtool_cmd_speed_set(cmd, SPEED_10);
-+      cmd->duplex = DUPLEX_HALF;
-+      cmd->port = PORT_TP; 
-+      cmd->phy_address = 0;
-+      cmd->transceiver = XCVR_INTERNAL;
-+      cmd->autoneg = AUTONEG_DISABLE;
-+      cmd->maxtxpkt = 1;
-+      cmd->maxrxpkt = 1;
-+      return 0;
-+}
-+
-+static const struct ethtool_ops ops = {
-+      .get_drvinfo = catc_get_drvinfo,
-+      .get_settings = catc_get_settings,
-+      .get_link = ethtool_op_get_link
-+};
-+
-+/*
-+ * Open, close.
-+ */
-+
-+static int catc_open(struct net_device *netdev)
-+{
-+      struct catc *catc = netdev_priv(netdev);
-+      int status;
-+
-+      catc->irq_urb->dev = catc->usbdev;
-+      if ((status = usb_submit_urb(catc->irq_urb, GFP_KERNEL)) < 0) {
-+              dev_err(&catc->usbdev->dev, "submit(irq_urb) status %d\n",
-+                      status);
-+              return -1;
-+      }
-+
-+      netif_start_queue(netdev);
-+
-+      if (!catc->is_f5u011)
-+              mod_timer(&catc->timer, jiffies + STATS_UPDATE);
-+
-+      return 0;
-+}
-+
-+static int catc_stop(struct net_device *netdev)
-+{
-+      struct catc *catc = netdev_priv(netdev);
-+
-+      netif_stop_queue(netdev);
-+
-+      if (!catc->is_f5u011)
-+              del_timer_sync(&catc->timer);
-+
-+      usb_kill_urb(catc->rx_urb);
-+      usb_kill_urb(catc->tx_urb);
-+      usb_kill_urb(catc->irq_urb);
-+      usb_kill_urb(catc->ctrl_urb);
-+
-+      return 0;
-+}
-+
-+static const struct net_device_ops catc_netdev_ops = {
-+      .ndo_open               = catc_open,
-+      .ndo_stop               = catc_stop,
-+      .ndo_start_xmit         = catc_start_xmit,
-+
-+      .ndo_tx_timeout         = catc_tx_timeout,
-+      .ndo_set_rx_mode        = catc_set_multicast_list,
-+      .ndo_change_mtu         = eth_change_mtu,
-+      .ndo_set_mac_address    = eth_mac_addr,
-+      .ndo_validate_addr      = eth_validate_addr,
-+};
-+
-+/*
-+ * USB probe, disconnect.
-+ */
-+
-+static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id)
-+{
-+      struct device *dev = &intf->dev;
-+      struct usb_device *usbdev = interface_to_usbdev(intf);
-+      struct net_device *netdev;
-+      struct catc *catc;
-+      u8 broadcast[ETH_ALEN];
-+      int i, pktsz;
-+
-+      if (usb_set_interface(usbdev,
-+                      intf->altsetting->desc.bInterfaceNumber, 1)) {
-+              dev_err(dev, "Can't set altsetting 1.\n");
-+              return -EIO;
-+      }
-+
-+      netdev = alloc_etherdev(sizeof(struct catc));
-+      if (!netdev)
-+              return -ENOMEM;
-+
-+      catc = netdev_priv(netdev);
-+
-+      netdev->netdev_ops = &catc_netdev_ops;
-+      netdev->watchdog_timeo = TX_TIMEOUT;
-+      netdev->ethtool_ops = &ops;
-+
-+      catc->usbdev = usbdev;
-+      catc->netdev = netdev;
-+
-+      spin_lock_init(&catc->tx_lock);
-+      spin_lock_init(&catc->ctrl_lock);
-+
-+      init_timer(&catc->timer);
-+      catc->timer.data = (long) catc;
-+      catc->timer.function = catc_stats_timer;
-+
-+      catc->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      catc->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      catc->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      catc->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if ((!catc->ctrl_urb) || (!catc->tx_urb) || 
-+          (!catc->rx_urb) || (!catc->irq_urb)) {
-+              dev_err(&intf->dev, "No free urbs available.\n");
-+              usb_free_urb(catc->ctrl_urb);
-+              usb_free_urb(catc->tx_urb);
-+              usb_free_urb(catc->rx_urb);
-+              usb_free_urb(catc->irq_urb);
-+              free_netdev(netdev);
-+              return -ENOMEM;
-+      }
-+
-+      /* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
-+      if (le16_to_cpu(usbdev->descriptor.idVendor) == 0x0423 && 
-+          le16_to_cpu(usbdev->descriptor.idProduct) == 0xa &&
-+          le16_to_cpu(catc->usbdev->descriptor.bcdDevice) == 0x0130) {
-+              dev_dbg(dev, "Testing for f5u011\n");
-+              catc->is_f5u011 = 1;            
-+              atomic_set(&catc->recq_sz, 0);
-+              pktsz = RX_PKT_SZ;
-+      } else {
-+              pktsz = RX_MAX_BURST * (PKT_SZ + 2);
-+      }
-+      
-+      usb_fill_control_urb(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),
-+              NULL, NULL, 0, catc_ctrl_done, catc);
-+
-+      usb_fill_bulk_urb(catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1),
-+              NULL, 0, catc_tx_done, catc);
-+
-+      usb_fill_bulk_urb(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),
-+              catc->rx_buf, pktsz, catc_rx_done, catc);
-+
-+      usb_fill_int_urb(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),
-+                catc->irq_buf, 2, catc_irq_done, catc, 1);
-+
-+      if (!catc->is_f5u011) {
-+              dev_dbg(dev, "Checking memory size\n");
-+
-+              i = 0x12345678;
-+              catc_write_mem(catc, 0x7a80, &i, 4);
-+              i = 0x87654321; 
-+              catc_write_mem(catc, 0xfa80, &i, 4);
-+              catc_read_mem(catc, 0x7a80, &i, 4);
-+        
-+              switch (i) {
-+              case 0x12345678:
-+                      catc_set_reg(catc, TxBufCount, 8);
-+                      catc_set_reg(catc, RxBufCount, 32);
-+                      dev_dbg(dev, "64k Memory\n");
-+                      break;
-+              default:
-+                      dev_warn(&intf->dev,
-+                               "Couldn't detect memory size, assuming 32k\n");
-+              case 0x87654321:
-+                      catc_set_reg(catc, TxBufCount, 4);
-+                      catc_set_reg(catc, RxBufCount, 16);
-+                      dev_dbg(dev, "32k Memory\n");
-+                      break;
-+              }
-+        
-+              dev_dbg(dev, "Getting MAC from SEEROM.\n");
-+        
-+              catc_get_mac(catc, netdev->dev_addr);
-+              
-+              dev_dbg(dev, "Setting MAC into registers.\n");
-+        
-+              for (i = 0; i < 6; i++)
-+                      catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);
-+              
-+              dev_dbg(dev, "Filling the multicast list.\n");
-+        
-+              eth_broadcast_addr(broadcast);
-+              catc_multicast(broadcast, catc->multicast);
-+              catc_multicast(netdev->dev_addr, catc->multicast);
-+              catc_write_mem(catc, 0xfa80, catc->multicast, 64);
-+              
-+              dev_dbg(dev, "Clearing error counters.\n");
-+              
-+              for (i = 0; i < 8; i++)
-+                      catc_set_reg(catc, EthStats + i, 0);
-+              catc->last_stats = jiffies;
-+              
-+              dev_dbg(dev, "Enabling.\n");
-+              
-+              catc_set_reg(catc, MaxBurst, RX_MAX_BURST);
-+              catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
-+              catc_set_reg(catc, LEDCtrl, LEDLink);
-+              catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
-+      } else {
-+              dev_dbg(dev, "Performing reset\n");
-+              catc_reset(catc);
-+              catc_get_mac(catc, netdev->dev_addr);
-+              
-+              dev_dbg(dev, "Setting RX Mode\n");
-+              catc->rxmode[0] = RxEnable | RxPolarity | RxMultiCast;
-+              catc->rxmode[1] = 0;
-+              f5u011_rxmode(catc, catc->rxmode);
-+      }
-+      dev_dbg(dev, "Init done.\n");
-+      printk(KERN_INFO "%s: %s USB Ethernet at usb-%s-%s, %pM.\n",
-+             netdev->name, (catc->is_f5u011) ? "Belkin F5U011" : "CATC EL1210A NetMate",
-+             usbdev->bus->bus_name, usbdev->devpath, netdev->dev_addr);
-+      usb_set_intfdata(intf, catc);
-+
-+      SET_NETDEV_DEV(netdev, &intf->dev);
-+      if (register_netdev(netdev) != 0) {
-+              usb_set_intfdata(intf, NULL);
-+              usb_free_urb(catc->ctrl_urb);
-+              usb_free_urb(catc->tx_urb);
-+              usb_free_urb(catc->rx_urb);
-+              usb_free_urb(catc->irq_urb);
-+              free_netdev(netdev);
-+              return -EIO;
-+      }
-+      return 0;
-+}
-+
-+static void catc_disconnect(struct usb_interface *intf)
-+{
-+      struct catc *catc = usb_get_intfdata(intf);
-+
-+      usb_set_intfdata(intf, NULL);
-+      if (catc) {
-+              unregister_netdev(catc->netdev);
-+              usb_free_urb(catc->ctrl_urb);
-+              usb_free_urb(catc->tx_urb);
-+              usb_free_urb(catc->rx_urb);
-+              usb_free_urb(catc->irq_urb);
-+              free_netdev(catc->netdev);
-+      }
-+}
-+
-+/*
-+ * Module functions and tables.
-+ */
-+
-+static struct usb_device_id catc_id_table [] = {
-+      { USB_DEVICE(0x0423, 0xa) },    /* CATC Netmate, Belkin F5U011 */
-+      { USB_DEVICE(0x0423, 0xc) },    /* CATC Netmate II, Belkin F5U111 */
-+      { USB_DEVICE(0x08d1, 0x1) },    /* smartBridges smartNIC */
-+      { }
-+};
-+
-+MODULE_DEVICE_TABLE(usb, catc_id_table);
-+
-+static struct usb_driver catc_driver = {
-+      .name =         driver_name,
-+      .probe =        catc_probe,
-+      .disconnect =   catc_disconnect,
-+      .id_table =     catc_id_table,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(catc_driver);
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/cdc_eem.c backports-4.2.6-1/drivers/net/usb/cdc_eem.c
---- backports-4.2.6-1.org/drivers/net/usb/cdc_eem.c    1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/cdc_eem.c        2016-06-28 14:35:17.975307221 +0200
-@@ -0,0 +1,381 @@
-+/*
-+ * USB CDC EEM network interface driver
-+ * Copyright (C) 2009 Oberthur Technologies
-+ * by Omar Laazimani, Olivier Condemine
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ctype.h>
-+#include <linux/ethtool.h>
-+#include <linux/workqueue.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/crc32.h>
-+#include <linux/usb/cdc.h>
-+#include <linux/usb/usbnet.h>
-+#include <linux/gfp.h>
-+#include <linux/if_vlan.h>
-+
-+
-+/*
-+ * This driver is an implementation of the CDC "Ethernet Emulation
-+ * Model" (EEM) specification, which encapsulates Ethernet frames
-+ * for transport over USB using a simpler USB device model than the
-+ * previous CDC "Ethernet Control Model" (ECM, or "CDC Ethernet").
-+ *
-+ * For details, see www.usb.org/developers/devclass_docs/CDC_EEM10.pdf
-+ *
-+ * This version has been tested with GIGAntIC WuaoW SIM Smart Card on 2.6.24,
-+ * 2.6.27 and 2.6.30rc2 kernel.
-+ * It has also been validated on Openmoko Om 2008.12 (based on 2.6.24 kernel).
-+ * build on 23-April-2009
-+ */
-+
-+#define EEM_HEAD      2               /* 2 byte header */
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static void eem_linkcmd_complete(struct urb *urb)
-+{
-+      dev_kfree_skb(urb->context);
-+      usb_free_urb(urb);
-+}
-+
-+static void eem_linkcmd(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      struct urb              *urb;
-+      int                     status;
-+
-+      urb = usb_alloc_urb(0, GFP_ATOMIC);
-+      if (!urb)
-+              goto fail;
-+
-+      usb_fill_bulk_urb(urb, dev->udev, dev->out,
-+                      skb->data, skb->len, eem_linkcmd_complete, skb);
-+
-+      status = usb_submit_urb(urb, GFP_ATOMIC);
-+      if (status) {
-+              usb_free_urb(urb);
-+fail:
-+              dev_kfree_skb(skb);
-+              netdev_warn(dev->net, "link cmd failure\n");
-+              return;
-+      }
-+}
-+
-+static int eem_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      int status = 0;
-+
-+      status = usbnet_get_endpoints(dev, intf);
-+      if (status < 0) {
-+              usb_set_intfdata(intf, NULL);
-+              usb_driver_release_interface(driver_of(intf), intf);
-+              return status;
-+      }
-+
-+      /* no jumbogram (16K) support for now */
-+
-+      dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN + VLAN_HLEN;
-+      dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
-+
-+      return 0;
-+}
-+
-+/*
-+ * EEM permits packing multiple Ethernet frames into USB transfers
-+ * (a "bundle"), but for TX we don't try to do that.
-+ */
-+static struct sk_buff *eem_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
-+                                     gfp_t flags)
-+{
-+      struct sk_buff  *skb2 = NULL;
-+      u16             len = skb->len;
-+      u32             crc = 0;
-+      int             padlen = 0;
-+
-+      /* When ((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket) is
-+       * zero, stick two bytes of zero length EEM packet on the end.
-+       * Else the framework would add invalid single byte padding,
-+       * since it can't know whether ZLPs will be handled right by
-+       * all the relevant hardware and software.
-+       */
-+      if (!((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket))
-+              padlen += 2;
-+
-+      if (!skb_cloned(skb)) {
-+              int     headroom = skb_headroom(skb);
-+              int     tailroom = skb_tailroom(skb);
-+
-+              if ((tailroom >= ETH_FCS_LEN + padlen) &&
-+                  (headroom >= EEM_HEAD))
-+                      goto done;
-+
-+              if ((headroom + tailroom)
-+                              > (EEM_HEAD + ETH_FCS_LEN + padlen)) {
-+                      skb->data = memmove(skb->head +
-+                                      EEM_HEAD,
-+                                      skb->data,
-+                                      skb->len);
-+                      skb_set_tail_pointer(skb, len);
-+                      goto done;
-+              }
-+      }
-+
-+      skb2 = skb_copy_expand(skb, EEM_HEAD, ETH_FCS_LEN + padlen, flags);
-+      if (!skb2)
-+              return NULL;
-+
-+      dev_kfree_skb_any(skb);
-+      skb = skb2;
-+
-+done:
-+      /* we don't use the "no Ethernet CRC" option */
-+      crc = crc32_le(~0, skb->data, skb->len);
-+      crc = ~crc;
-+
-+      put_unaligned_le32(crc, skb_put(skb, 4));
-+
-+      /* EEM packet header format:
-+       * b0..13:      length of ethernet frame
-+       * b14:         bmCRC (1 == valid Ethernet CRC)
-+       * b15:         bmType (0 == data)
-+       */
-+      len = skb->len;
-+      put_unaligned_le16(BIT(14) | len, skb_push(skb, 2));
-+
-+      /* Bundle a zero length EEM packet if needed */
-+      if (padlen)
-+              put_unaligned_le16(0, skb_put(skb, 2));
-+
-+      return skb;
-+}
-+
-+static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      /*
-+       * Our task here is to strip off framing, leaving skb with one
-+       * data frame for the usbnet framework code to process.  But we
-+       * may have received multiple EEM payloads, or command payloads.
-+       * So we must process _everything_ as if it's a header, except
-+       * maybe the last data payload
-+       *
-+       * REVISIT the framework needs updating so that when we consume
-+       * all payloads (the last or only message was a command, or a
-+       * zero length EEM packet) that is not accounted as an rx_error.
-+       */
-+      do {
-+              struct sk_buff  *skb2 = NULL;
-+              u16             header;
-+              u16             len = 0;
-+
-+              /* incomplete EEM header? */
-+              if (skb->len < EEM_HEAD)
-+                      return 0;
-+
-+              /*
-+               * EEM packet header format:
-+               * b0..14:      EEM type dependent (Data or Command)
-+               * b15:         bmType
-+               */
-+              header = get_unaligned_le16(skb->data);
-+              skb_pull(skb, EEM_HEAD);
-+
-+              /*
-+               * The bmType bit helps to denote when EEM
-+               * packet is data or command :
-+               *      bmType = 0      : EEM data payload
-+               *      bmType = 1      : EEM (link) command
-+               */
-+              if (header & BIT(15)) {
-+                      u16     bmEEMCmd;
-+
-+                      /*
-+                       * EEM (link) command packet:
-+                       * b0..10:      bmEEMCmdParam
-+                       * b11..13:     bmEEMCmd
-+                       * b14:         bmReserved (must be 0)
-+                       * b15:         1 (EEM command)
-+                       */
-+                      if (header & BIT(14)) {
-+                              netdev_dbg(dev->net, "reserved command %04x\n",
-+                                         header);
-+                              continue;
-+                      }
-+
-+                      bmEEMCmd = (header >> 11) & 0x7;
-+                      switch (bmEEMCmd) {
-+
-+                      /* Responding to echo requests is mandatory. */
-+                      case 0:         /* Echo command */
-+                              len = header & 0x7FF;
-+
-+                              /* bogus command? */
-+                              if (skb->len < len)
-+                                      return 0;
-+
-+                              skb2 = skb_clone(skb, GFP_ATOMIC);
-+                              if (unlikely(!skb2))
-+                                      goto next;
-+                              skb_trim(skb2, len);
-+                              put_unaligned_le16(BIT(15) | (1 << 11) | len,
-+                                              skb_push(skb2, 2));
-+                              eem_linkcmd(dev, skb2);
-+                              break;
-+
-+                      /*
-+                       * Host may choose to ignore hints.
-+                       *  - suspend: peripheral ready to suspend
-+                       *  - response: suggest N millisec polling
-+                       *  - response complete: suggest N sec polling
-+                       *
-+                       * Suspend is reported and maybe heeded.
-+                       */
-+                      case 2:         /* Suspend hint */
-+                              usbnet_device_suggests_idle(dev);
-+                              continue;
-+                      case 3:         /* Response hint */
-+                      case 4:         /* Response complete hint */
-+                              continue;
-+
-+                      /*
-+                       * Hosts should never receive host-to-peripheral
-+                       * or reserved command codes; or responses to an
-+                       * echo command we didn't send.
-+                       */
-+                      case 1:         /* Echo response */
-+                      case 5:         /* Tickle */
-+                      default:        /* reserved */
-+                              netdev_warn(dev->net,
-+                                          "unexpected link command %d\n",
-+                                          bmEEMCmd);
-+                              continue;
-+                      }
-+
-+              } else {
-+                      u32     crc, crc2;
-+                      int     is_last;
-+
-+                      /* zero length EEM packet? */
-+                      if (header == 0)
-+                              continue;
-+
-+                      /*
-+                       * EEM data packet header :
-+                       * b0..13:      length of ethernet frame
-+                       * b14:         bmCRC
-+                       * b15:         0 (EEM data)
-+                       */
-+                      len = header & 0x3FFF;
-+
-+                      /* bogus EEM payload? */
-+                      if (skb->len < len)
-+                              return 0;
-+
-+                      /* bogus ethernet frame? */
-+                      if (len < (ETH_HLEN + ETH_FCS_LEN))
-+                              goto next;
-+
-+                      /*
-+                       * Treat the last payload differently: framework
-+                       * code expects our "fixup" to have stripped off
-+                       * headers, so "skb" is a data packet (or error).
-+                       * Else if it's not the last payload, keep "skb"
-+                       * for further processing.
-+                       */
-+                      is_last = (len == skb->len);
-+                      if (is_last)
-+                              skb2 = skb;
-+                      else {
-+                              skb2 = skb_clone(skb, GFP_ATOMIC);
-+                              if (unlikely(!skb2))
-+                                      return 0;
-+                      }
-+
-+                      /*
-+                       * The bmCRC helps to denote when the CRC field in
-+                       * the Ethernet frame contains a calculated CRC:
-+                       *      bmCRC = 1       : CRC is calculated
-+                       *      bmCRC = 0       : CRC = 0xDEADBEEF
-+                       */
-+                      if (header & BIT(14)) {
-+                              crc = get_unaligned_le32(skb2->data
-+                                              + len - ETH_FCS_LEN);
-+                              crc2 = ~crc32_le(~0, skb2->data, skb2->len
-+                                              - ETH_FCS_LEN);
-+                      } else {
-+                              crc = get_unaligned_be32(skb2->data
-+                                              + len - ETH_FCS_LEN);
-+                              crc2 = 0xdeadbeef;
-+                      }
-+                      skb_trim(skb2, len - ETH_FCS_LEN);
-+
-+                      if (is_last)
-+                              return crc == crc2;
-+
-+                      if (unlikely(crc != crc2)) {
-+                              dev->net->stats.rx_errors++;
-+                              dev_kfree_skb_any(skb2);
-+                      } else
-+                              usbnet_skb_return(dev, skb2);
-+              }
-+
-+next:
-+              skb_pull(skb, len);
-+      } while (skb->len);
-+
-+      return 1;
-+}
-+
-+static const struct driver_info eem_info = {
-+      .description =  "CDC EEM Device",
-+      .flags =        FLAG_ETHER | FLAG_POINTTOPOINT,
-+      .bind =         eem_bind,
-+      .rx_fixup =     eem_rx_fixup,
-+      .tx_fixup =     eem_tx_fixup,
-+};
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static const struct usb_device_id products[] = {
-+{
-+      USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_EEM,
-+                      USB_CDC_PROTO_EEM),
-+      .driver_info = (unsigned long) &eem_info,
-+},
-+{
-+      /* EMPTY == end of list */
-+},
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver eem_driver = {
-+      .name =         "cdc_eem",
-+      .id_table =     products,
-+      .probe =        usbnet_probe,
-+      .disconnect =   usbnet_disconnect,
-+      .suspend =      usbnet_suspend,
-+      .resume =       usbnet_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(eem_driver);
-+
-+MODULE_AUTHOR("Omar Laazimani <omar.oberthur@gmail.com>");
-+MODULE_DESCRIPTION("USB CDC EEM");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/cdc-phonet.c backports-4.2.6-1/drivers/net/usb/cdc-phonet.c
---- backports-4.2.6-1.org/drivers/net/usb/cdc-phonet.c 1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/cdc-phonet.c     2016-06-28 14:35:17.975307221 +0200
-@@ -0,0 +1,466 @@
-+/*
-+ * phonet.c -- USB CDC Phonet host driver
-+ *
-+ * Copyright (C) 2008-2009 Nokia Corporation. All rights reserved.
-+ *
-+ * Author: Rémi Denis-Courmont
-+ *
-+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
-+ * 02110-1301 USA
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/mm.h>
-+#include <linux/module.h>
-+#include <linux/gfp.h>
-+#include <linux/usb.h>
-+#include <linux/usb/cdc.h>
-+#include <linux/netdevice.h>
-+#include <linux/if_arp.h>
-+#include <linux/if_phonet.h>
-+#include <linux/phonet.h>
-+
-+#define PN_MEDIA_USB  0x1B
-+
-+static const unsigned rxq_size = 17;
-+
-+struct usbpn_dev {
-+      struct net_device       *dev;
-+
-+      struct usb_interface    *intf, *data_intf;
-+      struct usb_device       *usb;
-+      unsigned int            tx_pipe, rx_pipe;
-+      u8 active_setting;
-+      u8 disconnected;
-+
-+      unsigned                tx_queue;
-+      spinlock_t              tx_lock;
-+
-+      spinlock_t              rx_lock;
-+      struct sk_buff          *rx_skb;
-+      struct urb              *urbs[0];
-+};
-+
-+static void tx_complete(struct urb *req);
-+static void rx_complete(struct urb *req);
-+
-+/*
-+ * Network device callbacks
-+ */
-+static netdev_tx_t usbpn_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      struct usbpn_dev *pnd = netdev_priv(dev);
-+      struct urb *req = NULL;
-+      unsigned long flags;
-+      int err;
-+
-+      if (skb->protocol != htons(ETH_P_PHONET))
-+              goto drop;
-+
-+      req = usb_alloc_urb(0, GFP_ATOMIC);
-+      if (!req)
-+              goto drop;
-+      usb_fill_bulk_urb(req, pnd->usb, pnd->tx_pipe, skb->data, skb->len,
-+                              tx_complete, skb);
-+      req->transfer_flags = URB_ZERO_PACKET;
-+      err = usb_submit_urb(req, GFP_ATOMIC);
-+      if (err) {
-+              usb_free_urb(req);
-+              goto drop;
-+      }
-+
-+      spin_lock_irqsave(&pnd->tx_lock, flags);
-+      pnd->tx_queue++;
-+      if (pnd->tx_queue >= dev->tx_queue_len)
-+              netif_stop_queue(dev);
-+      spin_unlock_irqrestore(&pnd->tx_lock, flags);
-+      return NETDEV_TX_OK;
-+
-+drop:
-+      dev_kfree_skb(skb);
-+      dev->stats.tx_dropped++;
-+      return NETDEV_TX_OK;
-+}
-+
-+static void tx_complete(struct urb *req)
-+{
-+      struct sk_buff *skb = req->context;
-+      struct net_device *dev = skb->dev;
-+      struct usbpn_dev *pnd = netdev_priv(dev);
-+      int status = req->status;
-+
-+      switch (status) {
-+      case 0:
-+              dev->stats.tx_bytes += skb->len;
-+              break;
-+
-+      case -ENOENT:
-+      case -ECONNRESET:
-+      case -ESHUTDOWN:
-+              dev->stats.tx_aborted_errors++;
-+      default:
-+              dev->stats.tx_errors++;
-+              dev_dbg(&dev->dev, "TX error (%d)\n", status);
-+      }
-+      dev->stats.tx_packets++;
-+
-+      spin_lock(&pnd->tx_lock);
-+      pnd->tx_queue--;
-+      netif_wake_queue(dev);
-+      spin_unlock(&pnd->tx_lock);
-+
-+      dev_kfree_skb_any(skb);
-+      usb_free_urb(req);
-+}
-+
-+static int rx_submit(struct usbpn_dev *pnd, struct urb *req, gfp_t gfp_flags)
-+{
-+      struct net_device *dev = pnd->dev;
-+      struct page *page;
-+      int err;
-+
-+      page = __dev_alloc_page(gfp_flags | __GFP_NOMEMALLOC);
-+      if (!page)
-+              return -ENOMEM;
-+
-+      usb_fill_bulk_urb(req, pnd->usb, pnd->rx_pipe, page_address(page),
-+                              PAGE_SIZE, rx_complete, dev);
-+      req->transfer_flags = 0;
-+      err = usb_submit_urb(req, gfp_flags);
-+      if (unlikely(err)) {
-+              dev_dbg(&dev->dev, "RX submit error (%d)\n", err);
-+              put_page(page);
-+      }
-+      return err;
-+}
-+
-+static void rx_complete(struct urb *req)
-+{
-+      struct net_device *dev = req->context;
-+      struct usbpn_dev *pnd = netdev_priv(dev);
-+      struct page *page = virt_to_page(req->transfer_buffer);
-+      struct sk_buff *skb;
-+      unsigned long flags;
-+      int status = req->status;
-+
-+      switch (status) {
-+      case 0:
-+              spin_lock_irqsave(&pnd->rx_lock, flags);
-+              skb = pnd->rx_skb;
-+              if (!skb) {
-+                      skb = pnd->rx_skb = netdev_alloc_skb(dev, 12);
-+                      if (likely(skb)) {
-+                              /* Can't use pskb_pull() on page in IRQ */
-+                              memcpy(skb_put(skb, 1), page_address(page), 1);
-+                              skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
-+                                              page, 1, req->actual_length,
-+                                              PAGE_SIZE);
-+                              page = NULL;
-+                      }
-+              } else {
-+                      skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
-+                                      page, 0, req->actual_length,
-+                                      PAGE_SIZE);
-+                      page = NULL;
-+              }
-+              if (req->actual_length < PAGE_SIZE)
-+                      pnd->rx_skb = NULL; /* Last fragment */
-+              else
-+                      skb = NULL;
-+              spin_unlock_irqrestore(&pnd->rx_lock, flags);
-+              if (skb) {
-+                      skb->protocol = htons(ETH_P_PHONET);
-+                      skb_reset_mac_header(skb);
-+                      __skb_pull(skb, 1);
-+                      skb->dev = dev;
-+                      dev->stats.rx_packets++;
-+                      dev->stats.rx_bytes += skb->len;
-+
-+                      netif_rx(skb);
-+              }
-+              goto resubmit;
-+
-+      case -ENOENT:
-+      case -ECONNRESET:
-+      case -ESHUTDOWN:
-+              req = NULL;
-+              break;
-+
-+      case -EOVERFLOW:
-+              dev->stats.rx_over_errors++;
-+              dev_dbg(&dev->dev, "RX overflow\n");
-+              break;
-+
-+      case -EILSEQ:
-+              dev->stats.rx_crc_errors++;
-+              break;
-+      }
-+
-+      dev->stats.rx_errors++;
-+resubmit:
-+      if (page)
-+              put_page(page);
-+      if (req)
-+              rx_submit(pnd, req, GFP_ATOMIC);
-+}
-+
-+static int usbpn_close(struct net_device *dev);
-+
-+static int usbpn_open(struct net_device *dev)
-+{
-+      struct usbpn_dev *pnd = netdev_priv(dev);
-+      int err;
-+      unsigned i;
-+      unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber;
-+
-+      err = usb_set_interface(pnd->usb, num, pnd->active_setting);
-+      if (err)
-+              return err;
-+
-+      for (i = 0; i < rxq_size; i++) {
-+              struct urb *req = usb_alloc_urb(0, GFP_KERNEL);
-+
-+              if (!req || rx_submit(pnd, req, GFP_KERNEL)) {
-+                      usb_free_urb(req);
-+                      usbpn_close(dev);
-+                      return -ENOMEM;
-+              }
-+              pnd->urbs[i] = req;
-+      }
-+
-+      netif_wake_queue(dev);
-+      return 0;
-+}
-+
-+static int usbpn_close(struct net_device *dev)
-+{
-+      struct usbpn_dev *pnd = netdev_priv(dev);
-+      unsigned i;
-+      unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber;
-+
-+      netif_stop_queue(dev);
-+
-+      for (i = 0; i < rxq_size; i++) {
-+              struct urb *req = pnd->urbs[i];
-+
-+              if (!req)
-+                      continue;
-+              usb_kill_urb(req);
-+              usb_free_urb(req);
-+              pnd->urbs[i] = NULL;
-+      }
-+
-+      return usb_set_interface(pnd->usb, num, !pnd->active_setting);
-+}
-+
-+static int usbpn_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-+{
-+      struct if_phonet_req *req = (struct if_phonet_req *)ifr;
-+
-+      switch (cmd) {
-+      case SIOCPNGAUTOCONF:
-+              req->ifr_phonet_autoconf.device = PN_DEV_PC;
-+              return 0;
-+      }
-+      return -ENOIOCTLCMD;
-+}
-+
-+static int usbpn_set_mtu(struct net_device *dev, int new_mtu)
-+{
-+      if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU))
-+              return -EINVAL;
-+
-+      dev->mtu = new_mtu;
-+      return 0;
-+}
-+
-+static const struct net_device_ops usbpn_ops = {
-+      .ndo_open       = usbpn_open,
-+      .ndo_stop       = usbpn_close,
-+      .ndo_start_xmit = usbpn_xmit,
-+      .ndo_do_ioctl   = usbpn_ioctl,
-+      .ndo_change_mtu = usbpn_set_mtu,
-+};
-+
-+static void usbpn_setup(struct net_device *dev)
-+{
-+      dev->features           = 0;
-+      dev->netdev_ops         = &usbpn_ops,
-+      dev->header_ops         = &phonet_header_ops;
-+      dev->type               = ARPHRD_PHONET;
-+      dev->flags              = IFF_POINTOPOINT | IFF_NOARP;
-+      dev->mtu                = PHONET_MAX_MTU;
-+      dev->hard_header_len    = 1;
-+      dev->dev_addr[0]        = PN_MEDIA_USB;
-+      dev->addr_len           = 1;
-+      dev->tx_queue_len       = 3;
-+
-+      dev->destructor         = free_netdev;
-+}
-+
-+/*
-+ * USB driver callbacks
-+ */
-+static struct usb_device_id usbpn_ids[] = {
-+      {
-+              .match_flags = USB_DEVICE_ID_MATCH_VENDOR
-+                      | USB_DEVICE_ID_MATCH_INT_CLASS
-+                      | USB_DEVICE_ID_MATCH_INT_SUBCLASS,
-+              .idVendor = 0x0421, /* Nokia */
-+              .bInterfaceClass = USB_CLASS_COMM,
-+              .bInterfaceSubClass = 0xFE,
-+      },
-+      { },
-+};
-+
-+MODULE_DEVICE_TABLE(usb, usbpn_ids);
-+
-+static struct usb_driver usbpn_driver;
-+
-+static int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
-+{
-+      static const char ifname[] = "usbpn%d";
-+      const struct usb_cdc_union_desc *union_header = NULL;
-+      const struct usb_host_interface *data_desc;
-+      struct usb_interface *data_intf;
-+      struct usb_device *usbdev = interface_to_usbdev(intf);
-+      struct net_device *dev;
-+      struct usbpn_dev *pnd;
-+      u8 *data;
-+      int phonet = 0;
-+      int len, err;
-+
-+      data = intf->altsetting->extra;
-+      len = intf->altsetting->extralen;
-+      while (len >= 3) {
-+              u8 dlen = data[0];
-+              if (dlen < 3)
-+                      return -EINVAL;
-+
-+              /* bDescriptorType */
-+              if (data[1] == USB_DT_CS_INTERFACE) {
-+                      /* bDescriptorSubType */
-+                      switch (data[2]) {
-+                      case USB_CDC_UNION_TYPE:
-+                              if (union_header || dlen < 5)
-+                                      break;
-+                              union_header =
-+                                      (struct usb_cdc_union_desc *)data;
-+                              break;
-+                      case 0xAB:
-+                              phonet = 1;
-+                              break;
-+                      }
-+              }
-+              data += dlen;
-+              len -= dlen;
-+      }
-+
-+      if (!union_header || !phonet)
-+              return -EINVAL;
-+
-+      data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0);
-+      if (data_intf == NULL)
-+              return -ENODEV;
-+      /* Data interface has one inactive and one active setting */
-+      if (data_intf->num_altsetting != 2)
-+              return -EINVAL;
-+      if (data_intf->altsetting[0].desc.bNumEndpoints == 0 &&
-+          data_intf->altsetting[1].desc.bNumEndpoints == 2)
-+              data_desc = data_intf->altsetting + 1;
-+      else
-+      if (data_intf->altsetting[0].desc.bNumEndpoints == 2 &&
-+          data_intf->altsetting[1].desc.bNumEndpoints == 0)
-+              data_desc = data_intf->altsetting;
-+      else
-+              return -EINVAL;
-+
-+      dev = alloc_netdev(sizeof(*pnd) + sizeof(pnd->urbs[0]) * rxq_size,
-+                         ifname, NET_NAME_UNKNOWN, usbpn_setup);
-+      if (!dev)
-+              return -ENOMEM;
-+
-+      pnd = netdev_priv(dev);
-+      SET_NETDEV_DEV(dev, &intf->dev);
-+
-+      pnd->dev = dev;
-+      pnd->usb = usbdev;
-+      pnd->intf = intf;
-+      pnd->data_intf = data_intf;
-+      spin_lock_init(&pnd->tx_lock);
-+      spin_lock_init(&pnd->rx_lock);
-+      /* Endpoints */
-+      if (usb_pipein(data_desc->endpoint[0].desc.bEndpointAddress)) {
-+              pnd->rx_pipe = usb_rcvbulkpipe(usbdev,
-+                      data_desc->endpoint[0].desc.bEndpointAddress);
-+              pnd->tx_pipe = usb_sndbulkpipe(usbdev,
-+                      data_desc->endpoint[1].desc.bEndpointAddress);
-+      } else {
-+              pnd->rx_pipe = usb_rcvbulkpipe(usbdev,
-+                      data_desc->endpoint[1].desc.bEndpointAddress);
-+              pnd->tx_pipe = usb_sndbulkpipe(usbdev,
-+                      data_desc->endpoint[0].desc.bEndpointAddress);
-+      }
-+      pnd->active_setting = data_desc - data_intf->altsetting;
-+
-+      err = usb_driver_claim_interface(&usbpn_driver, data_intf, pnd);
-+      if (err)
-+              goto out;
-+
-+      /* Force inactive mode until the network device is brought UP */
-+      usb_set_interface(usbdev, union_header->bSlaveInterface0,
-+                              !pnd->active_setting);
-+      usb_set_intfdata(intf, pnd);
-+
-+      err = register_netdev(dev);
-+      if (err) {
-+              usb_driver_release_interface(&usbpn_driver, data_intf);
-+              goto out;
-+      }
-+
-+      dev_dbg(&dev->dev, "USB CDC Phonet device found\n");
-+      return 0;
-+
-+out:
-+      usb_set_intfdata(intf, NULL);
-+      free_netdev(dev);
-+      return err;
-+}
-+
-+static void usbpn_disconnect(struct usb_interface *intf)
-+{
-+      struct usbpn_dev *pnd = usb_get_intfdata(intf);
-+
-+      if (pnd->disconnected)
-+              return;
-+
-+      pnd->disconnected = 1;
-+      usb_driver_release_interface(&usbpn_driver,
-+                      (pnd->intf == intf) ? pnd->data_intf : pnd->intf);
-+      unregister_netdev(pnd->dev);
-+}
-+
-+static struct usb_driver usbpn_driver = {
-+      .name =         "cdc_phonet",
-+      .probe =        usbpn_probe,
-+      .disconnect =   usbpn_disconnect,
-+      .id_table =     usbpn_ids,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(usbpn_driver);
-+
-+MODULE_AUTHOR("Remi Denis-Courmont");
-+MODULE_DESCRIPTION("USB CDC Phonet host interface");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/cdc_subset.c backports-4.2.6-1/drivers/net/usb/cdc_subset.c
---- backports-4.2.6-1.org/drivers/net/usb/cdc_subset.c 1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/cdc_subset.c     2016-06-28 14:35:17.975307221 +0200
-@@ -0,0 +1,369 @@
-+/*
-+ * Simple "CDC Subset" USB Networking Links
-+ * Copyright (C) 2000-2005 by David Brownell
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kmod.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/workqueue.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/usb/usbnet.h>
-+
-+
-+/*
-+ * This supports simple USB network links that don't require any special
-+ * framing or hardware control operations.  The protocol used here is a
-+ * strict subset of CDC Ethernet, with three basic differences reflecting
-+ * the goal that almost any hardware should run it:
-+ *
-+ *  - Minimal runtime control:  one interface, no altsettings, and
-+ *    no vendor or class specific control requests.  If a device is
-+ *    configured, it is allowed to exchange packets with the host.
-+ *    Fancier models would mean not working on some hardware.
-+ *
-+ *  - Minimal manufacturing control:  no IEEE "Organizationally
-+ *    Unique ID" required, or an EEPROMs to store one.  Each host uses
-+ *    one random "locally assigned" Ethernet address instead, which can
-+ *    of course be overridden using standard tools like "ifconfig".
-+ *    (With 2^46 such addresses, same-net collisions are quite rare.)
-+ *
-+ *  - There is no additional framing data for USB.  Packets are written
-+ *    exactly as in CDC Ethernet, starting with an Ethernet header and
-+ *    terminated by a short packet.  However, the host will never send a
-+ *    zero length packet; some systems can't handle those robustly.
-+ *
-+ * Anything that can transmit and receive USB bulk packets can implement
-+ * this protocol.  That includes both smart peripherals and quite a lot
-+ * of "host-to-host" USB cables (which embed two devices back-to-back).
-+ *
-+ * Note that although Linux may use many of those host-to-host links
-+ * with this "cdc_subset" framing, that doesn't mean there may not be a
-+ * better approach.  Handling the "other end unplugs/replugs" scenario
-+ * well tends to require chip-specific vendor requests.  Also, Windows
-+ * peers at the other end of host-to-host cables may expect their own
-+ * framing to be used rather than this "cdc_subset" model.
-+ */
-+
-+#if defined(CONFIG_USB_EPSON2888) || defined(CONFIG_USB_ARMLINUX)
-+/* PDA style devices are always connected if present */
-+static int always_connected (struct usbnet *dev)
-+{
-+      return 0;
-+}
-+#endif
-+
-+#ifdef        CONFIG_USB_ALI_M5632
-+#define       HAVE_HARDWARE
-+
-+/*-------------------------------------------------------------------------
-+ *
-+ * ALi M5632 driver ... does high speed
-+ *
-+ * NOTE that the MS-Windows drivers for this chip use some funky and
-+ * (naturally) undocumented 7-byte prefix to each packet, so this is a
-+ * case where we don't currently interoperate.  Also, once you unplug
-+ * one end of the cable, you need to replug the other end too ... since
-+ * chip docs are unavailable, there's no way to reset the relevant state
-+ * short of a power cycle.
-+ *
-+ *-------------------------------------------------------------------------*/
-+
-+static void m5632_recover(struct usbnet *dev)
-+{
-+      struct usb_device       *udev = dev->udev;
-+      struct usb_interface    *intf = dev->intf;
-+      int r;
-+
-+      r = usb_lock_device_for_reset(udev, intf);
-+      if (r < 0)
-+              return;
-+
-+      usb_reset_device(udev);
-+      usb_unlock_device(udev);
-+}
-+
-+static const struct driver_info       ali_m5632_info = {
-+      .description =  "ALi M5632",
-+      .flags       = FLAG_POINTTOPOINT,
-+      .recover     = m5632_recover,
-+};
-+
-+#endif
-+
-+#ifdef        CONFIG_USB_AN2720
-+#define       HAVE_HARDWARE
-+
-+/*-------------------------------------------------------------------------
-+ *
-+ * AnchorChips 2720 driver ... http://www.cypress.com
-+ *
-+ * This doesn't seem to have a way to detect whether the peer is
-+ * connected, or need any reset handshaking.  It's got pretty big
-+ * internal buffers (handles most of a frame's worth of data).
-+ * Chip data sheets don't describe any vendor control messages.
-+ *
-+ *-------------------------------------------------------------------------*/
-+
-+static const struct driver_info       an2720_info = {
-+      .description =  "AnchorChips/Cypress 2720",
-+      .flags       = FLAG_POINTTOPOINT,
-+      // no reset available!
-+      // no check_connect available!
-+
-+      .in = 2, .out = 2,              // direction distinguishes these
-+};
-+
-+#endif        /* CONFIG_USB_AN2720 */
-+
-+\f
-+#ifdef        CONFIG_USB_BELKIN
-+#define       HAVE_HARDWARE
-+
-+/*-------------------------------------------------------------------------
-+ *
-+ * Belkin F5U104 ... two NetChip 2280 devices + Atmel AVR microcontroller
-+ *
-+ * ... also two eTEK designs, including one sold as "Advance USBNET"
-+ *
-+ *-------------------------------------------------------------------------*/
-+
-+static const struct driver_info       belkin_info = {
-+      .description =  "Belkin, eTEK, or compatible",
-+      .flags       = FLAG_POINTTOPOINT,
-+};
-+
-+#endif        /* CONFIG_USB_BELKIN */
-+
-+
-+\f
-+#ifdef        CONFIG_USB_EPSON2888
-+#define       HAVE_HARDWARE
-+
-+/*-------------------------------------------------------------------------
-+ *
-+ * EPSON USB clients
-+ *
-+ * This is the same idea as Linux PDAs (below) except the firmware in the
-+ * device might not be Tux-powered.  Epson provides reference firmware that
-+ * implements this interface.  Product developers can reuse or modify that
-+ * code, such as by using their own product and vendor codes.
-+ *
-+ * Support was from Juro Bystricky <bystricky.juro@erd.epson.com>
-+ *
-+ *-------------------------------------------------------------------------*/
-+
-+static const struct driver_info       epson2888_info = {
-+      .description =  "Epson USB Device",
-+      .check_connect = always_connected,
-+      .flags = FLAG_POINTTOPOINT,
-+
-+      .in = 4, .out = 3,
-+};
-+
-+#endif        /* CONFIG_USB_EPSON2888 */
-+
-+\f
-+/*-------------------------------------------------------------------------
-+ *
-+ * info from Jonathan McDowell <noodles@earth.li>
-+ *
-+ *-------------------------------------------------------------------------*/
-+#ifdef CONFIG_USB_KC2190
-+#define HAVE_HARDWARE
-+static const struct driver_info kc2190_info = {
-+      .description =  "KC Technology KC-190",
-+      .flags = FLAG_POINTTOPOINT,
-+};
-+#endif /* CONFIG_USB_KC2190 */
-+
-+\f
-+#ifdef        CONFIG_USB_ARMLINUX
-+#define       HAVE_HARDWARE
-+
-+/*-------------------------------------------------------------------------
-+ *
-+ * Intel's SA-1100 chip integrates basic USB support, and is used
-+ * in PDAs like some iPaqs, the Yopy, some Zaurus models, and more.
-+ * When they run Linux, arch/arm/mach-sa1100/usb-eth.c may be used to
-+ * network using minimal USB framing data.
-+ *
-+ * This describes the driver currently in standard ARM Linux kernels.
-+ * The Zaurus uses a different driver (see later).
-+ *
-+ * PXA25x and PXA210 use XScale cores (ARM v5TE) with better USB support
-+ * and different USB endpoint numbering than the SA1100 devices.  The
-+ * mach-pxa/usb-eth.c driver re-uses the device ids from mach-sa1100
-+ * so we rely on the endpoint descriptors.
-+ *
-+ *-------------------------------------------------------------------------*/
-+
-+static const struct driver_info       linuxdev_info = {
-+      .description =  "Linux Device",
-+      .check_connect = always_connected,
-+      .flags = FLAG_POINTTOPOINT,
-+};
-+
-+static const struct driver_info       yopy_info = {
-+      .description =  "Yopy",
-+      .check_connect = always_connected,
-+      .flags = FLAG_POINTTOPOINT,
-+};
-+
-+static const struct driver_info       blob_info = {
-+      .description =  "Boot Loader OBject",
-+      .check_connect = always_connected,
-+      .flags = FLAG_POINTTOPOINT,
-+};
-+
-+#endif        /* CONFIG_USB_ARMLINUX */
-+
-+\f
-+/*-------------------------------------------------------------------------*/
-+
-+#ifndef       HAVE_HARDWARE
-+#warning You need to configure some hardware for this driver
-+#endif
-+
-+/*
-+ * chip vendor names won't normally be on the cables, and
-+ * may not be on the device.
-+ */
-+
-+static const struct usb_device_id     products [] = {
-+
-+#ifdef        CONFIG_USB_ALI_M5632
-+{
-+      USB_DEVICE (0x0402, 0x5632),    // ALi defaults
-+      .driver_info =  (unsigned long) &ali_m5632_info,
-+},
-+{
-+      USB_DEVICE (0x182d,0x207c),     // SiteCom CN-124
-+      .driver_info =  (unsigned long) &ali_m5632_info,
-+},
-+#endif
-+
-+#ifdef        CONFIG_USB_AN2720
-+{
-+      USB_DEVICE (0x0547, 0x2720),    // AnchorChips defaults
-+      .driver_info =  (unsigned long) &an2720_info,
-+}, {
-+      USB_DEVICE (0x0547, 0x2727),    // Xircom PGUNET
-+      .driver_info =  (unsigned long) &an2720_info,
-+},
-+#endif
-+
-+#ifdef        CONFIG_USB_BELKIN
-+{
-+      USB_DEVICE (0x050d, 0x0004),    // Belkin
-+      .driver_info =  (unsigned long) &belkin_info,
-+}, {
-+      USB_DEVICE (0x056c, 0x8100),    // eTEK
-+      .driver_info =  (unsigned long) &belkin_info,
-+}, {
-+      USB_DEVICE (0x0525, 0x9901),    // Advance USBNET (eTEK)
-+      .driver_info =  (unsigned long) &belkin_info,
-+},
-+#endif
-+
-+#ifdef        CONFIG_USB_EPSON2888
-+{
-+      USB_DEVICE (0x0525, 0x2888),    // EPSON USB client
-+      .driver_info    = (unsigned long) &epson2888_info,
-+},
-+#endif
-+
-+#ifdef CONFIG_USB_KC2190
-+{
-+      USB_DEVICE (0x050f, 0x0190),    // KC-190
-+      .driver_info =  (unsigned long) &kc2190_info,
-+},
-+#endif
-+
-+#ifdef        CONFIG_USB_ARMLINUX
-+/*
-+ * SA-1100 using standard ARM Linux kernels, or compatible.
-+ * Often used when talking to Linux PDAs (iPaq, Yopy, etc).
-+ * The sa-1100 "usb-eth" driver handles the basic framing.
-+ *
-+ * PXA25x or PXA210 ...  these use a "usb-eth" driver much like
-+ * the sa1100 one, but hardware uses different endpoint numbers.
-+ *
-+ * Or the Linux "Ethernet" gadget on hardware that can't talk
-+ * CDC Ethernet (e.g., no altsettings), in either of two modes:
-+ *  - acting just like the old "usb-eth" firmware, though
-+ *    the implementation is different
-+ *  - supporting RNDIS as the first/default configuration for
-+ *    MS-Windows interop; Linux needs to use the other config
-+ */
-+{
-+      // 1183 = 0x049F, both used as hex values?
-+      // Compaq "Itsy" vendor/product id
-+      USB_DEVICE (0x049F, 0x505A),    // usb-eth, or compatible
-+      .driver_info =  (unsigned long) &linuxdev_info,
-+}, {
-+      USB_DEVICE (0x0E7E, 0x1001),    // G.Mate "Yopy"
-+      .driver_info =  (unsigned long) &yopy_info,
-+}, {
-+      USB_DEVICE (0x8086, 0x07d3),    // "blob" bootloader
-+      .driver_info =  (unsigned long) &blob_info,
-+}, {
-+      USB_DEVICE (0x1286, 0x8001),    // "blob" bootloader
-+      .driver_info =  (unsigned long) &blob_info,
-+}, {
-+      // Linux Ethernet/RNDIS gadget, mostly on PXA, second config
-+      // e.g. Gumstix, current OpenZaurus, ... or anything else
-+      // that just enables this gadget option.
-+      USB_DEVICE (0x0525, 0xa4a2),
-+      .driver_info =  (unsigned long) &linuxdev_info,
-+},
-+#endif
-+
-+      { },            // END
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+/*-------------------------------------------------------------------------*/
-+static int dummy_prereset(struct usb_interface *intf)
-+{
-+        return 0;
-+}
-+
-+static int dummy_postreset(struct usb_interface *intf)
-+{
-+        return 0;
-+}
-+
-+static struct usb_driver cdc_subset_driver = {
-+      .name =         "cdc_subset",
-+      .probe =        usbnet_probe,
-+      .suspend =      usbnet_suspend,
-+      .resume =       usbnet_resume,
-+      .pre_reset =    dummy_prereset,
-+      .post_reset =   dummy_postreset,
-+      .disconnect =   usbnet_disconnect,
-+      .id_table =     products,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(cdc_subset_driver);
-+
-+MODULE_AUTHOR("David Brownell");
-+MODULE_DESCRIPTION("Simple 'CDC Subset' USB networking links");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/cx82310_eth.c backports-4.2.6-1/drivers/net/usb/cx82310_eth.c
---- backports-4.2.6-1.org/drivers/net/usb/cx82310_eth.c        1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/cx82310_eth.c    2016-06-28 14:35:17.978640554 +0200
-@@ -0,0 +1,353 @@
-+/*
-+ * Driver for USB ethernet port of Conexant CX82310-based ADSL routers
-+ * Copyright (C) 2010 by Ondrej Zary
-+ * some parts inspired by the cxacru driver
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/workqueue.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/usb/usbnet.h>
-+
-+enum cx82310_cmd {
-+      CMD_START               = 0x84, /* no effect? */
-+      CMD_STOP                = 0x85, /* no effect? */
-+      CMD_GET_STATUS          = 0x90, /* returns nothing? */
-+      CMD_GET_MAC_ADDR        = 0x91, /* read MAC address */
-+      CMD_GET_LINK_STATUS     = 0x92, /* not useful, link is always up */
-+      CMD_ETHERNET_MODE       = 0x99, /* unknown, needed during init */
-+};
-+
-+enum cx82310_status {
-+      STATUS_UNDEFINED,
-+      STATUS_SUCCESS,
-+      STATUS_ERROR,
-+      STATUS_UNSUPPORTED,
-+      STATUS_UNIMPLEMENTED,
-+      STATUS_PARAMETER_ERROR,
-+      STATUS_DBG_LOOPBACK,
-+};
-+
-+#define CMD_PACKET_SIZE       64
-+#define CMD_TIMEOUT   100
-+#define CMD_REPLY_RETRY 5
-+
-+#define CX82310_MTU   1514
-+#define CMD_EP                0x01
-+
-+/*
-+ * execute control command
-+ *  - optionally send some data (command parameters)
-+ *  - optionally wait for the reply
-+ *  - optionally read some data from the reply
-+ */
-+static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
-+                     u8 *wdata, int wlen, u8 *rdata, int rlen)
-+{
-+      int actual_len, retries, ret;
-+      struct usb_device *udev = dev->udev;
-+      u8 *buf = kzalloc(CMD_PACKET_SIZE, GFP_KERNEL);
-+
-+      if (!buf)
-+              return -ENOMEM;
-+
-+      /* create command packet */
-+      buf[0] = cmd;
-+      if (wdata)
-+              memcpy(buf + 4, wdata, min_t(int, wlen, CMD_PACKET_SIZE - 4));
-+
-+      /* send command packet */
-+      ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, CMD_EP), buf,
-+                         CMD_PACKET_SIZE, &actual_len, CMD_TIMEOUT);
-+      if (ret < 0) {
-+              if (cmd != CMD_GET_LINK_STATUS)
-+                      dev_err(&dev->udev->dev, "send command %#x: error %d\n",
-+                              cmd, ret);
-+              goto end;
-+      }
-+
-+      if (reply) {
-+              /* wait for reply, retry if it's empty */
-+              for (retries = 0; retries < CMD_REPLY_RETRY; retries++) {
-+                      ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, CMD_EP),
-+                                         buf, CMD_PACKET_SIZE, &actual_len,
-+                                         CMD_TIMEOUT);
-+                      if (ret < 0) {
-+                              if (cmd != CMD_GET_LINK_STATUS)
-+                                      dev_err(&dev->udev->dev,
-+                                              "reply receive error %d\n",
-+                                              ret);
-+                              goto end;
-+                      }
-+                      if (actual_len > 0)
-+                              break;
-+              }
-+              if (actual_len == 0) {
-+                      dev_err(&dev->udev->dev, "no reply to command %#x\n",
-+                              cmd);
-+                      ret = -EIO;
-+                      goto end;
-+              }
-+              if (buf[0] != cmd) {
-+                      dev_err(&dev->udev->dev,
-+                              "got reply to command %#x, expected: %#x\n",
-+                              buf[0], cmd);
-+                      ret = -EIO;
-+                      goto end;
-+              }
-+              if (buf[1] != STATUS_SUCCESS) {
-+                      dev_err(&dev->udev->dev, "command %#x failed: %#x\n",
-+                              cmd, buf[1]);
-+                      ret = -EIO;
-+                      goto end;
-+              }
-+              if (rdata)
-+                      memcpy(rdata, buf + 4,
-+                             min_t(int, rlen, CMD_PACKET_SIZE - 4));
-+      }
-+end:
-+      kfree(buf);
-+      return ret;
-+}
-+
-+#define partial_len   data[0]         /* length of partial packet data */
-+#define partial_rem   data[1]         /* remaining (missing) data length */
-+#define partial_data  data[2]         /* partial packet data */
-+
-+static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      int ret;
-+      char buf[15];
-+      struct usb_device *udev = dev->udev;
-+      u8 link[3];
-+      int timeout = 50;
-+
-+      /* avoid ADSL modems - continue only if iProduct is "USB NET CARD" */
-+      if (usb_string(udev, udev->descriptor.iProduct, buf, sizeof(buf)) > 0
-+          && strcmp(buf, "USB NET CARD")) {
-+              dev_info(&udev->dev, "ignoring: probably an ADSL modem\n");
-+              return -ENODEV;
-+      }
-+
-+      ret = usbnet_get_endpoints(dev, intf);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * this must not include ethernet header as the device can send partial
-+       * packets with no header (and sometimes even empty URBs)
-+       */
-+      dev->net->hard_header_len = 0;
-+      /* we can send at most 1514 bytes of data (+ 2-byte header) per URB */
-+      dev->hard_mtu = CX82310_MTU + 2;
-+      /* we can receive URBs up to 4KB from the device */
-+      dev->rx_urb_size = 4096;
-+
-+      dev->partial_data = (unsigned long) kmalloc(dev->hard_mtu, GFP_KERNEL);
-+      if (!dev->partial_data)
-+              return -ENOMEM;
-+
-+      /* wait for firmware to become ready (indicated by the link being up) */
-+      while (--timeout) {
-+              ret = cx82310_cmd(dev, CMD_GET_LINK_STATUS, true, NULL, 0,
-+                                link, sizeof(link));
-+              /* the command can time out during boot - it's not an error */
-+              if (!ret && link[0] == 1 && link[2] == 1)
-+                      break;
-+              msleep(500);
-+      }
-+      if (!timeout) {
-+              dev_err(&udev->dev, "firmware not ready in time\n");
-+              return -ETIMEDOUT;
-+      }
-+
-+      /* enable ethernet mode (?) */
-+      ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0);
-+      if (ret) {
-+              dev_err(&udev->dev, "unable to enable ethernet mode: %d\n",
-+                      ret);
-+              goto err;
-+      }
-+
-+      /* get the MAC address */
-+      ret = cx82310_cmd(dev, CMD_GET_MAC_ADDR, true, NULL, 0,
-+                        dev->net->dev_addr, ETH_ALEN);
-+      if (ret) {
-+              dev_err(&udev->dev, "unable to read MAC address: %d\n", ret);
-+              goto err;
-+      }
-+
-+      /* start (does not seem to have any effect?) */
-+      ret = cx82310_cmd(dev, CMD_START, false, NULL, 0, NULL, 0);
-+      if (ret)
-+              goto err;
-+
-+      return 0;
-+err:
-+      kfree((void *)dev->partial_data);
-+      return ret;
-+}
-+
-+static void cx82310_unbind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      kfree((void *)dev->partial_data);
-+}
-+
-+/*
-+ * RX is NOT easy - we can receive multiple packets per skb, each having 2-byte
-+ * packet length at the beginning.
-+ * The last packet might be incomplete (when it crosses the 4KB URB size),
-+ * continuing in the next skb (without any headers).
-+ * If a packet has odd length, there is one extra byte at the end (before next
-+ * packet or at the end of the URB).
-+ */
-+static int cx82310_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      int len;
-+      struct sk_buff *skb2;
-+
-+      /*
-+       * If the last skb ended with an incomplete packet, this skb contains
-+       * end of that packet at the beginning.
-+       */
-+      if (dev->partial_rem) {
-+              len = dev->partial_len + dev->partial_rem;
-+              skb2 = alloc_skb(len, GFP_ATOMIC);
-+              if (!skb2)
-+                      return 0;
-+              skb_put(skb2, len);
-+              memcpy(skb2->data, (void *)dev->partial_data,
-+                     dev->partial_len);
-+              memcpy(skb2->data + dev->partial_len, skb->data,
-+                     dev->partial_rem);
-+              usbnet_skb_return(dev, skb2);
-+              skb_pull(skb, (dev->partial_rem + 1) & ~1);
-+              dev->partial_rem = 0;
-+              if (skb->len < 2)
-+                      return 1;
-+      }
-+
-+      /* a skb can contain multiple packets */
-+      while (skb->len > 1) {
-+              /* first two bytes are packet length */
-+              len = skb->data[0] | (skb->data[1] << 8);
-+              skb_pull(skb, 2);
-+
-+              /* if last packet in the skb, let usbnet to process it */
-+              if (len == skb->len || len + 1 == skb->len) {
-+                      skb_trim(skb, len);
-+                      break;
-+              }
-+
-+              if (len > CX82310_MTU) {
-+                      dev_err(&dev->udev->dev, "RX packet too long: %d B\n",
-+                              len);
-+                      return 0;
-+              }
-+
-+              /* incomplete packet, save it for the next skb */
-+              if (len > skb->len) {
-+                      dev->partial_len = skb->len;
-+                      dev->partial_rem = len - skb->len;
-+                      memcpy((void *)dev->partial_data, skb->data,
-+                             dev->partial_len);
-+                      skb_pull(skb, skb->len);
-+                      break;
-+              }
-+
-+              skb2 = alloc_skb(len, GFP_ATOMIC);
-+              if (!skb2)
-+                      return 0;
-+              skb_put(skb2, len);
-+              memcpy(skb2->data, skb->data, len);
-+              /* process the packet */
-+              usbnet_skb_return(dev, skb2);
-+
-+              skb_pull(skb, (len + 1) & ~1);
-+      }
-+
-+      /* let usbnet process the last packet */
-+      return 1;
-+}
-+
-+/* TX is easy, just add 2 bytes of length at the beginning */
-+static struct sk_buff *cx82310_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
-+                                     gfp_t flags)
-+{
-+      int len = skb->len;
-+
-+      if (skb_headroom(skb) < 2) {
-+              struct sk_buff *skb2 = skb_copy_expand(skb, 2, 0, flags);
-+              dev_kfree_skb_any(skb);
-+              skb = skb2;
-+              if (!skb)
-+                      return NULL;
-+      }
-+      skb_push(skb, 2);
-+
-+      skb->data[0] = len;
-+      skb->data[1] = len >> 8;
-+
-+      return skb;
-+}
-+
-+
-+static const struct driver_info       cx82310_info = {
-+      .description    = "Conexant CX82310 USB ethernet",
-+      .flags          = FLAG_ETHER,
-+      .bind           = cx82310_bind,
-+      .unbind         = cx82310_unbind,
-+      .rx_fixup       = cx82310_rx_fixup,
-+      .tx_fixup       = cx82310_tx_fixup,
-+};
-+
-+#define USB_DEVICE_CLASS(vend, prod, cl, sc, pr) \
-+      .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
-+                     USB_DEVICE_ID_MATCH_DEV_INFO, \
-+      .idVendor = (vend), \
-+      .idProduct = (prod), \
-+      .bDeviceClass = (cl), \
-+      .bDeviceSubClass = (sc), \
-+      .bDeviceProtocol = (pr)
-+
-+static const struct usb_device_id products[] = {
-+      {
-+              USB_DEVICE_CLASS(0x0572, 0xcb01, 0xff, 0, 0),
-+              .driver_info = (unsigned long) &cx82310_info
-+      },
-+      { },
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver cx82310_driver = {
-+      .name           = "cx82310_eth",
-+      .id_table       = products,
-+      .probe          = usbnet_probe,
-+      .disconnect     = usbnet_disconnect,
-+      .suspend        = usbnet_suspend,
-+      .resume         = usbnet_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(cx82310_driver);
-+
-+MODULE_AUTHOR("Ondrej Zary");
-+MODULE_DESCRIPTION("Conexant CX82310-based ADSL router USB ethernet driver");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/dm9601.c backports-4.2.6-1/drivers/net/usb/dm9601.c
---- backports-4.2.6-1.org/drivers/net/usb/dm9601.c     1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/dm9601.c 2016-06-28 14:35:17.978640554 +0200
-@@ -0,0 +1,647 @@
-+/*
-+ * Davicom DM96xx USB 10/100Mbps ethernet devices
-+ *
-+ * Peter Korsgaard <jacmet@sunsite.dk>
-+ *
-+ * 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
-+ * kind, whether express or implied.
-+ */
-+
-+//#define DEBUG
-+
-+#include <linux/module.h>
-+#include <linux/sched.h>
-+#include <linux/stddef.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/crc32.h>
-+#include <linux/usb/usbnet.h>
-+#include <linux/slab.h>
-+
-+/* datasheet:
-+ http://ptm2.cc.utu.fi/ftp/network/cards/DM9601/From_NET/DM9601-DS-P01-930914.pdf
-+*/
-+
-+/* control requests */
-+#define DM_READ_REGS  0x00
-+#define DM_WRITE_REGS 0x01
-+#define DM_READ_MEMS  0x02
-+#define DM_WRITE_REG  0x03
-+#define DM_WRITE_MEMS 0x05
-+#define DM_WRITE_MEM  0x07
-+
-+/* registers */
-+#define DM_NET_CTRL   0x00
-+#define DM_RX_CTRL    0x05
-+#define DM_SHARED_CTRL        0x0b
-+#define DM_SHARED_ADDR        0x0c
-+#define DM_SHARED_DATA        0x0d    /* low + high */
-+#define DM_PHY_ADDR   0x10    /* 6 bytes */
-+#define DM_MCAST_ADDR 0x16    /* 8 bytes */
-+#define DM_GPR_CTRL   0x1e
-+#define DM_GPR_DATA   0x1f
-+#define DM_CHIP_ID    0x2c
-+#define DM_MODE_CTRL  0x91    /* only on dm9620 */
-+
-+/* chip id values */
-+#define ID_DM9601     0
-+#define ID_DM9620     1
-+
-+#define DM_MAX_MCAST  64
-+#define DM_MCAST_SIZE 8
-+#define DM_EEPROM_LEN 256
-+#define DM_TX_OVERHEAD        2       /* 2 byte header */
-+#define DM_RX_OVERHEAD        7       /* 3 byte header + 4 byte crc tail */
-+#define DM_TIMEOUT    1000
-+
-+static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
-+{
-+      int err;
-+      err = usbnet_read_cmd(dev, DM_READ_REGS,
-+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+                             0, reg, data, length);
-+      if(err != length && err >= 0)
-+              err = -EINVAL;
-+      return err;
-+}
-+
-+static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value)
-+{
-+      return dm_read(dev, reg, 1, value);
-+}
-+
-+static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data)
-+{
-+      int err;
-+      err = usbnet_write_cmd(dev, DM_WRITE_REGS,
-+                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+                              0, reg, data, length);
-+
-+      if (err >= 0 && err < length)
-+              err = -EINVAL;
-+      return err;
-+}
-+
-+static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
-+{
-+      return usbnet_write_cmd(dev, DM_WRITE_REG,
-+                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+                              value, reg, NULL, 0);
-+}
-+
-+static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
-+{
-+      usbnet_write_cmd_async(dev, DM_WRITE_REGS,
-+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+                             0, reg, data, length);
-+}
-+
-+static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
-+{
-+      usbnet_write_cmd_async(dev, DM_WRITE_REG,
-+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+                             value, reg, NULL, 0);
-+}
-+
-+static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value)
-+{
-+      int ret, i;
-+
-+      mutex_lock(&dev->phy_mutex);
-+
-+      dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
-+      dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0xc : 0x4);
-+
-+      for (i = 0; i < DM_TIMEOUT; i++) {
-+              u8 tmp = 0;
-+
-+              udelay(1);
-+              ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
-+              if (ret < 0)
-+                      goto out;
-+
-+              /* ready */
-+              if ((tmp & 1) == 0)
-+                      break;
-+      }
-+
-+      if (i == DM_TIMEOUT) {
-+              netdev_err(dev->net, "%s read timed out!\n", phy ? "phy" : "eeprom");
-+              ret = -EIO;
-+              goto out;
-+      }
-+
-+      dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
-+      ret = dm_read(dev, DM_SHARED_DATA, 2, value);
-+
-+      netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n",
-+                 phy, reg, *value, ret);
-+
-+ out:
-+      mutex_unlock(&dev->phy_mutex);
-+      return ret;
-+}
-+
-+static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 value)
-+{
-+      int ret, i;
-+
-+      mutex_lock(&dev->phy_mutex);
-+
-+      ret = dm_write(dev, DM_SHARED_DATA, 2, &value);
-+      if (ret < 0)
-+              goto out;
-+
-+      dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
-+      dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1a : 0x12);
-+
-+      for (i = 0; i < DM_TIMEOUT; i++) {
-+              u8 tmp = 0;
-+
-+              udelay(1);
-+              ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
-+              if (ret < 0)
-+                      goto out;
-+
-+              /* ready */
-+              if ((tmp & 1) == 0)
-+                      break;
-+      }
-+
-+      if (i == DM_TIMEOUT) {
-+              netdev_err(dev->net, "%s write timed out!\n", phy ? "phy" : "eeprom");
-+              ret = -EIO;
-+              goto out;
-+      }
-+
-+      dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
-+
-+out:
-+      mutex_unlock(&dev->phy_mutex);
-+      return ret;
-+}
-+
-+static int dm_read_eeprom_word(struct usbnet *dev, u8 offset, void *value)
-+{
-+      return dm_read_shared_word(dev, 0, offset, value);
-+}
-+
-+
-+
-+static int dm9601_get_eeprom_len(struct net_device *dev)
-+{
-+      return DM_EEPROM_LEN;
-+}
-+
-+static int dm9601_get_eeprom(struct net_device *net,
-+                           struct ethtool_eeprom *eeprom, u8 * data)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      __le16 *ebuf = (__le16 *) data;
-+      int i;
-+
-+      /* access is 16bit */
-+      if ((eeprom->offset % 2) || (eeprom->len % 2))
-+              return -EINVAL;
-+
-+      for (i = 0; i < eeprom->len / 2; i++) {
-+              if (dm_read_eeprom_word(dev, eeprom->offset / 2 + i,
-+                                      &ebuf[i]) < 0)
-+                      return -EINVAL;
-+      }
-+      return 0;
-+}
-+
-+static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+
-+      __le16 res;
-+
-+      if (phy_id) {
-+              netdev_dbg(dev->net, "Only internal phy supported\n");
-+              return 0;
-+      }
-+
-+      dm_read_shared_word(dev, 1, loc, &res);
-+
-+      netdev_dbg(dev->net,
-+                 "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
-+                 phy_id, loc, le16_to_cpu(res));
-+
-+      return le16_to_cpu(res);
-+}
-+
-+static void dm9601_mdio_write(struct net_device *netdev, int phy_id, int loc,
-+                            int val)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      __le16 res = cpu_to_le16(val);
-+
-+      if (phy_id) {
-+              netdev_dbg(dev->net, "Only internal phy supported\n");
-+              return;
-+      }
-+
-+      netdev_dbg(dev->net, "dm9601_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
-+                 phy_id, loc, val);
-+
-+      dm_write_shared_word(dev, 1, loc, res);
-+}
-+
-+static void dm9601_get_drvinfo(struct net_device *net,
-+                             struct ethtool_drvinfo *info)
-+{
-+      /* Inherit standard device info */
-+      usbnet_get_drvinfo(net, info);
-+      info->eedump_len = DM_EEPROM_LEN;
-+}
-+
-+static u32 dm9601_get_link(struct net_device *net)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+
-+      return mii_link_ok(&dev->mii);
-+}
-+
-+static int dm9601_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+
-+      return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
-+}
-+
-+static const struct ethtool_ops dm9601_ethtool_ops = {
-+      .get_drvinfo    = dm9601_get_drvinfo,
-+      .get_link       = dm9601_get_link,
-+      .get_msglevel   = usbnet_get_msglevel,
-+      .set_msglevel   = usbnet_set_msglevel,
-+      .get_eeprom_len = dm9601_get_eeprom_len,
-+      .get_eeprom     = dm9601_get_eeprom,
-+      .get_settings   = usbnet_get_settings,
-+      .set_settings   = usbnet_set_settings,
-+      .nway_reset     = usbnet_nway_reset,
-+};
-+
-+static void dm9601_set_multicast(struct net_device *net)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      /* We use the 20 byte dev->data for our 8 byte filter buffer
-+       * to avoid allocating memory that is tricky to free later */
-+      u8 *hashes = (u8 *) & dev->data;
-+      u8 rx_ctl = 0x31;
-+
-+      memset(hashes, 0x00, DM_MCAST_SIZE);
-+      hashes[DM_MCAST_SIZE - 1] |= 0x80;      /* broadcast address */
-+
-+      if (net->flags & IFF_PROMISC) {
-+              rx_ctl |= 0x02;
-+      } else if (net->flags & IFF_ALLMULTI ||
-+                 netdev_mc_count(net) > DM_MAX_MCAST) {
-+              rx_ctl |= 0x08;
-+      } else if (!netdev_mc_empty(net)) {
-+              struct netdev_hw_addr *ha;
-+
-+              netdev_for_each_mc_addr(ha, net) {
-+                      u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26;
-+                      hashes[crc >> 3] |= 1 << (crc & 0x7);
-+              }
-+      }
-+
-+      dm_write_async(dev, DM_MCAST_ADDR, DM_MCAST_SIZE, hashes);
-+      dm_write_reg_async(dev, DM_RX_CTRL, rx_ctl);
-+}
-+
-+static void __dm9601_set_mac_address(struct usbnet *dev)
-+{
-+      dm_write_async(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr);
-+}
-+
-+static int dm9601_set_mac_address(struct net_device *net, void *p)
-+{
-+      struct sockaddr *addr = p;
-+      struct usbnet *dev = netdev_priv(net);
-+
-+      if (!is_valid_ether_addr(addr->sa_data)) {
-+              dev_err(&net->dev, "not setting invalid mac address %pM\n",
-+                                                              addr->sa_data);
-+              return -EINVAL;
-+      }
-+
-+      memcpy(net->dev_addr, addr->sa_data, net->addr_len);
-+      __dm9601_set_mac_address(dev);
-+
-+      return 0;
-+}
-+
-+static const struct net_device_ops dm9601_netdev_ops = {
-+      .ndo_open               = usbnet_open,
-+      .ndo_stop               = usbnet_stop,
-+      .ndo_start_xmit         = usbnet_start_xmit,
-+      .ndo_tx_timeout         = usbnet_tx_timeout,
-+      .ndo_change_mtu         = usbnet_change_mtu,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_do_ioctl           = dm9601_ioctl,
-+      .ndo_set_rx_mode        = dm9601_set_multicast,
-+      .ndo_set_mac_address    = dm9601_set_mac_address,
-+};
-+
-+static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      int ret;
-+      u8 mac[ETH_ALEN], id;
-+
-+      ret = usbnet_get_endpoints(dev, intf);
-+      if (ret)
-+              goto out;
-+
-+      dev->net->netdev_ops = &dm9601_netdev_ops;
-+      dev->net->ethtool_ops = &dm9601_ethtool_ops;
-+      dev->net->hard_header_len += DM_TX_OVERHEAD;
-+      dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
-+
-+      /* dm9620/21a require room for 4 byte padding, even in dm9601
-+       * mode, so we need +1 to be able to receive full size
-+       * ethernet frames.
-+       */
-+      dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD + 1;
-+
-+      dev->mii.dev = dev->net;
-+      dev->mii.mdio_read = dm9601_mdio_read;
-+      dev->mii.mdio_write = dm9601_mdio_write;
-+      dev->mii.phy_id_mask = 0x1f;
-+      dev->mii.reg_num_mask = 0x1f;
-+
-+      /* reset */
-+      dm_write_reg(dev, DM_NET_CTRL, 1);
-+      udelay(20);
-+
-+      /* read MAC */
-+      if (dm_read(dev, DM_PHY_ADDR, ETH_ALEN, mac) < 0) {
-+              printk(KERN_ERR "Error reading MAC address\n");
-+              ret = -ENODEV;
-+              goto out;
-+      }
-+
-+      /*
-+       * Overwrite the auto-generated address only with good ones.
-+       */
-+      if (is_valid_ether_addr(mac))
-+              memcpy(dev->net->dev_addr, mac, ETH_ALEN);
-+      else {
-+              printk(KERN_WARNING
-+                      "dm9601: No valid MAC address in EEPROM, using %pM\n",
-+                      dev->net->dev_addr);
-+              __dm9601_set_mac_address(dev);
-+      }
-+
-+      if (dm_read_reg(dev, DM_CHIP_ID, &id) < 0) {
-+              netdev_err(dev->net, "Error reading chip ID\n");
-+              ret = -ENODEV;
-+              goto out;
-+      }
-+
-+      /* put dm9620 devices in dm9601 mode */
-+      if (id == ID_DM9620) {
-+              u8 mode;
-+
-+              if (dm_read_reg(dev, DM_MODE_CTRL, &mode) < 0) {
-+                      netdev_err(dev->net, "Error reading MODE_CTRL\n");
-+                      ret = -ENODEV;
-+                      goto out;
-+              }
-+              dm_write_reg(dev, DM_MODE_CTRL, mode & 0x7f);
-+      }
-+
-+      /* power up phy */
-+      dm_write_reg(dev, DM_GPR_CTRL, 1);
-+      dm_write_reg(dev, DM_GPR_DATA, 0);
-+
-+      /* receive broadcast packets */
-+      dm9601_set_multicast(dev->net);
-+
-+      dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-+      dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
-+                        ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
-+      mii_nway_restart(&dev->mii);
-+
-+out:
-+      return ret;
-+}
-+
-+static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      u8 status;
-+      int len;
-+
-+      /* format:
-+         b1: rx status
-+         b2: packet length (incl crc) low
-+         b3: packet length (incl crc) high
-+         b4..n-4: packet data
-+         bn-3..bn: ethernet crc
-+       */
-+
-+      if (unlikely(skb->len < DM_RX_OVERHEAD)) {
-+              dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
-+              return 0;
-+      }
-+
-+      status = skb->data[0];
-+      len = (skb->data[1] | (skb->data[2] << 8)) - 4;
-+
-+      if (unlikely(status & 0xbf)) {
-+              if (status & 0x01) dev->net->stats.rx_fifo_errors++;
-+              if (status & 0x02) dev->net->stats.rx_crc_errors++;
-+              if (status & 0x04) dev->net->stats.rx_frame_errors++;
-+              if (status & 0x20) dev->net->stats.rx_missed_errors++;
-+              if (status & 0x90) dev->net->stats.rx_length_errors++;
-+              return 0;
-+      }
-+
-+      skb_pull(skb, 3);
-+      skb_trim(skb, len);
-+
-+      return 1;
-+}
-+
-+static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
-+                                     gfp_t flags)
-+{
-+      int len, pad;
-+
-+      /* format:
-+         b1: packet length low
-+         b2: packet length high
-+         b3..n: packet data
-+      */
-+
-+      len = skb->len + DM_TX_OVERHEAD;
-+
-+      /* workaround for dm962x errata with tx fifo getting out of
-+       * sync if a USB bulk transfer retry happens right after a
-+       * packet with odd / maxpacket length by adding up to 3 bytes
-+       * padding.
-+       */
-+      while ((len & 1) || !(len % dev->maxpacket))
-+              len++;
-+
-+      len -= DM_TX_OVERHEAD; /* hw header doesn't count as part of length */
-+      pad = len - skb->len;
-+
-+      if (skb_headroom(skb) < DM_TX_OVERHEAD || skb_tailroom(skb) < pad) {
-+              struct sk_buff *skb2;
-+
-+              skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, pad, flags);
-+              dev_kfree_skb_any(skb);
-+              skb = skb2;
-+              if (!skb)
-+                      return NULL;
-+      }
-+
-+      __skb_push(skb, DM_TX_OVERHEAD);
-+
-+      if (pad) {
-+              memset(skb->data + skb->len, 0, pad);
-+              __skb_put(skb, pad);
-+      }
-+
-+      skb->data[0] = len;
-+      skb->data[1] = len >> 8;
-+
-+      return skb;
-+}
-+
-+static void dm9601_status(struct usbnet *dev, struct urb *urb)
-+{
-+      int link;
-+      u8 *buf;
-+
-+      /* format:
-+         b0: net status
-+         b1: tx status 1
-+         b2: tx status 2
-+         b3: rx status
-+         b4: rx overflow
-+         b5: rx count
-+         b6: tx count
-+         b7: gpr
-+      */
-+
-+      if (urb->actual_length < 8)
-+              return;
-+
-+      buf = urb->transfer_buffer;
-+
-+      link = !!(buf[0] & 0x40);
-+      if (netif_carrier_ok(dev->net) != link) {
-+              usbnet_link_change(dev, link, 1);
-+              netdev_dbg(dev->net, "Link Status is: %d\n", link);
-+      }
-+}
-+
-+static int dm9601_link_reset(struct usbnet *dev)
-+{
-+      struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
-+
-+      mii_check_media(&dev->mii, 1, 1);
-+      mii_ethtool_gset(&dev->mii, &ecmd);
-+
-+      netdev_dbg(dev->net, "link_reset() speed: %u duplex: %d\n",
-+                 ethtool_cmd_speed(&ecmd), ecmd.duplex);
-+
-+      return 0;
-+}
-+
-+static const struct driver_info dm9601_info = {
-+      .description    = "Davicom DM96xx USB 10/100 Ethernet",
-+      .flags          = FLAG_ETHER | FLAG_LINK_INTR,
-+      .bind           = dm9601_bind,
-+      .rx_fixup       = dm9601_rx_fixup,
-+      .tx_fixup       = dm9601_tx_fixup,
-+      .status         = dm9601_status,
-+      .link_reset     = dm9601_link_reset,
-+      .reset          = dm9601_link_reset,
-+};
-+
-+static const struct usb_device_id products[] = {
-+      {
-+       USB_DEVICE(0x07aa, 0x9601),    /* Corega FEther USB-TXC */
-+       .driver_info = (unsigned long)&dm9601_info,
-+       },
-+      {
-+       USB_DEVICE(0x0a46, 0x9601),    /* Davicom USB-100 */
-+       .driver_info = (unsigned long)&dm9601_info,
-+       },
-+      {
-+       USB_DEVICE(0x0a46, 0x6688),    /* ZT6688 USB NIC */
-+       .driver_info = (unsigned long)&dm9601_info,
-+       },
-+      {
-+       USB_DEVICE(0x0a46, 0x0268),    /* ShanTou ST268 USB NIC */
-+       .driver_info = (unsigned long)&dm9601_info,
-+       },
-+      {
-+       USB_DEVICE(0x0a46, 0x8515),    /* ADMtek ADM8515 USB NIC */
-+       .driver_info = (unsigned long)&dm9601_info,
-+       },
-+      {
-+      USB_DEVICE(0x0a47, 0x9601),     /* Hirose USB-100 */
-+      .driver_info = (unsigned long)&dm9601_info,
-+       },
-+      {
-+      USB_DEVICE(0x0fe6, 0x8101),     /* DM9601 USB to Fast Ethernet Adapter */
-+      .driver_info = (unsigned long)&dm9601_info,
-+       },
-+      {
-+       USB_DEVICE(0x0fe6, 0x9700),    /* DM9601 USB to Fast Ethernet Adapter */
-+       .driver_info = (unsigned long)&dm9601_info,
-+       },
-+      {
-+       USB_DEVICE(0x0a46, 0x9000),    /* DM9000E */
-+       .driver_info = (unsigned long)&dm9601_info,
-+       },
-+      {
-+       USB_DEVICE(0x0a46, 0x9620),    /* DM9620 USB to Fast Ethernet Adapter */
-+       .driver_info = (unsigned long)&dm9601_info,
-+       },
-+      {
-+       USB_DEVICE(0x0a46, 0x9621),    /* DM9621A USB to Fast Ethernet Adapter */
-+       .driver_info = (unsigned long)&dm9601_info,
-+      },
-+      {
-+       USB_DEVICE(0x0a46, 0x9622),    /* DM9622 USB to Fast Ethernet Adapter */
-+       .driver_info = (unsigned long)&dm9601_info,
-+      },
-+      {
-+       USB_DEVICE(0x0a46, 0x0269),    /* DM962OA USB to Fast Ethernet Adapter */
-+       .driver_info = (unsigned long)&dm9601_info,
-+      },
-+      {
-+       USB_DEVICE(0x0a46, 0x1269),    /* DM9621A USB to Fast Ethernet Adapter */
-+       .driver_info = (unsigned long)&dm9601_info,
-+      },
-+      {},                     // END
-+};
-+
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver dm9601_driver = {
-+      .name = "dm9601",
-+      .id_table = products,
-+      .probe = usbnet_probe,
-+      .disconnect = usbnet_disconnect,
-+      .suspend = usbnet_suspend,
-+      .resume = usbnet_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(dm9601_driver);
-+
-+MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
-+MODULE_DESCRIPTION("Davicom DM96xx USB 10/100 ethernet devices");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/gl620a.c backports-4.2.6-1/drivers/net/usb/gl620a.c
---- backports-4.2.6-1.org/drivers/net/usb/gl620a.c     1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/gl620a.c 2016-06-28 14:35:17.978640554 +0200
-@@ -0,0 +1,242 @@
-+/*
-+ * GeneSys GL620USB-A based links
-+ * Copyright (C) 2001 by Jiun-Jie Huang <huangjj@genesyslogic.com.tw>
-+ * Copyright (C) 2001 by Stanislav Brabec <utx@penguin.cz>
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+// #define    DEBUG                   // error path messages, extra info
-+// #define    VERBOSE                 // more; success messages
-+
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/workqueue.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/usb/usbnet.h>
-+#include <linux/gfp.h>
-+
-+
-+/*
-+ * GeneSys GL620USB-A (www.genesyslogic.com.tw)
-+ *
-+ * ... should partially interop with the Win32 driver for this hardware.
-+ * The GeneSys docs imply there's some NDIS issue motivating this framing.
-+ *
-+ * Some info from GeneSys:
-+ *  - GL620USB-A is full duplex; GL620USB is only half duplex for bulk.
-+ *    (Some cables, like the BAFO-100c, use the half duplex version.)
-+ *  - For the full duplex model, the low bit of the version code says
-+ *    which side is which ("left/right").
-+ *  - For the half duplex type, a control/interrupt handshake settles
-+ *    the transfer direction.  (That's disabled here, partially coded.)
-+ *    A control URB would block until other side writes an interrupt.
-+ *
-+ * Original code from Jiun-Jie Huang <huangjj@genesyslogic.com.tw>
-+ * and merged into "usbnet" by Stanislav Brabec <utx@penguin.cz>.
-+ */
-+
-+// control msg write command
-+#define GENELINK_CONNECT_WRITE                        0xF0
-+// interrupt pipe index
-+#define GENELINK_INTERRUPT_PIPE                       0x03
-+// interrupt read buffer size
-+#define INTERRUPT_BUFSIZE                     0x08
-+// interrupt pipe interval value
-+#define GENELINK_INTERRUPT_INTERVAL           0x10
-+// max transmit packet number per transmit
-+#define GL_MAX_TRANSMIT_PACKETS                       32
-+// max packet length
-+#define GL_MAX_PACKET_LEN                     1514
-+// max receive buffer size
-+#define GL_RCV_BUF_SIZE               \
-+      (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4)
-+
-+struct gl_packet {
-+      __le32          packet_length;
-+      char            packet_data [1];
-+};
-+
-+struct gl_header {
-+      __le32                  packet_count;
-+      struct gl_packet        packets;
-+};
-+
-+static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      struct gl_header        *header;
-+      struct gl_packet        *packet;
-+      struct sk_buff          *gl_skb;
-+      u32                     size;
-+      u32                     count;
-+
-+      /* This check is no longer done by usbnet */
-+      if (skb->len < dev->net->hard_header_len)
-+              return 0;
-+
-+      header = (struct gl_header *) skb->data;
-+
-+      // get the packet count of the received skb
-+      count = le32_to_cpu(header->packet_count);
-+      if (count > GL_MAX_TRANSMIT_PACKETS) {
-+              netdev_dbg(dev->net,
-+                         "genelink: invalid received packet count %u\n",
-+                         count);
-+              return 0;
-+      }
-+
-+      // set the current packet pointer to the first packet
-+      packet = &header->packets;
-+
-+      // decrement the length for the packet count size 4 bytes
-+      skb_pull(skb, 4);
-+
-+      while (count > 1) {
-+              // get the packet length
-+              size = le32_to_cpu(packet->packet_length);
-+
-+              // this may be a broken packet
-+              if (size > GL_MAX_PACKET_LEN) {
-+                      netdev_dbg(dev->net, "genelink: invalid rx length %d\n",
-+                                 size);
-+                      return 0;
-+              }
-+
-+              // allocate the skb for the individual packet
-+              gl_skb = alloc_skb(size, GFP_ATOMIC);
-+              if (gl_skb) {
-+
-+                      // copy the packet data to the new skb
-+                      memcpy(skb_put(gl_skb, size),
-+                                      packet->packet_data, size);
-+                      usbnet_skb_return(dev, gl_skb);
-+              }
-+
-+              // advance to the next packet
-+              packet = (struct gl_packet *)&packet->packet_data[size];
-+              count--;
-+
-+              // shift the data pointer to the next gl_packet
-+              skb_pull(skb, size + 4);
-+      }
-+
-+      // skip the packet length field 4 bytes
-+      skb_pull(skb, 4);
-+
-+      if (skb->len > GL_MAX_PACKET_LEN) {
-+              netdev_dbg(dev->net, "genelink: invalid rx length %d\n",
-+                         skb->len);
-+              return 0;
-+      }
-+      return 1;
-+}
-+
-+static struct sk_buff *
-+genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
-+{
-+      int     padlen;
-+      int     length = skb->len;
-+      int     headroom = skb_headroom(skb);
-+      int     tailroom = skb_tailroom(skb);
-+      __le32  *packet_count;
-+      __le32  *packet_len;
-+
-+      // FIXME:  magic numbers, bleech
-+      padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1;
-+
-+      if ((!skb_cloned(skb))
-+                      && ((headroom + tailroom) >= (padlen + (4 + 4*1)))) {
-+              if ((headroom < (4 + 4*1)) || (tailroom < padlen)) {
-+                      skb->data = memmove(skb->head + (4 + 4*1),
-+                                           skb->data, skb->len);
-+                      skb_set_tail_pointer(skb, skb->len);
-+              }
-+      } else {
-+              struct sk_buff  *skb2;
-+              skb2 = skb_copy_expand(skb, (4 + 4*1) , padlen, flags);
-+              dev_kfree_skb_any(skb);
-+              skb = skb2;
-+              if (!skb)
-+                      return NULL;
-+      }
-+
-+      // attach the packet count to the header
-+      packet_count = (__le32 *) skb_push(skb, (4 + 4*1));
-+      packet_len = packet_count + 1;
-+
-+      *packet_count = cpu_to_le32(1);
-+      *packet_len = cpu_to_le32(length);
-+
-+      // add padding byte
-+      if ((skb->len % dev->maxpacket) == 0)
-+              skb_put(skb, 1);
-+
-+      return skb;
-+}
-+
-+static int genelink_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      dev->hard_mtu = GL_RCV_BUF_SIZE;
-+      dev->net->hard_header_len += 4;
-+      dev->in = usb_rcvbulkpipe(dev->udev, dev->driver_info->in);
-+      dev->out = usb_sndbulkpipe(dev->udev, dev->driver_info->out);
-+      return 0;
-+}
-+
-+static const struct driver_info       genelink_info = {
-+      .description =  "Genesys GeneLink",
-+      .flags =        FLAG_POINTTOPOINT | FLAG_FRAMING_GL | FLAG_NO_SETINT,
-+      .bind =         genelink_bind,
-+      .rx_fixup =     genelink_rx_fixup,
-+      .tx_fixup =     genelink_tx_fixup,
-+
-+      .in = 1, .out = 2,
-+
-+#ifdef        GENELINK_ACK
-+      .check_connect =genelink_check_connect,
-+#endif
-+};
-+
-+static const struct usb_device_id     products [] = {
-+
-+{
-+      USB_DEVICE(0x05e3, 0x0502),     // GL620USB-A
-+      .driver_info =  (unsigned long) &genelink_info,
-+},
-+      /* NOT: USB_DEVICE(0x05e3, 0x0501),     // GL620USB
-+       * that's half duplex, not currently supported
-+       */
-+      { },            // END
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver gl620a_driver = {
-+      .name =         "gl620a",
-+      .id_table =     products,
-+      .probe =        usbnet_probe,
-+      .disconnect =   usbnet_disconnect,
-+      .suspend =      usbnet_suspend,
-+      .resume =       usbnet_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(gl620a_driver);
-+
-+MODULE_AUTHOR("Jiun-Jie Huang");
-+MODULE_DESCRIPTION("GL620-USB-A Host-to-Host Link cables");
-+MODULE_LICENSE("GPL");
-+
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/hso.c backports-4.2.6-1/drivers/net/usb/hso.c
---- backports-4.2.6-1.org/drivers/net/usb/hso.c        1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/hso.c    2016-06-28 14:35:17.981973887 +0200
-@@ -0,0 +1,3322 @@
-+/******************************************************************************
-+ *
-+ * Driver for Option High Speed Mobile Devices.
-+ *
-+ *  Copyright (C) 2008 Option International
-+ *                     Filip Aben <f.aben@option.com>
-+ *                     Denis Joseph Barrow <d.barow@option.com>
-+ *                     Jan Dumon <j.dumon@option.com>
-+ *  Copyright (C) 2007 Andrew Bird (Sphere Systems Ltd)
-+ *                    <ajb@spheresystems.co.uk>
-+ *  Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de>
-+ *  Copyright (C) 2008 Novell, Inc.
-+ *
-+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
-+ *  USA
-+ *
-+ *
-+ *****************************************************************************/
-+
-+/******************************************************************************
-+ *
-+ * Description of the device:
-+ *
-+ * Interface 0:       Contains the IP network interface on the bulk end points.
-+ *            The multiplexed serial ports are using the interrupt and
-+ *            control endpoints.
-+ *            Interrupt contains a bitmap telling which multiplexed
-+ *            serialport needs servicing.
-+ *
-+ * Interface 1:       Diagnostics port, uses bulk only, do not submit urbs until the
-+ *            port is opened, as this have a huge impact on the network port
-+ *            throughput.
-+ *
-+ * Interface 2:       Standard modem interface - circuit switched interface, this
-+ *            can be used to make a standard ppp connection however it
-+ *              should not be used in conjunction with the IP network interface
-+ *              enabled for USB performance reasons i.e. if using this set
-+ *              ideally disable_net=1.
-+ *
-+ *****************************************************************************/
-+
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/netdevice.h>
-+#include <linux/module.h>
-+#include <linux/ethtool.h>
-+#include <linux/usb.h>
-+#include <linux/tty.h>
-+#include <linux/tty_driver.h>
-+#include <linux/tty_flip.h>
-+#include <linux/kmod.h>
-+#include <linux/rfkill.h>
-+#include <linux/ip.h>
-+#include <linux/uaccess.h>
-+#include <linux/usb/cdc.h>
-+#include <net/arp.h>
-+#include <asm/byteorder.h>
-+#include <linux/serial_core.h>
-+#include <linux/serial.h>
-+#include <asm/local.h>
-+
-+#define MOD_AUTHOR                    "Option Wireless"
-+#define MOD_DESCRIPTION                       "USB High Speed Option driver"
-+#define MOD_LICENSE                   "GPL"
-+
-+#define HSO_MAX_NET_DEVICES           10
-+#define HSO__MAX_MTU                  2048
-+#define DEFAULT_MTU                   1500
-+#define DEFAULT_MRU                   1500
-+
-+#define CTRL_URB_RX_SIZE              1024
-+#define CTRL_URB_TX_SIZE              64
-+
-+#define BULK_URB_RX_SIZE              4096
-+#define BULK_URB_TX_SIZE              8192
-+
-+#define MUX_BULK_RX_BUF_SIZE          HSO__MAX_MTU
-+#define MUX_BULK_TX_BUF_SIZE          HSO__MAX_MTU
-+#define MUX_BULK_RX_BUF_COUNT         4
-+#define USB_TYPE_OPTION_VENDOR                0x20
-+
-+/* These definitions are used with the struct hso_net flags element */
-+/* - use *_bit operations on it. (bit indices not values.) */
-+#define HSO_NET_RUNNING                       0
-+
-+#define       HSO_NET_TX_TIMEOUT              (HZ*10)
-+
-+#define HSO_SERIAL_MAGIC              0x48534f31
-+
-+/* Number of ttys to handle */
-+#define HSO_SERIAL_TTY_MINORS         256
-+
-+#define MAX_RX_URBS                   2
-+
-+/*****************************************************************************/
-+/* Debugging functions                                                       */
-+/*****************************************************************************/
-+#define D__(lvl_, fmt, arg...)                                \
-+      do {                                            \
-+              printk(lvl_ "[%d:%s]: " fmt "\n",       \
-+                     __LINE__, __func__, ## arg);     \
-+      } while (0)
-+
-+#define D_(lvl, args...)                              \
-+      do {                                            \
-+              if (lvl & debug)                        \
-+                      D__(KERN_INFO, args);           \
-+      } while (0)
-+
-+#define D1(args...)   D_(0x01, ##args)
-+#define D2(args...)   D_(0x02, ##args)
-+#define D3(args...)   D_(0x04, ##args)
-+#define D4(args...)   D_(0x08, ##args)
-+#define D5(args...)   D_(0x10, ##args)
-+
-+/*****************************************************************************/
-+/* Enumerators                                                               */
-+/*****************************************************************************/
-+enum pkt_parse_state {
-+      WAIT_IP,
-+      WAIT_DATA,
-+      WAIT_SYNC
-+};
-+
-+/*****************************************************************************/
-+/* Structs                                                                   */
-+/*****************************************************************************/
-+
-+struct hso_shared_int {
-+      struct usb_endpoint_descriptor *intr_endp;
-+      void *shared_intr_buf;
-+      struct urb *shared_intr_urb;
-+      struct usb_device *usb;
-+      int use_count;
-+      int ref_count;
-+      struct mutex shared_int_lock;
-+};
-+
-+struct hso_net {
-+      struct hso_device *parent;
-+      struct net_device *net;
-+      struct rfkill *rfkill;
-+      char name[24];
-+
-+      struct usb_endpoint_descriptor *in_endp;
-+      struct usb_endpoint_descriptor *out_endp;
-+
-+      struct urb *mux_bulk_rx_urb_pool[MUX_BULK_RX_BUF_COUNT];
-+      struct urb *mux_bulk_tx_urb;
-+      void *mux_bulk_rx_buf_pool[MUX_BULK_RX_BUF_COUNT];
-+      void *mux_bulk_tx_buf;
-+
-+      struct sk_buff *skb_rx_buf;
-+      struct sk_buff *skb_tx_buf;
-+
-+      enum pkt_parse_state rx_parse_state;
-+      spinlock_t net_lock;
-+
-+      unsigned short rx_buf_size;
-+      unsigned short rx_buf_missing;
-+      struct iphdr rx_ip_hdr;
-+
-+      unsigned long flags;
-+};
-+
-+enum rx_ctrl_state{
-+      RX_IDLE,
-+      RX_SENT,
-+      RX_PENDING
-+};
-+
-+#define BM_REQUEST_TYPE (0xa1)
-+#define B_NOTIFICATION  (0x20)
-+#define W_VALUE         (0x0)
-+#define W_LENGTH        (0x2)
-+
-+#define B_OVERRUN       (0x1<<6)
-+#define B_PARITY        (0x1<<5)
-+#define B_FRAMING       (0x1<<4)
-+#define B_RING_SIGNAL   (0x1<<3)
-+#define B_BREAK         (0x1<<2)
-+#define B_TX_CARRIER    (0x1<<1)
-+#define B_RX_CARRIER    (0x1<<0)
-+
-+struct hso_serial_state_notification {
-+      u8 bmRequestType;
-+      u8 bNotification;
-+      u16 wValue;
-+      u16 wIndex;
-+      u16 wLength;
-+      u16 UART_state_bitmap;
-+} __packed;
-+
-+struct hso_tiocmget {
-+      struct mutex mutex;
-+      wait_queue_head_t waitq;
-+      int    intr_completed;
-+      struct usb_endpoint_descriptor *endp;
-+      struct urb *urb;
-+      struct hso_serial_state_notification serial_state_notification;
-+      u16    prev_UART_state_bitmap;
-+      struct uart_icount icount;
-+};
-+
-+
-+struct hso_serial {
-+      struct hso_device *parent;
-+      int magic;
-+      u8 minor;
-+
-+      struct hso_shared_int *shared_int;
-+
-+      /* rx/tx urb could be either a bulk urb or a control urb depending
-+         on which serial port it is used on. */
-+      struct urb *rx_urb[MAX_RX_URBS];
-+      u8 num_rx_urbs;
-+      u8 *rx_data[MAX_RX_URBS];
-+      u16 rx_data_length;     /* should contain allocated length */
-+
-+      struct urb *tx_urb;
-+      u8 *tx_data;
-+      u8 *tx_buffer;
-+      u16 tx_data_length;     /* should contain allocated length */
-+      u16 tx_data_count;
-+      u16 tx_buffer_count;
-+      struct usb_ctrlrequest ctrl_req_tx;
-+      struct usb_ctrlrequest ctrl_req_rx;
-+
-+      struct usb_endpoint_descriptor *in_endp;
-+      struct usb_endpoint_descriptor *out_endp;
-+
-+      enum rx_ctrl_state rx_state;
-+      u8 rts_state;
-+      u8 dtr_state;
-+      unsigned tx_urb_used:1;
-+
-+      struct tty_port port;
-+      /* from usb_serial_port */
-+      spinlock_t serial_lock;
-+
-+      int (*write_data) (struct hso_serial *serial);
-+      struct hso_tiocmget  *tiocmget;
-+      /* Hacks required to get flow control
-+       * working on the serial receive buffers
-+       * so as not to drop characters on the floor.
-+       */
-+      int  curr_rx_urb_idx;
-+      u8   rx_urb_filled[MAX_RX_URBS];
-+      struct tasklet_struct unthrottle_tasklet;
-+};
-+
-+struct hso_device {
-+      union {
-+              struct hso_serial *dev_serial;
-+              struct hso_net *dev_net;
-+      } port_data;
-+
-+      u32 port_spec;
-+
-+      u8 is_active;
-+      u8 usb_gone;
-+      struct work_struct async_get_intf;
-+      struct work_struct async_put_intf;
-+
-+      struct usb_device *usb;
-+      struct usb_interface *interface;
-+
-+      struct device *dev;
-+      struct kref ref;
-+      struct mutex mutex;
-+};
-+
-+/* Type of interface */
-+#define HSO_INTF_MASK         0xFF00
-+#define       HSO_INTF_MUX            0x0100
-+#define       HSO_INTF_BULK           0x0200
-+
-+/* Type of port */
-+#define HSO_PORT_MASK         0xFF
-+#define HSO_PORT_NO_PORT      0x0
-+#define       HSO_PORT_CONTROL        0x1
-+#define       HSO_PORT_APP            0x2
-+#define       HSO_PORT_GPS            0x3
-+#define       HSO_PORT_PCSC           0x4
-+#define       HSO_PORT_APP2           0x5
-+#define HSO_PORT_GPS_CONTROL  0x6
-+#define HSO_PORT_MSD          0x7
-+#define HSO_PORT_VOICE                0x8
-+#define HSO_PORT_DIAG2                0x9
-+#define       HSO_PORT_DIAG           0x10
-+#define       HSO_PORT_MODEM          0x11
-+#define       HSO_PORT_NETWORK        0x12
-+
-+/* Additional device info */
-+#define HSO_INFO_MASK         0xFF000000
-+#define HSO_INFO_CRC_BUG      0x01000000
-+
-+/*****************************************************************************/
-+/* Prototypes                                                                */
-+/*****************************************************************************/
-+/* Serial driver functions */
-+static int hso_serial_tiocmset(struct tty_struct *tty,
-+                             unsigned int set, unsigned int clear);
-+static void ctrl_callback(struct urb *urb);
-+static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial);
-+static void hso_kick_transmit(struct hso_serial *serial);
-+/* Helper functions */
-+static int hso_mux_submit_intr_urb(struct hso_shared_int *mux_int,
-+                                 struct usb_device *usb, gfp_t gfp);
-+static void handle_usb_error(int status, const char *function,
-+                           struct hso_device *hso_dev);
-+static struct usb_endpoint_descriptor *hso_get_ep(struct usb_interface *intf,
-+                                                int type, int dir);
-+static int hso_get_mux_ports(struct usb_interface *intf, unsigned char *ports);
-+static void hso_free_interface(struct usb_interface *intf);
-+static int hso_start_serial_device(struct hso_device *hso_dev, gfp_t flags);
-+static int hso_stop_serial_device(struct hso_device *hso_dev);
-+static int hso_start_net_device(struct hso_device *hso_dev);
-+static void hso_free_shared_int(struct hso_shared_int *shared_int);
-+static int hso_stop_net_device(struct hso_device *hso_dev);
-+static void hso_serial_ref_free(struct kref *ref);
-+static void hso_std_serial_read_bulk_callback(struct urb *urb);
-+static int hso_mux_serial_read(struct hso_serial *serial);
-+static void async_get_intf(struct work_struct *data);
-+static void async_put_intf(struct work_struct *data);
-+static int hso_put_activity(struct hso_device *hso_dev);
-+static int hso_get_activity(struct hso_device *hso_dev);
-+static void tiocmget_intr_callback(struct urb *urb);
-+/*****************************************************************************/
-+/* Helping functions                                                         */
-+/*****************************************************************************/
-+
-+/* #define DEBUG */
-+
-+static inline struct hso_net *dev2net(struct hso_device *hso_dev)
-+{
-+      return hso_dev->port_data.dev_net;
-+}
-+
-+static inline struct hso_serial *dev2ser(struct hso_device *hso_dev)
-+{
-+      return hso_dev->port_data.dev_serial;
-+}
-+
-+/* Debugging functions */
-+#ifdef DEBUG
-+static void dbg_dump(int line_count, const char *func_name, unsigned char *buf,
-+                   unsigned int len)
-+{
-+      static char name[255];
-+
-+      sprintf(name, "hso[%d:%s]", line_count, func_name);
-+      print_hex_dump_bytes(name, DUMP_PREFIX_NONE, buf, len);
-+}
-+
-+#define DUMP(buf_, len_)      \
-+      dbg_dump(__LINE__, __func__, (unsigned char *)buf_, len_)
-+
-+#define DUMP1(buf_, len_)                     \
-+      do {                                    \
-+              if (0x01 & debug)               \
-+                      DUMP(buf_, len_);       \
-+      } while (0)
-+#else
-+#define DUMP(buf_, len_)
-+#define DUMP1(buf_, len_)
-+#endif
-+
-+/* module parameters */
-+static int debug;
-+static int tty_major;
-+static int disable_net;
-+
-+/* driver info */
-+static const char driver_name[] = "hso";
-+static const char tty_filename[] = "ttyHS";
-+static const char *version = __FILE__ ": " MOD_AUTHOR;
-+/* the usb driver itself (registered in hso_init) */
-+static struct usb_driver hso_driver;
-+/* serial structures */
-+static struct tty_driver *tty_drv;
-+static struct hso_device *serial_table[HSO_SERIAL_TTY_MINORS];
-+static struct hso_device *network_table[HSO_MAX_NET_DEVICES];
-+static spinlock_t serial_table_lock;
-+
-+static const s32 default_port_spec[] = {
-+      HSO_INTF_MUX | HSO_PORT_NETWORK,
-+      HSO_INTF_BULK | HSO_PORT_DIAG,
-+      HSO_INTF_BULK | HSO_PORT_MODEM,
-+      0
-+};
-+
-+static const s32 icon321_port_spec[] = {
-+      HSO_INTF_MUX | HSO_PORT_NETWORK,
-+      HSO_INTF_BULK | HSO_PORT_DIAG2,
-+      HSO_INTF_BULK | HSO_PORT_MODEM,
-+      HSO_INTF_BULK | HSO_PORT_DIAG,
-+      0
-+};
-+
-+#define default_port_device(vendor, product)  \
-+      USB_DEVICE(vendor, product),    \
-+              .driver_info = (kernel_ulong_t)default_port_spec
-+
-+#define icon321_port_device(vendor, product)  \
-+      USB_DEVICE(vendor, product),    \
-+              .driver_info = (kernel_ulong_t)icon321_port_spec
-+
-+/* list of devices we support */
-+static const struct usb_device_id hso_ids[] = {
-+      {default_port_device(0x0af0, 0x6711)},
-+      {default_port_device(0x0af0, 0x6731)},
-+      {default_port_device(0x0af0, 0x6751)},
-+      {default_port_device(0x0af0, 0x6771)},
-+      {default_port_device(0x0af0, 0x6791)},
-+      {default_port_device(0x0af0, 0x6811)},
-+      {default_port_device(0x0af0, 0x6911)},
-+      {default_port_device(0x0af0, 0x6951)},
-+      {default_port_device(0x0af0, 0x6971)},
-+      {default_port_device(0x0af0, 0x7011)},
-+      {default_port_device(0x0af0, 0x7031)},
-+      {default_port_device(0x0af0, 0x7051)},
-+      {default_port_device(0x0af0, 0x7071)},
-+      {default_port_device(0x0af0, 0x7111)},
-+      {default_port_device(0x0af0, 0x7211)},
-+      {default_port_device(0x0af0, 0x7251)},
-+      {default_port_device(0x0af0, 0x7271)},
-+      {default_port_device(0x0af0, 0x7311)},
-+      {default_port_device(0x0af0, 0xc031)},  /* Icon-Edge */
-+      {icon321_port_device(0x0af0, 0xd013)},  /* Module HSxPA */
-+      {icon321_port_device(0x0af0, 0xd031)},  /* Icon-321 */
-+      {icon321_port_device(0x0af0, 0xd033)},  /* Icon-322 */
-+      {USB_DEVICE(0x0af0, 0x7301)},           /* GE40x */
-+      {USB_DEVICE(0x0af0, 0x7361)},           /* GE40x */
-+      {USB_DEVICE(0x0af0, 0x7381)},           /* GE40x */
-+      {USB_DEVICE(0x0af0, 0x7401)},           /* GI 0401 */
-+      {USB_DEVICE(0x0af0, 0x7501)},           /* GTM 382 */
-+      {USB_DEVICE(0x0af0, 0x7601)},           /* GE40x */
-+      {USB_DEVICE(0x0af0, 0x7701)},
-+      {USB_DEVICE(0x0af0, 0x7706)},
-+      {USB_DEVICE(0x0af0, 0x7801)},
-+      {USB_DEVICE(0x0af0, 0x7901)},
-+      {USB_DEVICE(0x0af0, 0x7A01)},
-+      {USB_DEVICE(0x0af0, 0x7A05)},
-+      {USB_DEVICE(0x0af0, 0x8200)},
-+      {USB_DEVICE(0x0af0, 0x8201)},
-+      {USB_DEVICE(0x0af0, 0x8300)},
-+      {USB_DEVICE(0x0af0, 0x8302)},
-+      {USB_DEVICE(0x0af0, 0x8304)},
-+      {USB_DEVICE(0x0af0, 0x8400)},
-+      {USB_DEVICE(0x0af0, 0x8600)},
-+      {USB_DEVICE(0x0af0, 0x8800)},
-+      {USB_DEVICE(0x0af0, 0x8900)},
-+      {USB_DEVICE(0x0af0, 0x9000)},
-+      {USB_DEVICE(0x0af0, 0x9200)},           /* Option GTM671WFS */
-+      {USB_DEVICE(0x0af0, 0xd035)},
-+      {USB_DEVICE(0x0af0, 0xd055)},
-+      {USB_DEVICE(0x0af0, 0xd155)},
-+      {USB_DEVICE(0x0af0, 0xd255)},
-+      {USB_DEVICE(0x0af0, 0xd057)},
-+      {USB_DEVICE(0x0af0, 0xd157)},
-+      {USB_DEVICE(0x0af0, 0xd257)},
-+      {USB_DEVICE(0x0af0, 0xd357)},
-+      {USB_DEVICE(0x0af0, 0xd058)},
-+      {USB_DEVICE(0x0af0, 0xc100)},
-+      {}
-+};
-+MODULE_DEVICE_TABLE(usb, hso_ids);
-+
-+/* Sysfs attribute */
-+static ssize_t hso_sysfs_show_porttype(struct device *dev,
-+                                     struct device_attribute *attr,
-+                                     char *buf)
-+{
-+      struct hso_device *hso_dev = dev_get_drvdata(dev);
-+      char *port_name;
-+
-+      if (!hso_dev)
-+              return 0;
-+
-+      switch (hso_dev->port_spec & HSO_PORT_MASK) {
-+      case HSO_PORT_CONTROL:
-+              port_name = "Control";
-+              break;
-+      case HSO_PORT_APP:
-+              port_name = "Application";
-+              break;
-+      case HSO_PORT_APP2:
-+              port_name = "Application2";
-+              break;
-+      case HSO_PORT_GPS:
-+              port_name = "GPS";
-+              break;
-+      case HSO_PORT_GPS_CONTROL:
-+              port_name = "GPS Control";
-+              break;
-+      case HSO_PORT_PCSC:
-+              port_name = "PCSC";
-+              break;
-+      case HSO_PORT_DIAG:
-+              port_name = "Diagnostic";
-+              break;
-+      case HSO_PORT_DIAG2:
-+              port_name = "Diagnostic2";
-+              break;
-+      case HSO_PORT_MODEM:
-+              port_name = "Modem";
-+              break;
-+      case HSO_PORT_NETWORK:
-+              port_name = "Network";
-+              break;
-+      default:
-+              port_name = "Unknown";
-+              break;
-+      }
-+
-+      return sprintf(buf, "%s\n", port_name);
-+}
-+static DEVICE_ATTR(hsotype, S_IRUGO, hso_sysfs_show_porttype, NULL);
-+
-+static struct attribute *hso_serial_dev_attrs[] = {
-+      &dev_attr_hsotype.attr,
-+      NULL
-+};
-+
-+ATTRIBUTE_GROUPS(hso_serial_dev);
-+
-+static int hso_urb_to_index(struct hso_serial *serial, struct urb *urb)
-+{
-+      int idx;
-+
-+      for (idx = 0; idx < serial->num_rx_urbs; idx++)
-+              if (serial->rx_urb[idx] == urb)
-+                      return idx;
-+      dev_err(serial->parent->dev, "hso_urb_to_index failed\n");
-+      return -1;
-+}
-+
-+/* converts mux value to a port spec value */
-+static u32 hso_mux_to_port(int mux)
-+{
-+      u32 result;
-+
-+      switch (mux) {
-+      case 0x1:
-+              result = HSO_PORT_CONTROL;
-+              break;
-+      case 0x2:
-+              result = HSO_PORT_APP;
-+              break;
-+      case 0x4:
-+              result = HSO_PORT_PCSC;
-+              break;
-+      case 0x8:
-+              result = HSO_PORT_GPS;
-+              break;
-+      case 0x10:
-+              result = HSO_PORT_APP2;
-+              break;
-+      default:
-+              result = HSO_PORT_NO_PORT;
-+      }
-+      return result;
-+}
-+
-+/* converts port spec value to a mux value */
-+static u32 hso_port_to_mux(int port)
-+{
-+      u32 result;
-+
-+      switch (port & HSO_PORT_MASK) {
-+      case HSO_PORT_CONTROL:
-+              result = 0x0;
-+              break;
-+      case HSO_PORT_APP:
-+              result = 0x1;
-+              break;
-+      case HSO_PORT_PCSC:
-+              result = 0x2;
-+              break;
-+      case HSO_PORT_GPS:
-+              result = 0x3;
-+              break;
-+      case HSO_PORT_APP2:
-+              result = 0x4;
-+              break;
-+      default:
-+              result = 0x0;
-+      }
-+      return result;
-+}
-+
-+static struct hso_serial *get_serial_by_shared_int_and_type(
-+                                      struct hso_shared_int *shared_int,
-+                                      int mux)
-+{
-+      int i, port;
-+
-+      port = hso_mux_to_port(mux);
-+
-+      for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {
-+              if (serial_table[i] &&
-+                  (dev2ser(serial_table[i])->shared_int == shared_int) &&
-+                  ((serial_table[i]->port_spec & HSO_PORT_MASK) == port)) {
-+                      return dev2ser(serial_table[i]);
-+              }
-+      }
-+
-+      return NULL;
-+}
-+
-+static struct hso_serial *get_serial_by_index(unsigned index)
-+{
-+      struct hso_serial *serial = NULL;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&serial_table_lock, flags);
-+      if (serial_table[index])
-+              serial = dev2ser(serial_table[index]);
-+      spin_unlock_irqrestore(&serial_table_lock, flags);
-+
-+      return serial;
-+}
-+
-+static int get_free_serial_index(void)
-+{
-+      int index;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&serial_table_lock, flags);
-+      for (index = 0; index < HSO_SERIAL_TTY_MINORS; index++) {
-+              if (serial_table[index] == NULL) {
-+                      spin_unlock_irqrestore(&serial_table_lock, flags);
-+                      return index;
-+              }
-+      }
-+      spin_unlock_irqrestore(&serial_table_lock, flags);
-+
-+      printk(KERN_ERR "%s: no free serial devices in table\n", __func__);
-+      return -1;
-+}
-+
-+static void set_serial_by_index(unsigned index, struct hso_serial *serial)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&serial_table_lock, flags);
-+      if (serial)
-+              serial_table[index] = serial->parent;
-+      else
-+              serial_table[index] = NULL;
-+      spin_unlock_irqrestore(&serial_table_lock, flags);
-+}
-+
-+static void handle_usb_error(int status, const char *function,
-+                           struct hso_device *hso_dev)
-+{
-+      char *explanation;
-+
-+      switch (status) {
-+      case -ENODEV:
-+              explanation = "no device";
-+              break;
-+      case -ENOENT:
-+              explanation = "endpoint not enabled";
-+              break;
-+      case -EPIPE:
-+              explanation = "endpoint stalled";
-+              break;
-+      case -ENOSPC:
-+              explanation = "not enough bandwidth";
-+              break;
-+      case -ESHUTDOWN:
-+              explanation = "device disabled";
-+              break;
-+      case -EHOSTUNREACH:
-+              explanation = "device suspended";
-+              break;
-+      case -EINVAL:
-+      case -EAGAIN:
-+      case -EFBIG:
-+      case -EMSGSIZE:
-+              explanation = "internal error";
-+              break;
-+      case -EILSEQ:
-+      case -EPROTO:
-+      case -ETIME:
-+      case -ETIMEDOUT:
-+              explanation = "protocol error";
-+              if (hso_dev)
-+                      usb_queue_reset_device(hso_dev->interface);
-+              break;
-+      default:
-+              explanation = "unknown status";
-+              break;
-+      }
-+
-+      /* log a meaningful explanation of an USB status */
-+      D1("%s: received USB status - %s (%d)", function, explanation, status);
-+}
-+
-+/* Network interface functions */
-+
-+/* called when net interface is brought up by ifconfig */
-+static int hso_net_open(struct net_device *net)
-+{
-+      struct hso_net *odev = netdev_priv(net);
-+      unsigned long flags = 0;
-+
-+      if (!odev) {
-+              dev_err(&net->dev, "No net device !\n");
-+              return -ENODEV;
-+      }
-+
-+      odev->skb_tx_buf = NULL;
-+
-+      /* setup environment */
-+      spin_lock_irqsave(&odev->net_lock, flags);
-+      odev->rx_parse_state = WAIT_IP;
-+      odev->rx_buf_size = 0;
-+      odev->rx_buf_missing = sizeof(struct iphdr);
-+      spin_unlock_irqrestore(&odev->net_lock, flags);
-+
-+      /* We are up and running. */
-+      set_bit(HSO_NET_RUNNING, &odev->flags);
-+      hso_start_net_device(odev->parent);
-+
-+      /* Tell the kernel we are ready to start receiving from it */
-+      netif_start_queue(net);
-+
-+      return 0;
-+}
-+
-+/* called when interface is brought down by ifconfig */
-+static int hso_net_close(struct net_device *net)
-+{
-+      struct hso_net *odev = netdev_priv(net);
-+
-+      /* we don't need the queue anymore */
-+      netif_stop_queue(net);
-+      /* no longer running */
-+      clear_bit(HSO_NET_RUNNING, &odev->flags);
-+
-+      hso_stop_net_device(odev->parent);
-+
-+      /* done */
-+      return 0;
-+}
-+
-+/* USB tells is xmit done, we should start the netqueue again */
-+static void write_bulk_callback(struct urb *urb)
-+{
-+      struct hso_net *odev = urb->context;
-+      int status = urb->status;
-+
-+      /* Sanity check */
-+      if (!odev || !test_bit(HSO_NET_RUNNING, &odev->flags)) {
-+              dev_err(&urb->dev->dev, "%s: device not running\n", __func__);
-+              return;
-+      }
-+
-+      /* Do we still have a valid kernel network device? */
-+      if (!netif_device_present(odev->net)) {
-+              dev_err(&urb->dev->dev, "%s: net device not present\n",
-+                      __func__);
-+              return;
-+      }
-+
-+      /* log status, but don't act on it, we don't need to resubmit anything
-+       * anyhow */
-+      if (status)
-+              handle_usb_error(status, __func__, odev->parent);
-+
-+      hso_put_activity(odev->parent);
-+
-+      /* Tell the network interface we are ready for another frame */
-+      netif_wake_queue(odev->net);
-+}
-+
-+/* called by kernel when we need to transmit a packet */
-+static netdev_tx_t hso_net_start_xmit(struct sk_buff *skb,
-+                                          struct net_device *net)
-+{
-+      struct hso_net *odev = netdev_priv(net);
-+      int result;
-+
-+      /* Tell the kernel, "No more frames 'til we are done with this one." */
-+      netif_stop_queue(net);
-+      if (hso_get_activity(odev->parent) == -EAGAIN) {
-+              odev->skb_tx_buf = skb;
-+              return NETDEV_TX_OK;
-+      }
-+
-+      /* log if asked */
-+      DUMP1(skb->data, skb->len);
-+      /* Copy it from kernel memory to OUR memory */
-+      memcpy(odev->mux_bulk_tx_buf, skb->data, skb->len);
-+      D1("len: %d/%d", skb->len, MUX_BULK_TX_BUF_SIZE);
-+
-+      /* Fill in the URB for shipping it out. */
-+      usb_fill_bulk_urb(odev->mux_bulk_tx_urb,
-+                        odev->parent->usb,
-+                        usb_sndbulkpipe(odev->parent->usb,
-+                                        odev->out_endp->
-+                                        bEndpointAddress & 0x7F),
-+                        odev->mux_bulk_tx_buf, skb->len, write_bulk_callback,
-+                        odev);
-+
-+      /* Deal with the Zero Length packet problem, I hope */
-+      odev->mux_bulk_tx_urb->transfer_flags |= URB_ZERO_PACKET;
-+
-+      /* Send the URB on its merry way. */
-+      result = usb_submit_urb(odev->mux_bulk_tx_urb, GFP_ATOMIC);
-+      if (result) {
-+              dev_warn(&odev->parent->interface->dev,
-+                      "failed mux_bulk_tx_urb %d\n", result);
-+              net->stats.tx_errors++;
-+              netif_start_queue(net);
-+      } else {
-+              net->stats.tx_packets++;
-+              net->stats.tx_bytes += skb->len;
-+      }
-+      dev_kfree_skb(skb);
-+      /* we're done */
-+      return NETDEV_TX_OK;
-+}
-+
-+static const struct ethtool_ops ops = {
-+      .get_link = ethtool_op_get_link
-+};
-+
-+/* called when a packet did not ack after watchdogtimeout */
-+static void hso_net_tx_timeout(struct net_device *net)
-+{
-+      struct hso_net *odev = netdev_priv(net);
-+
-+      if (!odev)
-+              return;
-+
-+      /* Tell syslog we are hosed. */
-+      dev_warn(&net->dev, "Tx timed out.\n");
-+
-+      /* Tear the waiting frame off the list */
-+      if (odev->mux_bulk_tx_urb &&
-+          (odev->mux_bulk_tx_urb->status == -EINPROGRESS))
-+              usb_unlink_urb(odev->mux_bulk_tx_urb);
-+
-+      /* Update statistics */
-+      net->stats.tx_errors++;
-+}
-+
-+/* make a real packet from the received USB buffer */
-+static void packetizeRx(struct hso_net *odev, unsigned char *ip_pkt,
-+                      unsigned int count, unsigned char is_eop)
-+{
-+      unsigned short temp_bytes;
-+      unsigned short buffer_offset = 0;
-+      unsigned short frame_len;
-+      unsigned char *tmp_rx_buf;
-+
-+      /* log if needed */
-+      D1("Rx %d bytes", count);
-+      DUMP(ip_pkt, min(128, (int)count));
-+
-+      while (count) {
-+              switch (odev->rx_parse_state) {
-+              case WAIT_IP:
-+                      /* waiting for IP header. */
-+                      /* wanted bytes - size of ip header */
-+                      temp_bytes =
-+                          (count <
-+                           odev->rx_buf_missing) ? count : odev->
-+                          rx_buf_missing;
-+
-+                      memcpy(((unsigned char *)(&odev->rx_ip_hdr)) +
-+                             odev->rx_buf_size, ip_pkt + buffer_offset,
-+                             temp_bytes);
-+
-+                      odev->rx_buf_size += temp_bytes;
-+                      buffer_offset += temp_bytes;
-+                      odev->rx_buf_missing -= temp_bytes;
-+                      count -= temp_bytes;
-+
-+                      if (!odev->rx_buf_missing) {
-+                              /* header is complete allocate an sk_buffer and
-+                               * continue to WAIT_DATA */
-+                              frame_len = ntohs(odev->rx_ip_hdr.tot_len);
-+
-+                              if ((frame_len > DEFAULT_MRU) ||
-+                                  (frame_len < sizeof(struct iphdr))) {
-+                                      dev_err(&odev->net->dev,
-+                                              "Invalid frame (%d) length\n",
-+                                              frame_len);
-+                                      odev->rx_parse_state = WAIT_SYNC;
-+                                      continue;
-+                              }
-+                              /* Allocate an sk_buff */
-+                              odev->skb_rx_buf = netdev_alloc_skb(odev->net,
-+                                                                  frame_len);
-+                              if (!odev->skb_rx_buf) {
-+                                      /* We got no receive buffer. */
-+                                      D1("could not allocate memory");
-+                                      odev->rx_parse_state = WAIT_SYNC;
-+                                      continue;
-+                              }
-+
-+                              /* Copy what we got so far. make room for iphdr
-+                               * after tail. */
-+                              tmp_rx_buf =
-+                                  skb_put(odev->skb_rx_buf,
-+                                          sizeof(struct iphdr));
-+                              memcpy(tmp_rx_buf, (char *)&(odev->rx_ip_hdr),
-+                                     sizeof(struct iphdr));
-+
-+                              /* ETH_HLEN */
-+                              odev->rx_buf_size = sizeof(struct iphdr);
-+
-+                              /* Filip actually use .tot_len */
-+                              odev->rx_buf_missing =
-+                                  frame_len - sizeof(struct iphdr);
-+                              odev->rx_parse_state = WAIT_DATA;
-+                      }
-+                      break;
-+
-+              case WAIT_DATA:
-+                      temp_bytes = (count < odev->rx_buf_missing)
-+                                      ? count : odev->rx_buf_missing;
-+
-+                      /* Copy the rest of the bytes that are left in the
-+                       * buffer into the waiting sk_buf. */
-+                      /* Make room for temp_bytes after tail. */
-+                      tmp_rx_buf = skb_put(odev->skb_rx_buf, temp_bytes);
-+                      memcpy(tmp_rx_buf, ip_pkt + buffer_offset, temp_bytes);
-+
-+                      odev->rx_buf_missing -= temp_bytes;
-+                      count -= temp_bytes;
-+                      buffer_offset += temp_bytes;
-+                      odev->rx_buf_size += temp_bytes;
-+                      if (!odev->rx_buf_missing) {
-+                              /* Packet is complete. Inject into stack. */
-+                              /* We have IP packet here */
-+                              odev->skb_rx_buf->protocol = cpu_to_be16(ETH_P_IP);
-+                              skb_reset_mac_header(odev->skb_rx_buf);
-+
-+                              /* Ship it off to the kernel */
-+                              netif_rx(odev->skb_rx_buf);
-+                              /* No longer our buffer. */
-+                              odev->skb_rx_buf = NULL;
-+
-+                              /* update out statistics */
-+                              odev->net->stats.rx_packets++;
-+
-+                              odev->net->stats.rx_bytes += odev->rx_buf_size;
-+
-+                              odev->rx_buf_size = 0;
-+                              odev->rx_buf_missing = sizeof(struct iphdr);
-+                              odev->rx_parse_state = WAIT_IP;
-+                      }
-+                      break;
-+
-+              case WAIT_SYNC:
-+                      D1(" W_S");
-+                      count = 0;
-+                      break;
-+              default:
-+                      D1(" ");
-+                      count--;
-+                      break;
-+              }
-+      }
-+
-+      /* Recovery mechanism for WAIT_SYNC state. */
-+      if (is_eop) {
-+              if (odev->rx_parse_state == WAIT_SYNC) {
-+                      odev->rx_parse_state = WAIT_IP;
-+                      odev->rx_buf_size = 0;
-+                      odev->rx_buf_missing = sizeof(struct iphdr);
-+              }
-+      }
-+}
-+
-+static void fix_crc_bug(struct urb *urb, __le16 max_packet_size)
-+{
-+      static const u8 crc_check[4] = { 0xDE, 0xAD, 0xBE, 0xEF };
-+      u32 rest = urb->actual_length % le16_to_cpu(max_packet_size);
-+
-+      if (((rest == 5) || (rest == 6)) &&
-+          !memcmp(((u8 *)urb->transfer_buffer) + urb->actual_length - 4,
-+                  crc_check, 4)) {
-+              urb->actual_length -= 4;
-+      }
-+}
-+
-+/* Moving data from usb to kernel (in interrupt state) */
-+static void read_bulk_callback(struct urb *urb)
-+{
-+      struct hso_net *odev = urb->context;
-+      struct net_device *net;
-+      int result;
-+      int status = urb->status;
-+
-+      /* is al ok?  (Filip: Who's Al ?) */
-+      if (status) {
-+              handle_usb_error(status, __func__, odev->parent);
-+              return;
-+      }
-+
-+      /* Sanity check */
-+      if (!odev || !test_bit(HSO_NET_RUNNING, &odev->flags)) {
-+              D1("BULK IN callback but driver is not active!");
-+              return;
-+      }
-+      usb_mark_last_busy(urb->dev);
-+
-+      net = odev->net;
-+
-+      if (!netif_device_present(net)) {
-+              /* Somebody killed our network interface... */
-+              return;
-+      }
-+
-+      if (odev->parent->port_spec & HSO_INFO_CRC_BUG)
-+              fix_crc_bug(urb, odev->in_endp->wMaxPacketSize);
-+
-+      /* do we even have a packet? */
-+      if (urb->actual_length) {
-+              /* Handle the IP stream, add header and push it onto network
-+               * stack if the packet is complete. */
-+              spin_lock(&odev->net_lock);
-+              packetizeRx(odev, urb->transfer_buffer, urb->actual_length,
-+                          (urb->transfer_buffer_length >
-+                           urb->actual_length) ? 1 : 0);
-+              spin_unlock(&odev->net_lock);
-+      }
-+
-+      /* We are done with this URB, resubmit it. Prep the USB to wait for
-+       * another frame. Reuse same as received. */
-+      usb_fill_bulk_urb(urb,
-+                        odev->parent->usb,
-+                        usb_rcvbulkpipe(odev->parent->usb,
-+                                        odev->in_endp->
-+                                        bEndpointAddress & 0x7F),
-+                        urb->transfer_buffer, MUX_BULK_RX_BUF_SIZE,
-+                        read_bulk_callback, odev);
-+
-+      /* Give this to the USB subsystem so it can tell us when more data
-+       * arrives. */
-+      result = usb_submit_urb(urb, GFP_ATOMIC);
-+      if (result)
-+              dev_warn(&odev->parent->interface->dev,
-+                       "%s failed submit mux_bulk_rx_urb %d\n", __func__,
-+                       result);
-+}
-+
-+/* Serial driver functions */
-+
-+static void hso_init_termios(struct ktermios *termios)
-+{
-+      /*
-+       * The default requirements for this device are:
-+       */
-+      termios->c_iflag &=
-+              ~(IGNBRK        /* disable ignore break */
-+              | BRKINT        /* disable break causes interrupt */
-+              | PARMRK        /* disable mark parity errors */
-+              | ISTRIP        /* disable clear high bit of input characters */
-+              | INLCR         /* disable translate NL to CR */
-+              | IGNCR         /* disable ignore CR */
-+              | ICRNL         /* disable translate CR to NL */
-+              | IXON);        /* disable enable XON/XOFF flow control */
-+
-+      /* disable postprocess output characters */
-+      termios->c_oflag &= ~OPOST;
-+
-+      termios->c_lflag &=
-+              ~(ECHO          /* disable echo input characters */
-+              | ECHONL        /* disable echo new line */
-+              | ICANON        /* disable erase, kill, werase, and rprnt
-+                                 special characters */
-+              | ISIG          /* disable interrupt, quit, and suspend special
-+                                 characters */
-+              | IEXTEN);      /* disable non-POSIX special characters */
-+
-+      termios->c_cflag &=
-+              ~(CSIZE         /* no size */
-+              | PARENB        /* disable parity bit */
-+              | CBAUD         /* clear current baud rate */
-+              | CBAUDEX);     /* clear current buad rate */
-+
-+      termios->c_cflag |= CS8;        /* character size 8 bits */
-+
-+      /* baud rate 115200 */
-+      tty_termios_encode_baud_rate(termios, 115200, 115200);
-+}
-+
-+static void _hso_serial_set_termios(struct tty_struct *tty,
-+                                  struct ktermios *old)
-+{
-+      struct hso_serial *serial = tty->driver_data;
-+
-+      if (!serial) {
-+              printk(KERN_ERR "%s: no tty structures", __func__);
-+              return;
-+      }
-+
-+      D4("port %d", serial->minor);
-+
-+      /*
-+       *      Fix up unsupported bits
-+       */
-+      tty->termios.c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */
-+
-+      tty->termios.c_cflag &=
-+              ~(CSIZE         /* no size */
-+              | PARENB        /* disable parity bit */
-+              | CBAUD         /* clear current baud rate */
-+              | CBAUDEX);     /* clear current buad rate */
-+
-+      tty->termios.c_cflag |= CS8;    /* character size 8 bits */
-+
-+      /* baud rate 115200 */
-+      tty_encode_baud_rate(tty, 115200, 115200);
-+}
-+
-+static void hso_resubmit_rx_bulk_urb(struct hso_serial *serial, struct urb *urb)
-+{
-+      int result;
-+      /* We are done with this URB, resubmit it. Prep the USB to wait for
-+       * another frame */
-+      usb_fill_bulk_urb(urb, serial->parent->usb,
-+                        usb_rcvbulkpipe(serial->parent->usb,
-+                                        serial->in_endp->
-+                                        bEndpointAddress & 0x7F),
-+                        urb->transfer_buffer, serial->rx_data_length,
-+                        hso_std_serial_read_bulk_callback, serial);
-+      /* Give this to the USB subsystem so it can tell us when more data
-+       * arrives. */
-+      result = usb_submit_urb(urb, GFP_ATOMIC);
-+      if (result) {
-+              dev_err(&urb->dev->dev, "%s failed submit serial rx_urb %d\n",
-+                      __func__, result);
-+      }
-+}
-+
-+
-+
-+
-+static void put_rxbuf_data_and_resubmit_bulk_urb(struct hso_serial *serial)
-+{
-+      int count;
-+      struct urb *curr_urb;
-+
-+      while (serial->rx_urb_filled[serial->curr_rx_urb_idx]) {
-+              curr_urb = serial->rx_urb[serial->curr_rx_urb_idx];
-+              count = put_rxbuf_data(curr_urb, serial);
-+              if (count == -1)
-+                      return;
-+              if (count == 0) {
-+                      serial->curr_rx_urb_idx++;
-+                      if (serial->curr_rx_urb_idx >= serial->num_rx_urbs)
-+                              serial->curr_rx_urb_idx = 0;
-+                      hso_resubmit_rx_bulk_urb(serial, curr_urb);
-+              }
-+      }
-+}
-+
-+static void put_rxbuf_data_and_resubmit_ctrl_urb(struct hso_serial *serial)
-+{
-+      int count = 0;
-+      struct urb *urb;
-+
-+      urb = serial->rx_urb[0];
-+      if (atomic_read(&serial->port.count) > 0) {
-+              count = put_rxbuf_data(urb, serial);
-+              if (count == -1)
-+                      return;
-+      }
-+      /* Re issue a read as long as we receive data. */
-+
-+      if (count == 0 && ((urb->actual_length != 0) ||
-+                         (serial->rx_state == RX_PENDING))) {
-+              serial->rx_state = RX_SENT;
-+              hso_mux_serial_read(serial);
-+      } else
-+              serial->rx_state = RX_IDLE;
-+}
-+
-+
-+/* read callback for Diag and CS port */
-+static void hso_std_serial_read_bulk_callback(struct urb *urb)
-+{
-+      struct hso_serial *serial = urb->context;
-+      int status = urb->status;
-+
-+      D4("\n--- Got serial_read_bulk callback %02x ---", status);
-+
-+      /* sanity check */
-+      if (!serial) {
-+              D1("serial == NULL");
-+              return;
-+      }
-+      if (status) {
-+              handle_usb_error(status, __func__, serial->parent);
-+              return;
-+      }
-+
-+      D1("Actual length = %d\n", urb->actual_length);
-+      DUMP1(urb->transfer_buffer, urb->actual_length);
-+
-+      /* Anyone listening? */
-+      if (atomic_read(&serial->port.count) == 0)
-+              return;
-+
-+      if (serial->parent->port_spec & HSO_INFO_CRC_BUG)
-+              fix_crc_bug(urb, serial->in_endp->wMaxPacketSize);
-+      /* Valid data, handle RX data */
-+      spin_lock(&serial->serial_lock);
-+      serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1;
-+      put_rxbuf_data_and_resubmit_bulk_urb(serial);
-+      spin_unlock(&serial->serial_lock);
-+}
-+
-+/*
-+ * This needs to be a tasklet otherwise we will
-+ * end up recursively calling this function.
-+ */
-+static void hso_unthrottle_tasklet(struct hso_serial *serial)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&serial->serial_lock, flags);
-+      if ((serial->parent->port_spec & HSO_INTF_MUX))
-+              put_rxbuf_data_and_resubmit_ctrl_urb(serial);
-+      else
-+              put_rxbuf_data_and_resubmit_bulk_urb(serial);
-+      spin_unlock_irqrestore(&serial->serial_lock, flags);
-+}
-+
-+static        void hso_unthrottle(struct tty_struct *tty)
-+{
-+      struct hso_serial *serial = tty->driver_data;
-+
-+      tasklet_hi_schedule(&serial->unthrottle_tasklet);
-+}
-+
-+/* open the requested serial port */
-+static int hso_serial_open(struct tty_struct *tty, struct file *filp)
-+{
-+      struct hso_serial *serial = get_serial_by_index(tty->index);
-+      int result;
-+
-+      /* sanity check */
-+      if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) {
-+              WARN_ON(1);
-+              tty->driver_data = NULL;
-+              D1("Failed to open port");
-+              return -ENODEV;
-+      }
-+
-+      mutex_lock(&serial->parent->mutex);
-+      result = usb_autopm_get_interface(serial->parent->interface);
-+      if (result < 0)
-+              goto err_out;
-+
-+      D1("Opening %d", serial->minor);
-+
-+      /* setup */
-+      tty->driver_data = serial;
-+      tty_port_tty_set(&serial->port, tty);
-+
-+      /* check for port already opened, if not set the termios */
-+      if (atomic_inc_return(&serial->port.count) == 1) {
-+              serial->rx_state = RX_IDLE;
-+              /* Force default termio settings */
-+              _hso_serial_set_termios(tty, NULL);
-+              tasklet_init(&serial->unthrottle_tasklet,
-+                           (void (*)(unsigned long))hso_unthrottle_tasklet,
-+                           (unsigned long)serial);
-+              result = hso_start_serial_device(serial->parent, GFP_KERNEL);
-+              if (result) {
-+                      hso_stop_serial_device(serial->parent);
-+                      atomic_dec(&serial->port.count);
-+              } else {
-+                      kref_get(&serial->parent->ref);
-+              }
-+      } else {
-+              D1("Port was already open");
-+      }
-+
-+      usb_autopm_put_interface(serial->parent->interface);
-+
-+      /* done */
-+      if (result)
-+              hso_serial_tiocmset(tty, TIOCM_RTS | TIOCM_DTR, 0);
-+err_out:
-+      mutex_unlock(&serial->parent->mutex);
-+      return result;
-+}
-+
-+/* close the requested serial port */
-+static void hso_serial_close(struct tty_struct *tty, struct file *filp)
-+{
-+      struct hso_serial *serial = tty->driver_data;
-+      u8 usb_gone;
-+
-+      D1("Closing serial port");
-+
-+      /* Open failed, no close cleanup required */
-+      if (serial == NULL)
-+              return;
-+
-+      mutex_lock(&serial->parent->mutex);
-+      usb_gone = serial->parent->usb_gone;
-+
-+      if (!usb_gone)
-+              usb_autopm_get_interface(serial->parent->interface);
-+
-+      /* reset the rts and dtr */
-+      /* do the actual close */
-+      atomic_dec(&serial->port.count);
-+
-+      if (atomic_read(&serial->port.count) <= 0) {
-+              atomic_set(&serial->port.count, 0);
-+              tty_port_tty_set(&serial->port, NULL);
-+              if (!usb_gone)
-+                      hso_stop_serial_device(serial->parent);
-+              tasklet_kill(&serial->unthrottle_tasklet);
-+      }
-+
-+      if (!usb_gone)
-+              usb_autopm_put_interface(serial->parent->interface);
-+
-+      mutex_unlock(&serial->parent->mutex);
-+}
-+
-+/* close the requested serial port */
-+static int hso_serial_write(struct tty_struct *tty, const unsigned char *buf,
-+                          int count)
-+{
-+      struct hso_serial *serial = tty->driver_data;
-+      int space, tx_bytes;
-+      unsigned long flags;
-+
-+      /* sanity check */
-+      if (serial == NULL) {
-+              printk(KERN_ERR "%s: serial is NULL\n", __func__);
-+              return -ENODEV;
-+      }
-+
-+      spin_lock_irqsave(&serial->serial_lock, flags);
-+
-+      space = serial->tx_data_length - serial->tx_buffer_count;
-+      tx_bytes = (count < space) ? count : space;
-+
-+      if (!tx_bytes)
-+              goto out;
-+
-+      memcpy(serial->tx_buffer + serial->tx_buffer_count, buf, tx_bytes);
-+      serial->tx_buffer_count += tx_bytes;
-+
-+out:
-+      spin_unlock_irqrestore(&serial->serial_lock, flags);
-+
-+      hso_kick_transmit(serial);
-+      /* done */
-+      return tx_bytes;
-+}
-+
-+/* how much room is there for writing */
-+static int hso_serial_write_room(struct tty_struct *tty)
-+{
-+      struct hso_serial *serial = tty->driver_data;
-+      int room;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&serial->serial_lock, flags);
-+      room = serial->tx_data_length - serial->tx_buffer_count;
-+      spin_unlock_irqrestore(&serial->serial_lock, flags);
-+
-+      /* return free room */
-+      return room;
-+}
-+
-+static void hso_serial_cleanup(struct tty_struct *tty)
-+{
-+      struct hso_serial *serial = tty->driver_data;
-+
-+      if (!serial)
-+              return;
-+
-+      kref_put(&serial->parent->ref, hso_serial_ref_free);
-+}
-+
-+/* setup the term */
-+static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old)
-+{
-+      struct hso_serial *serial = tty->driver_data;
-+      unsigned long flags;
-+
-+      if (old)
-+              D5("Termios called with: cflags new[%d] - old[%d]",
-+                 tty->termios.c_cflag, old->c_cflag);
-+
-+      /* the actual setup */
-+      spin_lock_irqsave(&serial->serial_lock, flags);
-+      if (atomic_read(&serial->port.count))
-+              _hso_serial_set_termios(tty, old);
-+      else
-+              tty->termios = *old;
-+      spin_unlock_irqrestore(&serial->serial_lock, flags);
-+
-+      /* done */
-+}
-+
-+/* how many characters in the buffer */
-+static int hso_serial_chars_in_buffer(struct tty_struct *tty)
-+{
-+      struct hso_serial *serial = tty->driver_data;
-+      int chars;
-+      unsigned long flags;
-+
-+      /* sanity check */
-+      if (serial == NULL)
-+              return 0;
-+
-+      spin_lock_irqsave(&serial->serial_lock, flags);
-+      chars = serial->tx_buffer_count;
-+      spin_unlock_irqrestore(&serial->serial_lock, flags);
-+
-+      return chars;
-+}
-+static int tiocmget_submit_urb(struct hso_serial *serial,
-+                             struct hso_tiocmget *tiocmget,
-+                             struct usb_device *usb)
-+{
-+      int result;
-+
-+      if (serial->parent->usb_gone)
-+              return -ENODEV;
-+      usb_fill_int_urb(tiocmget->urb, usb,
-+                       usb_rcvintpipe(usb,
-+                                      tiocmget->endp->
-+                                      bEndpointAddress & 0x7F),
-+                       &tiocmget->serial_state_notification,
-+                       sizeof(struct hso_serial_state_notification),
-+                       tiocmget_intr_callback, serial,
-+                       tiocmget->endp->bInterval);
-+      result = usb_submit_urb(tiocmget->urb, GFP_ATOMIC);
-+      if (result) {
-+              dev_warn(&usb->dev, "%s usb_submit_urb failed %d\n", __func__,
-+                       result);
-+      }
-+      return result;
-+
-+}
-+
-+static void tiocmget_intr_callback(struct urb *urb)
-+{
-+      struct hso_serial *serial = urb->context;
-+      struct hso_tiocmget *tiocmget;
-+      int status = urb->status;
-+      u16 UART_state_bitmap, prev_UART_state_bitmap;
-+      struct uart_icount *icount;
-+      struct hso_serial_state_notification *serial_state_notification;
-+      struct usb_device *usb;
-+      struct usb_interface *interface;
-+      int if_num;
-+
-+      /* Sanity checks */
-+      if (!serial)
-+              return;
-+      if (status) {
-+              handle_usb_error(status, __func__, serial->parent);
-+              return;
-+      }
-+
-+      /* tiocmget is only supported on HSO_PORT_MODEM */
-+      tiocmget = serial->tiocmget;
-+      if (!tiocmget)
-+              return;
-+      BUG_ON((serial->parent->port_spec & HSO_PORT_MASK) != HSO_PORT_MODEM);
-+
-+      usb = serial->parent->usb;
-+      interface = serial->parent->interface;
-+
-+      if_num = interface->cur_altsetting->desc.bInterfaceNumber;
-+
-+      /* wIndex should be the USB interface number of the port to which the
-+       * notification applies, which should always be the Modem port.
-+       */
-+      serial_state_notification = &tiocmget->serial_state_notification;
-+      if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE ||
-+          serial_state_notification->bNotification != B_NOTIFICATION ||
-+          le16_to_cpu(serial_state_notification->wValue) != W_VALUE ||
-+          le16_to_cpu(serial_state_notification->wIndex) != if_num ||
-+          le16_to_cpu(serial_state_notification->wLength) != W_LENGTH) {
-+              dev_warn(&usb->dev,
-+                       "hso received invalid serial state notification\n");
-+              DUMP(serial_state_notification,
-+                   sizeof(struct hso_serial_state_notification));
-+      } else {
-+
-+              UART_state_bitmap = le16_to_cpu(serial_state_notification->
-+                                              UART_state_bitmap);
-+              prev_UART_state_bitmap = tiocmget->prev_UART_state_bitmap;
-+              icount = &tiocmget->icount;
-+              spin_lock(&serial->serial_lock);
-+              if ((UART_state_bitmap & B_OVERRUN) !=
-+                 (prev_UART_state_bitmap & B_OVERRUN))
-+                      icount->parity++;
-+              if ((UART_state_bitmap & B_PARITY) !=
-+                 (prev_UART_state_bitmap & B_PARITY))
-+                      icount->parity++;
-+              if ((UART_state_bitmap & B_FRAMING) !=
-+                 (prev_UART_state_bitmap & B_FRAMING))
-+                      icount->frame++;
-+              if ((UART_state_bitmap & B_RING_SIGNAL) &&
-+                 !(prev_UART_state_bitmap & B_RING_SIGNAL))
-+                      icount->rng++;
-+              if ((UART_state_bitmap & B_BREAK) !=
-+                 (prev_UART_state_bitmap & B_BREAK))
-+                      icount->brk++;
-+              if ((UART_state_bitmap & B_TX_CARRIER) !=
-+                 (prev_UART_state_bitmap & B_TX_CARRIER))
-+                      icount->dsr++;
-+              if ((UART_state_bitmap & B_RX_CARRIER) !=
-+                 (prev_UART_state_bitmap & B_RX_CARRIER))
-+                      icount->dcd++;
-+              tiocmget->prev_UART_state_bitmap = UART_state_bitmap;
-+              spin_unlock(&serial->serial_lock);
-+              tiocmget->intr_completed = 1;
-+              wake_up_interruptible(&tiocmget->waitq);
-+      }
-+      memset(serial_state_notification, 0,
-+             sizeof(struct hso_serial_state_notification));
-+      tiocmget_submit_urb(serial,
-+                          tiocmget,
-+                          serial->parent->usb);
-+}
-+
-+/*
-+ * next few functions largely stolen from drivers/serial/serial_core.c
-+ */
-+/* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-+ * - mask passed in arg for lines of interest
-+ *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-+ * Caller should use TIOCGICOUNT to see which one it was
-+ */
-+static int
-+hso_wait_modem_status(struct hso_serial *serial, unsigned long arg)
-+{
-+      DECLARE_WAITQUEUE(wait, current);
-+      struct uart_icount cprev, cnow;
-+      struct hso_tiocmget  *tiocmget;
-+      int ret;
-+
-+      tiocmget = serial->tiocmget;
-+      if (!tiocmget)
-+              return -ENOENT;
-+      /*
-+       * note the counters on entry
-+       */
-+      spin_lock_irq(&serial->serial_lock);
-+      memcpy(&cprev, &tiocmget->icount, sizeof(struct uart_icount));
-+      spin_unlock_irq(&serial->serial_lock);
-+      add_wait_queue(&tiocmget->waitq, &wait);
-+      for (;;) {
-+              spin_lock_irq(&serial->serial_lock);
-+              memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount));
-+              spin_unlock_irq(&serial->serial_lock);
-+              set_current_state(TASK_INTERRUPTIBLE);
-+              if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-+                  ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-+                  ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd))) {
-+                      ret = 0;
-+                      break;
-+              }
-+              schedule();
-+              /* see if a signal did it */
-+              if (signal_pending(current)) {
-+                      ret = -ERESTARTSYS;
-+                      break;
-+              }
-+              cprev = cnow;
-+      }
-+      __set_current_state(TASK_RUNNING);
-+      remove_wait_queue(&tiocmget->waitq, &wait);
-+
-+      return ret;
-+}
-+
-+/*
-+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-+ * Return: write counters to the user passed counter struct
-+ * NB: both 1->0 and 0->1 transitions are counted except for
-+ *     RI where only 0->1 is counted.
-+ */
-+static int hso_get_count(struct tty_struct *tty,
-+                struct serial_icounter_struct *icount)
-+{
-+      struct uart_icount cnow;
-+      struct hso_serial *serial = tty->driver_data;
-+      struct hso_tiocmget  *tiocmget = serial->tiocmget;
-+
-+      memset(icount, 0, sizeof(struct serial_icounter_struct));
-+
-+      if (!tiocmget)
-+               return -ENOENT;
-+      spin_lock_irq(&serial->serial_lock);
-+      memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount));
-+      spin_unlock_irq(&serial->serial_lock);
-+
-+      icount->cts         = cnow.cts;
-+      icount->dsr         = cnow.dsr;
-+      icount->rng         = cnow.rng;
-+      icount->dcd         = cnow.dcd;
-+      icount->rx          = cnow.rx;
-+      icount->tx          = cnow.tx;
-+      icount->frame       = cnow.frame;
-+      icount->overrun     = cnow.overrun;
-+      icount->parity      = cnow.parity;
-+      icount->brk         = cnow.brk;
-+      icount->buf_overrun = cnow.buf_overrun;
-+
-+      return 0;
-+}
-+
-+
-+static int hso_serial_tiocmget(struct tty_struct *tty)
-+{
-+      int retval;
-+      struct hso_serial *serial = tty->driver_data;
-+      struct hso_tiocmget  *tiocmget;
-+      u16 UART_state_bitmap;
-+
-+      /* sanity check */
-+      if (!serial) {
-+              D1("no tty structures");
-+              return -EINVAL;
-+      }
-+      spin_lock_irq(&serial->serial_lock);
-+      retval = ((serial->rts_state) ? TIOCM_RTS : 0) |
-+          ((serial->dtr_state) ? TIOCM_DTR : 0);
-+      tiocmget = serial->tiocmget;
-+      if (tiocmget) {
-+
-+              UART_state_bitmap = le16_to_cpu(
-+                      tiocmget->prev_UART_state_bitmap);
-+              if (UART_state_bitmap & B_RING_SIGNAL)
-+                      retval |=  TIOCM_RNG;
-+              if (UART_state_bitmap & B_RX_CARRIER)
-+                      retval |=  TIOCM_CD;
-+              if (UART_state_bitmap & B_TX_CARRIER)
-+                      retval |=  TIOCM_DSR;
-+      }
-+      spin_unlock_irq(&serial->serial_lock);
-+      return retval;
-+}
-+
-+static int hso_serial_tiocmset(struct tty_struct *tty,
-+                             unsigned int set, unsigned int clear)
-+{
-+      int val = 0;
-+      unsigned long flags;
-+      int if_num;
-+      struct hso_serial *serial = tty->driver_data;
-+      struct usb_interface *interface;
-+
-+      /* sanity check */
-+      if (!serial) {
-+              D1("no tty structures");
-+              return -EINVAL;
-+      }
-+
-+      if ((serial->parent->port_spec & HSO_PORT_MASK) != HSO_PORT_MODEM)
-+              return -EINVAL;
-+
-+      interface = serial->parent->interface;
-+      if_num = interface->cur_altsetting->desc.bInterfaceNumber;
-+
-+      spin_lock_irqsave(&serial->serial_lock, flags);
-+      if (set & TIOCM_RTS)
-+              serial->rts_state = 1;
-+      if (set & TIOCM_DTR)
-+              serial->dtr_state = 1;
-+
-+      if (clear & TIOCM_RTS)
-+              serial->rts_state = 0;
-+      if (clear & TIOCM_DTR)
-+              serial->dtr_state = 0;
-+
-+      if (serial->dtr_state)
-+              val |= 0x01;
-+      if (serial->rts_state)
-+              val |= 0x02;
-+
-+      spin_unlock_irqrestore(&serial->serial_lock, flags);
-+
-+      return usb_control_msg(serial->parent->usb,
-+                             usb_rcvctrlpipe(serial->parent->usb, 0), 0x22,
-+                             0x21, val, if_num, NULL, 0,
-+                             USB_CTRL_SET_TIMEOUT);
-+}
-+
-+static int hso_serial_ioctl(struct tty_struct *tty,
-+                          unsigned int cmd, unsigned long arg)
-+{
-+      struct hso_serial *serial = tty->driver_data;
-+      int ret = 0;
-+      D4("IOCTL cmd: %d, arg: %ld", cmd, arg);
-+
-+      if (!serial)
-+              return -ENODEV;
-+      switch (cmd) {
-+      case TIOCMIWAIT:
-+              ret = hso_wait_modem_status(serial, arg);
-+              break;
-+      default:
-+              ret = -ENOIOCTLCMD;
-+              break;
-+      }
-+      return ret;
-+}
-+
-+
-+/* starts a transmit */
-+static void hso_kick_transmit(struct hso_serial *serial)
-+{
-+      u8 *temp;
-+      unsigned long flags;
-+      int res;
-+
-+      spin_lock_irqsave(&serial->serial_lock, flags);
-+      if (!serial->tx_buffer_count)
-+              goto out;
-+
-+      if (serial->tx_urb_used)
-+              goto out;
-+
-+      /* Wakeup USB interface if necessary */
-+      if (hso_get_activity(serial->parent) == -EAGAIN)
-+              goto out;
-+
-+      /* Switch pointers around to avoid memcpy */
-+      temp = serial->tx_buffer;
-+      serial->tx_buffer = serial->tx_data;
-+      serial->tx_data = temp;
-+      serial->tx_data_count = serial->tx_buffer_count;
-+      serial->tx_buffer_count = 0;
-+
-+      /* If temp is set, it means we switched buffers */
-+      if (temp && serial->write_data) {
-+              res = serial->write_data(serial);
-+              if (res >= 0)
-+                      serial->tx_urb_used = 1;
-+      }
-+out:
-+      spin_unlock_irqrestore(&serial->serial_lock, flags);
-+}
-+
-+/* make a request (for reading and writing data to muxed serial port) */
-+static int mux_device_request(struct hso_serial *serial, u8 type, u16 port,
-+                            struct urb *ctrl_urb,
-+                            struct usb_ctrlrequest *ctrl_req,
-+                            u8 *ctrl_urb_data, u32 size)
-+{
-+      int result;
-+      int pipe;
-+
-+      /* Sanity check */
-+      if (!serial || !ctrl_urb || !ctrl_req) {
-+              printk(KERN_ERR "%s: Wrong arguments\n", __func__);
-+              return -EINVAL;
-+      }
-+
-+      /* initialize */
-+      ctrl_req->wValue = 0;
-+      ctrl_req->wIndex = cpu_to_le16(hso_port_to_mux(port));
-+      ctrl_req->wLength = cpu_to_le16(size);
-+
-+      if (type == USB_CDC_GET_ENCAPSULATED_RESPONSE) {
-+              /* Reading command */
-+              ctrl_req->bRequestType = USB_DIR_IN |
-+                                       USB_TYPE_OPTION_VENDOR |
-+                                       USB_RECIP_INTERFACE;
-+              ctrl_req->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
-+              pipe = usb_rcvctrlpipe(serial->parent->usb, 0);
-+      } else {
-+              /* Writing command */
-+              ctrl_req->bRequestType = USB_DIR_OUT |
-+                                       USB_TYPE_OPTION_VENDOR |
-+                                       USB_RECIP_INTERFACE;
-+              ctrl_req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
-+              pipe = usb_sndctrlpipe(serial->parent->usb, 0);
-+      }
-+      /* syslog */
-+      D2("%s command (%02x) len: %d, port: %d",
-+         type == USB_CDC_GET_ENCAPSULATED_RESPONSE ? "Read" : "Write",
-+         ctrl_req->bRequestType, ctrl_req->wLength, port);
-+
-+      /* Load ctrl urb */
-+      ctrl_urb->transfer_flags = 0;
-+      usb_fill_control_urb(ctrl_urb,
-+                           serial->parent->usb,
-+                           pipe,
-+                           (u8 *) ctrl_req,
-+                           ctrl_urb_data, size, ctrl_callback, serial);
-+      /* Send it on merry way */
-+      result = usb_submit_urb(ctrl_urb, GFP_ATOMIC);
-+      if (result) {
-+              dev_err(&ctrl_urb->dev->dev,
-+                      "%s failed submit ctrl_urb %d type %d\n", __func__,
-+                      result, type);
-+              return result;
-+      }
-+
-+      /* done */
-+      return size;
-+}
-+
-+/* called by intr_callback when read occurs */
-+static int hso_mux_serial_read(struct hso_serial *serial)
-+{
-+      if (!serial)
-+              return -EINVAL;
-+
-+      /* clean data */
-+      memset(serial->rx_data[0], 0, CTRL_URB_RX_SIZE);
-+      /* make the request */
-+
-+      if (serial->num_rx_urbs != 1) {
-+              dev_err(&serial->parent->interface->dev,
-+                      "ERROR: mux'd reads with multiple buffers "
-+                      "not possible\n");
-+              return 0;
-+      }
-+      return mux_device_request(serial,
-+                                USB_CDC_GET_ENCAPSULATED_RESPONSE,
-+                                serial->parent->port_spec & HSO_PORT_MASK,
-+                                serial->rx_urb[0],
-+                                &serial->ctrl_req_rx,
-+                                serial->rx_data[0], serial->rx_data_length);
-+}
-+
-+/* used for muxed serial port callback (muxed serial read) */
-+static void intr_callback(struct urb *urb)
-+{
-+      struct hso_shared_int *shared_int = urb->context;
-+      struct hso_serial *serial;
-+      unsigned char *port_req;
-+      int status = urb->status;
-+      int i;
-+
-+      usb_mark_last_busy(urb->dev);
-+
-+      /* sanity check */
-+      if (!shared_int)
-+              return;
-+
-+      /* status check */
-+      if (status) {
-+              handle_usb_error(status, __func__, NULL);
-+              return;
-+      }
-+      D4("\n--- Got intr callback 0x%02X ---", status);
-+
-+      /* what request? */
-+      port_req = urb->transfer_buffer;
-+      D4(" port_req = 0x%.2X\n", *port_req);
-+      /* loop over all muxed ports to find the one sending this */
-+      for (i = 0; i < 8; i++) {
-+              /* max 8 channels on MUX */
-+              if (*port_req & (1 << i)) {
-+                      serial = get_serial_by_shared_int_and_type(shared_int,
-+                                                                 (1 << i));
-+                      if (serial != NULL) {
-+                              D1("Pending read interrupt on port %d\n", i);
-+                              spin_lock(&serial->serial_lock);
-+                              if (serial->rx_state == RX_IDLE &&
-+                                      atomic_read(&serial->port.count) > 0) {
-+                                      /* Setup and send a ctrl req read on
-+                                       * port i */
-+                                      if (!serial->rx_urb_filled[0]) {
-+                                              serial->rx_state = RX_SENT;
-+                                              hso_mux_serial_read(serial);
-+                                      } else
-+                                              serial->rx_state = RX_PENDING;
-+                              } else {
-+                                      D1("Already a read pending on "
-+                                         "port %d or port not open\n", i);
-+                              }
-+                              spin_unlock(&serial->serial_lock);
-+                      }
-+              }
-+      }
-+      /* Resubmit interrupt urb */
-+      hso_mux_submit_intr_urb(shared_int, urb->dev, GFP_ATOMIC);
-+}
-+
-+/* called for writing to muxed serial port */
-+static int hso_mux_serial_write_data(struct hso_serial *serial)
-+{
-+      if (NULL == serial)
-+              return -EINVAL;
-+
-+      return mux_device_request(serial,
-+                                USB_CDC_SEND_ENCAPSULATED_COMMAND,
-+                                serial->parent->port_spec & HSO_PORT_MASK,
-+                                serial->tx_urb,
-+                                &serial->ctrl_req_tx,
-+                                serial->tx_data, serial->tx_data_count);
-+}
-+
-+/* write callback for Diag and CS port */
-+static void hso_std_serial_write_bulk_callback(struct urb *urb)
-+{
-+      struct hso_serial *serial = urb->context;
-+      int status = urb->status;
-+
-+      /* sanity check */
-+      if (!serial) {
-+              D1("serial == NULL");
-+              return;
-+      }
-+
-+      spin_lock(&serial->serial_lock);
-+      serial->tx_urb_used = 0;
-+      spin_unlock(&serial->serial_lock);
-+      if (status) {
-+              handle_usb_error(status, __func__, serial->parent);
-+              return;
-+      }
-+      hso_put_activity(serial->parent);
-+      tty_port_tty_wakeup(&serial->port);
-+      hso_kick_transmit(serial);
-+
-+      D1(" ");
-+}
-+
-+/* called for writing diag or CS serial port */
-+static int hso_std_serial_write_data(struct hso_serial *serial)
-+{
-+      int count = serial->tx_data_count;
-+      int result;
-+
-+      usb_fill_bulk_urb(serial->tx_urb,
-+                        serial->parent->usb,
-+                        usb_sndbulkpipe(serial->parent->usb,
-+                                        serial->out_endp->
-+                                        bEndpointAddress & 0x7F),
-+                        serial->tx_data, serial->tx_data_count,
-+                        hso_std_serial_write_bulk_callback, serial);
-+
-+      result = usb_submit_urb(serial->tx_urb, GFP_ATOMIC);
-+      if (result) {
-+              dev_warn(&serial->parent->usb->dev,
-+                       "Failed to submit urb - res %d\n", result);
-+              return result;
-+      }
-+
-+      return count;
-+}
-+
-+/* callback after read or write on muxed serial port */
-+static void ctrl_callback(struct urb *urb)
-+{
-+      struct hso_serial *serial = urb->context;
-+      struct usb_ctrlrequest *req;
-+      int status = urb->status;
-+
-+      /* sanity check */
-+      if (!serial)
-+              return;
-+
-+      spin_lock(&serial->serial_lock);
-+      serial->tx_urb_used = 0;
-+      spin_unlock(&serial->serial_lock);
-+      if (status) {
-+              handle_usb_error(status, __func__, serial->parent);
-+              return;
-+      }
-+
-+      /* what request? */
-+      req = (struct usb_ctrlrequest *)(urb->setup_packet);
-+      D4("\n--- Got muxed ctrl callback 0x%02X ---", status);
-+      D4("Actual length of urb = %d\n", urb->actual_length);
-+      DUMP1(urb->transfer_buffer, urb->actual_length);
-+
-+      if (req->bRequestType ==
-+          (USB_DIR_IN | USB_TYPE_OPTION_VENDOR | USB_RECIP_INTERFACE)) {
-+              /* response to a read command */
-+              serial->rx_urb_filled[0] = 1;
-+              spin_lock(&serial->serial_lock);
-+              put_rxbuf_data_and_resubmit_ctrl_urb(serial);
-+              spin_unlock(&serial->serial_lock);
-+      } else {
-+              hso_put_activity(serial->parent);
-+              tty_port_tty_wakeup(&serial->port);
-+              /* response to a write command */
-+              hso_kick_transmit(serial);
-+      }
-+}
-+
-+/* handle RX data for serial port */
-+static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
-+{
-+      struct tty_struct *tty;
-+      int count;
-+
-+      /* Sanity check */
-+      if (urb == NULL || serial == NULL) {
-+              D1("serial = NULL");
-+              return -2;
-+      }
-+
-+      tty = tty_port_tty_get(&serial->port);
-+
-+      if (tty && test_bit(TTY_THROTTLED, &tty->flags)) {
-+              tty_kref_put(tty);
-+              return -1;
-+      }
-+
-+      /* Push data to tty */
-+      D1("data to push to tty");
-+      count = tty_buffer_request_room(&serial->port, urb->actual_length);
-+      if (count >= urb->actual_length) {
-+              tty_insert_flip_string(&serial->port, urb->transfer_buffer,
-+                                     urb->actual_length);
-+              tty_flip_buffer_push(&serial->port);
-+      } else {
-+              dev_warn(&serial->parent->usb->dev,
-+                       "dropping data, %d bytes lost\n", urb->actual_length);
-+      }
-+
-+      tty_kref_put(tty);
-+
-+      serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
-+
-+      return 0;
-+}
-+
-+
-+/* Base driver functions */
-+
-+static void hso_log_port(struct hso_device *hso_dev)
-+{
-+      char *port_type;
-+      char port_dev[20];
-+
-+      switch (hso_dev->port_spec & HSO_PORT_MASK) {
-+      case HSO_PORT_CONTROL:
-+              port_type = "Control";
-+              break;
-+      case HSO_PORT_APP:
-+              port_type = "Application";
-+              break;
-+      case HSO_PORT_GPS:
-+              port_type = "GPS";
-+              break;
-+      case HSO_PORT_GPS_CONTROL:
-+              port_type = "GPS control";
-+              break;
-+      case HSO_PORT_APP2:
-+              port_type = "Application2";
-+              break;
-+      case HSO_PORT_PCSC:
-+              port_type = "PCSC";
-+              break;
-+      case HSO_PORT_DIAG:
-+              port_type = "Diagnostic";
-+              break;
-+      case HSO_PORT_DIAG2:
-+              port_type = "Diagnostic2";
-+              break;
-+      case HSO_PORT_MODEM:
-+              port_type = "Modem";
-+              break;
-+      case HSO_PORT_NETWORK:
-+              port_type = "Network";
-+              break;
-+      default:
-+              port_type = "Unknown";
-+              break;
-+      }
-+      if ((hso_dev->port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) {
-+              sprintf(port_dev, "%s", dev2net(hso_dev)->net->name);
-+      } else
-+              sprintf(port_dev, "/dev/%s%d", tty_filename,
-+                      dev2ser(hso_dev)->minor);
-+
-+      dev_dbg(&hso_dev->interface->dev, "HSO: Found %s port %s\n",
-+              port_type, port_dev);
-+}
-+
-+static int hso_start_net_device(struct hso_device *hso_dev)
-+{
-+      int i, result = 0;
-+      struct hso_net *hso_net = dev2net(hso_dev);
-+
-+      if (!hso_net)
-+              return -ENODEV;
-+
-+      /* send URBs for all read buffers */
-+      for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) {
-+
-+              /* Prep a receive URB */
-+              usb_fill_bulk_urb(hso_net->mux_bulk_rx_urb_pool[i],
-+                                hso_dev->usb,
-+                                usb_rcvbulkpipe(hso_dev->usb,
-+                                                hso_net->in_endp->
-+                                                bEndpointAddress & 0x7F),
-+                                hso_net->mux_bulk_rx_buf_pool[i],
-+                                MUX_BULK_RX_BUF_SIZE, read_bulk_callback,
-+                                hso_net);
-+
-+              /* Put it out there so the device can send us stuff */
-+              result = usb_submit_urb(hso_net->mux_bulk_rx_urb_pool[i],
-+                                      GFP_NOIO);
-+              if (result)
-+                      dev_warn(&hso_dev->usb->dev,
-+                              "%s failed mux_bulk_rx_urb[%d] %d\n", __func__,
-+                              i, result);
-+      }
-+
-+      return result;
-+}
-+
-+static int hso_stop_net_device(struct hso_device *hso_dev)
-+{
-+      int i;
-+      struct hso_net *hso_net = dev2net(hso_dev);
-+
-+      if (!hso_net)
-+              return -ENODEV;
-+
-+      for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) {
-+              if (hso_net->mux_bulk_rx_urb_pool[i])
-+                      usb_kill_urb(hso_net->mux_bulk_rx_urb_pool[i]);
-+
-+      }
-+      if (hso_net->mux_bulk_tx_urb)
-+              usb_kill_urb(hso_net->mux_bulk_tx_urb);
-+
-+      return 0;
-+}
-+
-+static int hso_start_serial_device(struct hso_device *hso_dev, gfp_t flags)
-+{
-+      int i, result = 0;
-+      struct hso_serial *serial = dev2ser(hso_dev);
-+
-+      if (!serial)
-+              return -ENODEV;
-+
-+      /* If it is not the MUX port fill in and submit a bulk urb (already
-+       * allocated in hso_serial_start) */
-+      if (!(serial->parent->port_spec & HSO_INTF_MUX)) {
-+              for (i = 0; i < serial->num_rx_urbs; i++) {
-+                      usb_fill_bulk_urb(serial->rx_urb[i],
-+                                        serial->parent->usb,
-+                                        usb_rcvbulkpipe(serial->parent->usb,
-+                                                        serial->in_endp->
-+                                                        bEndpointAddress &
-+                                                        0x7F),
-+                                        serial->rx_data[i],
-+                                        serial->rx_data_length,
-+                                        hso_std_serial_read_bulk_callback,
-+                                        serial);
-+                      result = usb_submit_urb(serial->rx_urb[i], flags);
-+                      if (result) {
-+                              dev_warn(&serial->parent->usb->dev,
-+                                       "Failed to submit urb - res %d\n",
-+                                       result);
-+                              break;
-+                      }
-+              }
-+      } else {
-+              mutex_lock(&serial->shared_int->shared_int_lock);
-+              if (!serial->shared_int->use_count) {
-+                      result =
-+                          hso_mux_submit_intr_urb(serial->shared_int,
-+                                                  hso_dev->usb, flags);
-+              }
-+              serial->shared_int->use_count++;
-+              mutex_unlock(&serial->shared_int->shared_int_lock);
-+      }
-+      if (serial->tiocmget)
-+              tiocmget_submit_urb(serial,
-+                                  serial->tiocmget,
-+                                  serial->parent->usb);
-+      return result;
-+}
-+
-+static int hso_stop_serial_device(struct hso_device *hso_dev)
-+{
-+      int i;
-+      struct hso_serial *serial = dev2ser(hso_dev);
-+      struct hso_tiocmget  *tiocmget;
-+
-+      if (!serial)
-+              return -ENODEV;
-+
-+      for (i = 0; i < serial->num_rx_urbs; i++) {
-+              if (serial->rx_urb[i]) {
-+                      usb_kill_urb(serial->rx_urb[i]);
-+                      serial->rx_urb_filled[i] = 0;
-+              }
-+      }
-+      serial->curr_rx_urb_idx = 0;
-+
-+      if (serial->tx_urb)
-+              usb_kill_urb(serial->tx_urb);
-+
-+      if (serial->shared_int) {
-+              mutex_lock(&serial->shared_int->shared_int_lock);
-+              if (serial->shared_int->use_count &&
-+                  (--serial->shared_int->use_count == 0)) {
-+                      struct urb *urb;
-+
-+                      urb = serial->shared_int->shared_intr_urb;
-+                      if (urb)
-+                              usb_kill_urb(urb);
-+              }
-+              mutex_unlock(&serial->shared_int->shared_int_lock);
-+      }
-+      tiocmget = serial->tiocmget;
-+      if (tiocmget) {
-+              wake_up_interruptible(&tiocmget->waitq);
-+              usb_kill_urb(tiocmget->urb);
-+      }
-+
-+      return 0;
-+}
-+
-+static void hso_serial_tty_unregister(struct hso_serial *serial)
-+{
-+      tty_unregister_device(tty_drv, serial->minor);
-+}
-+
-+static void hso_serial_common_free(struct hso_serial *serial)
-+{
-+      int i;
-+
-+      for (i = 0; i < serial->num_rx_urbs; i++) {
-+              /* unlink and free RX URB */
-+              usb_free_urb(serial->rx_urb[i]);
-+              /* free the RX buffer */
-+              kfree(serial->rx_data[i]);
-+      }
-+
-+      /* unlink and free TX URB */
-+      usb_free_urb(serial->tx_urb);
-+      kfree(serial->tx_buffer);
-+      kfree(serial->tx_data);
-+      tty_port_destroy(&serial->port);
-+}
-+
-+static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
-+                                  int rx_size, int tx_size)
-+{
-+      struct device *dev;
-+      int minor;
-+      int i;
-+
-+      tty_port_init(&serial->port);
-+
-+      minor = get_free_serial_index();
-+      if (minor < 0)
-+              goto exit;
-+
-+      /* register our minor number */
-+      serial->parent->dev = tty_port_register_device_attr(&serial->port,
-+                      tty_drv, minor, &serial->parent->interface->dev,
-+                      serial->parent, hso_serial_dev_groups);
-+      dev = serial->parent->dev;
-+
-+      /* fill in specific data for later use */
-+      serial->minor = minor;
-+      serial->magic = HSO_SERIAL_MAGIC;
-+      spin_lock_init(&serial->serial_lock);
-+      serial->num_rx_urbs = num_urbs;
-+
-+      /* RX, allocate urb and initialize */
-+
-+      /* prepare our RX buffer */
-+      serial->rx_data_length = rx_size;
-+      for (i = 0; i < serial->num_rx_urbs; i++) {
-+              serial->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
-+              if (!serial->rx_urb[i]) {
-+                      dev_err(dev, "Could not allocate urb?\n");
-+                      goto exit;
-+              }
-+              serial->rx_urb[i]->transfer_buffer = NULL;
-+              serial->rx_urb[i]->transfer_buffer_length = 0;
-+              serial->rx_data[i] = kzalloc(serial->rx_data_length,
-+                                           GFP_KERNEL);
-+              if (!serial->rx_data[i])
-+                      goto exit;
-+      }
-+
-+      /* TX, allocate urb and initialize */
-+      serial->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!serial->tx_urb) {
-+              dev_err(dev, "Could not allocate urb?\n");
-+              goto exit;
-+      }
-+      serial->tx_urb->transfer_buffer = NULL;
-+      serial->tx_urb->transfer_buffer_length = 0;
-+      /* prepare our TX buffer */
-+      serial->tx_data_count = 0;
-+      serial->tx_buffer_count = 0;
-+      serial->tx_data_length = tx_size;
-+      serial->tx_data = kzalloc(serial->tx_data_length, GFP_KERNEL);
-+      if (!serial->tx_data)
-+              goto exit;
-+
-+      serial->tx_buffer = kzalloc(serial->tx_data_length, GFP_KERNEL);
-+      if (!serial->tx_buffer)
-+              goto exit;
-+
-+      return 0;
-+exit:
-+      hso_serial_tty_unregister(serial);
-+      hso_serial_common_free(serial);
-+      return -1;
-+}
-+
-+/* Creates a general hso device */
-+static struct hso_device *hso_create_device(struct usb_interface *intf,
-+                                          int port_spec)
-+{
-+      struct hso_device *hso_dev;
-+
-+      hso_dev = kzalloc(sizeof(*hso_dev), GFP_ATOMIC);
-+      if (!hso_dev)
-+              return NULL;
-+
-+      hso_dev->port_spec = port_spec;
-+      hso_dev->usb = interface_to_usbdev(intf);
-+      hso_dev->interface = intf;
-+      kref_init(&hso_dev->ref);
-+      mutex_init(&hso_dev->mutex);
-+
-+      INIT_WORK(&hso_dev->async_get_intf, async_get_intf);
-+      INIT_WORK(&hso_dev->async_put_intf, async_put_intf);
-+
-+      return hso_dev;
-+}
-+
-+/* Removes a network device in the network device table */
-+static int remove_net_device(struct hso_device *hso_dev)
-+{
-+      int i;
-+
-+      for (i = 0; i < HSO_MAX_NET_DEVICES; i++) {
-+              if (network_table[i] == hso_dev) {
-+                      network_table[i] = NULL;
-+                      break;
-+              }
-+      }
-+      if (i == HSO_MAX_NET_DEVICES)
-+              return -1;
-+      return 0;
-+}
-+
-+/* Frees our network device */
-+static void hso_free_net_device(struct hso_device *hso_dev)
-+{
-+      int i;
-+      struct hso_net *hso_net = dev2net(hso_dev);
-+
-+      if (!hso_net)
-+              return;
-+
-+      remove_net_device(hso_net->parent);
-+
-+      if (hso_net->net)
-+              unregister_netdev(hso_net->net);
-+
-+      /* start freeing */
-+      for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) {
-+              usb_free_urb(hso_net->mux_bulk_rx_urb_pool[i]);
-+              kfree(hso_net->mux_bulk_rx_buf_pool[i]);
-+              hso_net->mux_bulk_rx_buf_pool[i] = NULL;
-+      }
-+      usb_free_urb(hso_net->mux_bulk_tx_urb);
-+      kfree(hso_net->mux_bulk_tx_buf);
-+      hso_net->mux_bulk_tx_buf = NULL;
-+
-+      if (hso_net->net)
-+              free_netdev(hso_net->net);
-+
-+      kfree(hso_dev);
-+}
-+
-+static const struct net_device_ops hso_netdev_ops = {
-+      .ndo_open       = hso_net_open,
-+      .ndo_stop       = hso_net_close,
-+      .ndo_start_xmit = hso_net_start_xmit,
-+      .ndo_tx_timeout = hso_net_tx_timeout,
-+};
-+
-+/* initialize the network interface */
-+static void hso_net_init(struct net_device *net)
-+{
-+      struct hso_net *hso_net = netdev_priv(net);
-+
-+      D1("sizeof hso_net is %d", (int)sizeof(*hso_net));
-+
-+      /* fill in the other fields */
-+      net->netdev_ops = &hso_netdev_ops;
-+      net->watchdog_timeo = HSO_NET_TX_TIMEOUT;
-+      net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
-+      net->type = ARPHRD_NONE;
-+      net->mtu = DEFAULT_MTU - 14;
-+      net->tx_queue_len = 10;
-+      net->ethtool_ops = &ops;
-+
-+      /* and initialize the semaphore */
-+      spin_lock_init(&hso_net->net_lock);
-+}
-+
-+/* Adds a network device in the network device table */
-+static int add_net_device(struct hso_device *hso_dev)
-+{
-+      int i;
-+
-+      for (i = 0; i < HSO_MAX_NET_DEVICES; i++) {
-+              if (network_table[i] == NULL) {
-+                      network_table[i] = hso_dev;
-+                      break;
-+              }
-+      }
-+      if (i == HSO_MAX_NET_DEVICES)
-+              return -1;
-+      return 0;
-+}
-+
-+static int hso_rfkill_set_block(void *data, bool blocked)
-+{
-+      struct hso_device *hso_dev = data;
-+      int enabled = !blocked;
-+      int rv;
-+
-+      mutex_lock(&hso_dev->mutex);
-+      if (hso_dev->usb_gone)
-+              rv = 0;
-+      else
-+              rv = usb_control_msg(hso_dev->usb, usb_rcvctrlpipe(hso_dev->usb, 0),
-+                                     enabled ? 0x82 : 0x81, 0x40, 0, 0, NULL, 0,
-+                                     USB_CTRL_SET_TIMEOUT);
-+      mutex_unlock(&hso_dev->mutex);
-+      return rv;
-+}
-+
-+static const struct rfkill_ops hso_rfkill_ops = {
-+      .set_block = hso_rfkill_set_block,
-+};
-+
-+/* Creates and sets up everything for rfkill */
-+static void hso_create_rfkill(struct hso_device *hso_dev,
-+                           struct usb_interface *interface)
-+{
-+      struct hso_net *hso_net = dev2net(hso_dev);
-+      struct device *dev = &hso_net->net->dev;
-+      static u32 rfkill_counter;
-+
-+      snprintf(hso_net->name, sizeof(hso_net->name), "hso-%d",
-+               rfkill_counter++);
-+
-+      hso_net->rfkill = rfkill_alloc(hso_net->name,
-+                                     &interface_to_usbdev(interface)->dev,
-+                                     RFKILL_TYPE_WWAN,
-+                                     &hso_rfkill_ops, hso_dev);
-+      if (!hso_net->rfkill) {
-+              dev_err(dev, "%s - Out of memory\n", __func__);
-+              return;
-+      }
-+      if (rfkill_register(hso_net->rfkill) < 0) {
-+              rfkill_destroy(hso_net->rfkill);
-+              hso_net->rfkill = NULL;
-+              dev_err(dev, "%s - Failed to register rfkill\n", __func__);
-+              return;
-+      }
-+}
-+
-+static struct device_type hso_type = {
-+      .name   = "wwan",
-+};
-+
-+/* Creates our network device */
-+static struct hso_device *hso_create_net_device(struct usb_interface *interface,
-+                                              int port_spec)
-+{
-+      int result, i;
-+      struct net_device *net;
-+      struct hso_net *hso_net;
-+      struct hso_device *hso_dev;
-+
-+      hso_dev = hso_create_device(interface, port_spec);
-+      if (!hso_dev)
-+              return NULL;
-+
-+      /* allocate our network device, then we can put in our private data */
-+      /* call hso_net_init to do the basic initialization */
-+      net = alloc_netdev(sizeof(struct hso_net), "hso%d", NET_NAME_UNKNOWN,
-+                         hso_net_init);
-+      if (!net) {
-+              dev_err(&interface->dev, "Unable to create ethernet device\n");
-+              goto exit;
-+      }
-+
-+      hso_net = netdev_priv(net);
-+
-+      hso_dev->port_data.dev_net = hso_net;
-+      hso_net->net = net;
-+      hso_net->parent = hso_dev;
-+
-+      hso_net->in_endp = hso_get_ep(interface, USB_ENDPOINT_XFER_BULK,
-+                                    USB_DIR_IN);
-+      if (!hso_net->in_endp) {
-+              dev_err(&interface->dev, "Can't find BULK IN endpoint\n");
-+              goto exit;
-+      }
-+      hso_net->out_endp = hso_get_ep(interface, USB_ENDPOINT_XFER_BULK,
-+                                     USB_DIR_OUT);
-+      if (!hso_net->out_endp) {
-+              dev_err(&interface->dev, "Can't find BULK OUT endpoint\n");
-+              goto exit;
-+      }
-+      SET_NETDEV_DEV(net, &interface->dev);
-+      SET_NETDEV_DEVTYPE(net, &hso_type);
-+
-+      /* registering our net device */
-+      result = register_netdev(net);
-+      if (result) {
-+              dev_err(&interface->dev, "Failed to register device\n");
-+              goto exit;
-+      }
-+
-+      /* start allocating */
-+      for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) {
-+              hso_net->mux_bulk_rx_urb_pool[i] = usb_alloc_urb(0, GFP_KERNEL);
-+              if (!hso_net->mux_bulk_rx_urb_pool[i]) {
-+                      dev_err(&interface->dev, "Could not allocate rx urb\n");
-+                      goto exit;
-+              }
-+              hso_net->mux_bulk_rx_buf_pool[i] = kzalloc(MUX_BULK_RX_BUF_SIZE,
-+                                                         GFP_KERNEL);
-+              if (!hso_net->mux_bulk_rx_buf_pool[i])
-+                      goto exit;
-+      }
-+      hso_net->mux_bulk_tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!hso_net->mux_bulk_tx_urb) {
-+              dev_err(&interface->dev, "Could not allocate tx urb\n");
-+              goto exit;
-+      }
-+      hso_net->mux_bulk_tx_buf = kzalloc(MUX_BULK_TX_BUF_SIZE, GFP_KERNEL);
-+      if (!hso_net->mux_bulk_tx_buf)
-+              goto exit;
-+
-+      add_net_device(hso_dev);
-+
-+      hso_log_port(hso_dev);
-+
-+      hso_create_rfkill(hso_dev, interface);
-+
-+      return hso_dev;
-+exit:
-+      hso_free_net_device(hso_dev);
-+      return NULL;
-+}
-+
-+static void hso_free_tiomget(struct hso_serial *serial)
-+{
-+      struct hso_tiocmget *tiocmget;
-+      if (!serial)
-+              return;
-+      tiocmget = serial->tiocmget;
-+      if (tiocmget) {
-+              usb_free_urb(tiocmget->urb);
-+              tiocmget->urb = NULL;
-+              serial->tiocmget = NULL;
-+              kfree(tiocmget);
-+      }
-+}
-+
-+/* Frees an AT channel ( goes for both mux and non-mux ) */
-+static void hso_free_serial_device(struct hso_device *hso_dev)
-+{
-+      struct hso_serial *serial = dev2ser(hso_dev);
-+
-+      if (!serial)
-+              return;
-+
-+      hso_serial_common_free(serial);
-+
-+      if (serial->shared_int) {
-+              mutex_lock(&serial->shared_int->shared_int_lock);
-+              if (--serial->shared_int->ref_count == 0)
-+                      hso_free_shared_int(serial->shared_int);
-+              else
-+                      mutex_unlock(&serial->shared_int->shared_int_lock);
-+      }
-+      hso_free_tiomget(serial);
-+      kfree(serial);
-+      kfree(hso_dev);
-+}
-+
-+/* Creates a bulk AT channel */
-+static struct hso_device *hso_create_bulk_serial_device(
-+                      struct usb_interface *interface, int port)
-+{
-+      struct hso_device *hso_dev;
-+      struct hso_serial *serial;
-+      int num_urbs;
-+      struct hso_tiocmget *tiocmget;
-+
-+      hso_dev = hso_create_device(interface, port);
-+      if (!hso_dev)
-+              return NULL;
-+
-+      serial = kzalloc(sizeof(*serial), GFP_KERNEL);
-+      if (!serial)
-+              goto exit;
-+
-+      serial->parent = hso_dev;
-+      hso_dev->port_data.dev_serial = serial;
-+
-+      if ((port & HSO_PORT_MASK) == HSO_PORT_MODEM) {
-+              num_urbs = 2;
-+              serial->tiocmget = kzalloc(sizeof(struct hso_tiocmget),
-+                                         GFP_KERNEL);
-+              /* it isn't going to break our heart if serial->tiocmget
-+               *  allocation fails don't bother checking this.
-+               */
-+              if (serial->tiocmget) {
-+                      tiocmget = serial->tiocmget;
-+                      tiocmget->urb = usb_alloc_urb(0, GFP_KERNEL);
-+                      if (tiocmget->urb) {
-+                              mutex_init(&tiocmget->mutex);
-+                              init_waitqueue_head(&tiocmget->waitq);
-+                              tiocmget->endp = hso_get_ep(
-+                                      interface,
-+                                      USB_ENDPOINT_XFER_INT,
-+                                      USB_DIR_IN);
-+                      } else
-+                              hso_free_tiomget(serial);
-+              }
-+      }
-+      else
-+              num_urbs = 1;
-+
-+      if (hso_serial_common_create(serial, num_urbs, BULK_URB_RX_SIZE,
-+                                   BULK_URB_TX_SIZE))
-+              goto exit;
-+
-+      serial->in_endp = hso_get_ep(interface, USB_ENDPOINT_XFER_BULK,
-+                                   USB_DIR_IN);
-+      if (!serial->in_endp) {
-+              dev_err(&interface->dev, "Failed to find BULK IN ep\n");
-+              goto exit2;
-+      }
-+
-+      if (!
-+          (serial->out_endp =
-+           hso_get_ep(interface, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT))) {
-+              dev_err(&interface->dev, "Failed to find BULK IN ep\n");
-+              goto exit2;
-+      }
-+
-+      serial->write_data = hso_std_serial_write_data;
-+
-+      /* and record this serial */
-+      set_serial_by_index(serial->minor, serial);
-+
-+      /* setup the proc dirs and files if needed */
-+      hso_log_port(hso_dev);
-+
-+      /* done, return it */
-+      return hso_dev;
-+
-+exit2:
-+      hso_serial_tty_unregister(serial);
-+      hso_serial_common_free(serial);
-+exit:
-+      hso_free_tiomget(serial);
-+      kfree(serial);
-+      kfree(hso_dev);
-+      return NULL;
-+}
-+
-+/* Creates a multiplexed AT channel */
-+static
-+struct hso_device *hso_create_mux_serial_device(struct usb_interface *interface,
-+                                              int port,
-+                                              struct hso_shared_int *mux)
-+{
-+      struct hso_device *hso_dev;
-+      struct hso_serial *serial;
-+      int port_spec;
-+
-+      port_spec = HSO_INTF_MUX;
-+      port_spec &= ~HSO_PORT_MASK;
-+
-+      port_spec |= hso_mux_to_port(port);
-+      if ((port_spec & HSO_PORT_MASK) == HSO_PORT_NO_PORT)
-+              return NULL;
-+
-+      hso_dev = hso_create_device(interface, port_spec);
-+      if (!hso_dev)
-+              return NULL;
-+
-+      serial = kzalloc(sizeof(*serial), GFP_KERNEL);
-+      if (!serial)
-+              goto exit;
-+
-+      hso_dev->port_data.dev_serial = serial;
-+      serial->parent = hso_dev;
-+
-+      if (hso_serial_common_create
-+          (serial, 1, CTRL_URB_RX_SIZE, CTRL_URB_TX_SIZE))
-+              goto exit;
-+
-+      serial->tx_data_length--;
-+      serial->write_data = hso_mux_serial_write_data;
-+
-+      serial->shared_int = mux;
-+      mutex_lock(&serial->shared_int->shared_int_lock);
-+      serial->shared_int->ref_count++;
-+      mutex_unlock(&serial->shared_int->shared_int_lock);
-+
-+      /* and record this serial */
-+      set_serial_by_index(serial->minor, serial);
-+
-+      /* setup the proc dirs and files if needed */
-+      hso_log_port(hso_dev);
-+
-+      /* done, return it */
-+      return hso_dev;
-+
-+exit:
-+      if (serial) {
-+              tty_unregister_device(tty_drv, serial->minor);
-+              kfree(serial);
-+      }
-+      kfree(hso_dev);
-+      return NULL;
-+
-+}
-+
-+static void hso_free_shared_int(struct hso_shared_int *mux)
-+{
-+      usb_free_urb(mux->shared_intr_urb);
-+      kfree(mux->shared_intr_buf);
-+      mutex_unlock(&mux->shared_int_lock);
-+      kfree(mux);
-+}
-+
-+static
-+struct hso_shared_int *hso_create_shared_int(struct usb_interface *interface)
-+{
-+      struct hso_shared_int *mux = kzalloc(sizeof(*mux), GFP_KERNEL);
-+
-+      if (!mux)
-+              return NULL;
-+
-+      mux->intr_endp = hso_get_ep(interface, USB_ENDPOINT_XFER_INT,
-+                                  USB_DIR_IN);
-+      if (!mux->intr_endp) {
-+              dev_err(&interface->dev, "Can't find INT IN endpoint\n");
-+              goto exit;
-+      }
-+
-+      mux->shared_intr_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!mux->shared_intr_urb) {
-+              dev_err(&interface->dev, "Could not allocate intr urb?\n");
-+              goto exit;
-+      }
-+      mux->shared_intr_buf =
-+              kzalloc(le16_to_cpu(mux->intr_endp->wMaxPacketSize),
-+                      GFP_KERNEL);
-+      if (!mux->shared_intr_buf)
-+              goto exit;
-+
-+      mutex_init(&mux->shared_int_lock);
-+
-+      return mux;
-+
-+exit:
-+      kfree(mux->shared_intr_buf);
-+      usb_free_urb(mux->shared_intr_urb);
-+      kfree(mux);
-+      return NULL;
-+}
-+
-+/* Gets the port spec for a certain interface */
-+static int hso_get_config_data(struct usb_interface *interface)
-+{
-+      struct usb_device *usbdev = interface_to_usbdev(interface);
-+      u8 *config_data = kmalloc(17, GFP_KERNEL);
-+      u32 if_num = interface->cur_altsetting->desc.bInterfaceNumber;
-+      s32 result;
-+
-+      if (!config_data)
-+              return -ENOMEM;
-+      if (usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
-+                          0x86, 0xC0, 0, 0, config_data, 17,
-+                          USB_CTRL_SET_TIMEOUT) != 0x11) {
-+              kfree(config_data);
-+              return -EIO;
-+      }
-+
-+      switch (config_data[if_num]) {
-+      case 0x0:
-+              result = 0;
-+              break;
-+      case 0x1:
-+              result = HSO_PORT_DIAG;
-+              break;
-+      case 0x2:
-+              result = HSO_PORT_GPS;
-+              break;
-+      case 0x3:
-+              result = HSO_PORT_GPS_CONTROL;
-+              break;
-+      case 0x4:
-+              result = HSO_PORT_APP;
-+              break;
-+      case 0x5:
-+              result = HSO_PORT_APP2;
-+              break;
-+      case 0x6:
-+              result = HSO_PORT_CONTROL;
-+              break;
-+      case 0x7:
-+              result = HSO_PORT_NETWORK;
-+              break;
-+      case 0x8:
-+              result = HSO_PORT_MODEM;
-+              break;
-+      case 0x9:
-+              result = HSO_PORT_MSD;
-+              break;
-+      case 0xa:
-+              result = HSO_PORT_PCSC;
-+              break;
-+      case 0xb:
-+              result = HSO_PORT_VOICE;
-+              break;
-+      default:
-+              result = 0;
-+      }
-+
-+      if (result)
-+              result |= HSO_INTF_BULK;
-+
-+      if (config_data[16] & 0x1)
-+              result |= HSO_INFO_CRC_BUG;
-+
-+      kfree(config_data);
-+      return result;
-+}
-+
-+/* called once for each interface upon device insertion */
-+static int hso_probe(struct usb_interface *interface,
-+                   const struct usb_device_id *id)
-+{
-+      int mux, i, if_num, port_spec;
-+      unsigned char port_mask;
-+      struct hso_device *hso_dev = NULL;
-+      struct hso_shared_int *shared_int;
-+      struct hso_device *tmp_dev = NULL;
-+
-+      if (interface->cur_altsetting->desc.bInterfaceClass != 0xFF) {
-+              dev_err(&interface->dev, "Not our interface\n");
-+              return -ENODEV;
-+      }
-+
-+      if_num = interface->cur_altsetting->desc.bInterfaceNumber;
-+
-+      /* Get the interface/port specification from either driver_info or from
-+       * the device itself */
-+      if (id->driver_info)
-+              port_spec = ((u32 *)(id->driver_info))[if_num];
-+      else
-+              port_spec = hso_get_config_data(interface);
-+
-+      /* Check if we need to switch to alt interfaces prior to port
-+       * configuration */
-+      if (interface->num_altsetting > 1)
-+              usb_set_interface(interface_to_usbdev(interface), if_num, 1);
-+      interface->needs_remote_wakeup = 1;
-+
-+      /* Allocate new hso device(s) */
-+      switch (port_spec & HSO_INTF_MASK) {
-+      case HSO_INTF_MUX:
-+              if ((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) {
-+                      /* Create the network device */
-+                      if (!disable_net) {
-+                              hso_dev = hso_create_net_device(interface,
-+                                                              port_spec);
-+                              if (!hso_dev)
-+                                      goto exit;
-+                              tmp_dev = hso_dev;
-+                      }
-+              }
-+
-+              if (hso_get_mux_ports(interface, &port_mask))
-+                      /* TODO: de-allocate everything */
-+                      goto exit;
-+
-+              shared_int = hso_create_shared_int(interface);
-+              if (!shared_int)
-+                      goto exit;
-+
-+              for (i = 1, mux = 0; i < 0x100; i = i << 1, mux++) {
-+                      if (port_mask & i) {
-+                              hso_dev = hso_create_mux_serial_device(
-+                                              interface, i, shared_int);
-+                              if (!hso_dev)
-+                                      goto exit;
-+                      }
-+              }
-+
-+              if (tmp_dev)
-+                      hso_dev = tmp_dev;
-+              break;
-+
-+      case HSO_INTF_BULK:
-+              /* It's a regular bulk interface */
-+              if ((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) {
-+                      if (!disable_net)
-+                              hso_dev =
-+                                  hso_create_net_device(interface, port_spec);
-+              } else {
-+                      hso_dev =
-+                          hso_create_bulk_serial_device(interface, port_spec);
-+              }
-+              if (!hso_dev)
-+                      goto exit;
-+              break;
-+      default:
-+              goto exit;
-+      }
-+
-+      /* save our data pointer in this device */
-+      usb_set_intfdata(interface, hso_dev);
-+
-+      /* done */
-+      return 0;
-+exit:
-+      hso_free_interface(interface);
-+      return -ENODEV;
-+}
-+
-+/* device removed, cleaning up */
-+static void hso_disconnect(struct usb_interface *interface)
-+{
-+      hso_free_interface(interface);
-+
-+      /* remove reference of our private data */
-+      usb_set_intfdata(interface, NULL);
-+}
-+
-+static void async_get_intf(struct work_struct *data)
-+{
-+      struct hso_device *hso_dev =
-+          container_of(data, struct hso_device, async_get_intf);
-+      usb_autopm_get_interface(hso_dev->interface);
-+}
-+
-+static void async_put_intf(struct work_struct *data)
-+{
-+      struct hso_device *hso_dev =
-+          container_of(data, struct hso_device, async_put_intf);
-+      usb_autopm_put_interface(hso_dev->interface);
-+}
-+
-+static int hso_get_activity(struct hso_device *hso_dev)
-+{
-+      if (hso_dev->usb->state == USB_STATE_SUSPENDED) {
-+              if (!hso_dev->is_active) {
-+                      hso_dev->is_active = 1;
-+                      schedule_work(&hso_dev->async_get_intf);
-+              }
-+      }
-+
-+      if (hso_dev->usb->state != USB_STATE_CONFIGURED)
-+              return -EAGAIN;
-+
-+      usb_mark_last_busy(hso_dev->usb);
-+
-+      return 0;
-+}
-+
-+static int hso_put_activity(struct hso_device *hso_dev)
-+{
-+      if (hso_dev->usb->state != USB_STATE_SUSPENDED) {
-+              if (hso_dev->is_active) {
-+                      hso_dev->is_active = 0;
-+                      schedule_work(&hso_dev->async_put_intf);
-+                      return -EAGAIN;
-+              }
-+      }
-+      hso_dev->is_active = 0;
-+      return 0;
-+}
-+
-+/* called by kernel when we need to suspend device */
-+static int hso_suspend(struct usb_interface *iface, pm_message_t message)
-+{
-+      int i, result;
-+
-+      /* Stop all serial ports */
-+      for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {
-+              if (serial_table[i] && (serial_table[i]->interface == iface)) {
-+                      result = hso_stop_serial_device(serial_table[i]);
-+                      if (result)
-+                              goto out;
-+              }
-+      }
-+
-+      /* Stop all network ports */
-+      for (i = 0; i < HSO_MAX_NET_DEVICES; i++) {
-+              if (network_table[i] &&
-+                  (network_table[i]->interface == iface)) {
-+                      result = hso_stop_net_device(network_table[i]);
-+                      if (result)
-+                              goto out;
-+              }
-+      }
-+
-+out:
-+      return 0;
-+}
-+
-+/* called by kernel when we need to resume device */
-+static int hso_resume(struct usb_interface *iface)
-+{
-+      int i, result = 0;
-+      struct hso_net *hso_net;
-+
-+      /* Start all serial ports */
-+      for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {
-+              if (serial_table[i] && (serial_table[i]->interface == iface)) {
-+                      if (atomic_read(&dev2ser(serial_table[i])->port.count)) {
-+                              result =
-+                                  hso_start_serial_device(serial_table[i], GFP_NOIO);
-+                              hso_kick_transmit(dev2ser(serial_table[i]));
-+                              if (result)
-+                                      goto out;
-+                      }
-+              }
-+      }
-+
-+      /* Start all network ports */
-+      for (i = 0; i < HSO_MAX_NET_DEVICES; i++) {
-+              if (network_table[i] &&
-+                  (network_table[i]->interface == iface)) {
-+                      hso_net = dev2net(network_table[i]);
-+                      if (hso_net->flags & IFF_UP) {
-+                              /* First transmit any lingering data,
-+                                 then restart the device. */
-+                              if (hso_net->skb_tx_buf) {
-+                                      dev_dbg(&iface->dev,
-+                                              "Transmitting"
-+                                              " lingering data\n");
-+                                      hso_net_start_xmit(hso_net->skb_tx_buf,
-+                                                         hso_net->net);
-+                                      hso_net->skb_tx_buf = NULL;
-+                              }
-+                              result = hso_start_net_device(network_table[i]);
-+                              if (result)
-+                                      goto out;
-+                      }
-+              }
-+      }
-+
-+out:
-+      return result;
-+}
-+
-+static void hso_serial_ref_free(struct kref *ref)
-+{
-+      struct hso_device *hso_dev = container_of(ref, struct hso_device, ref);
-+
-+      hso_free_serial_device(hso_dev);
-+}
-+
-+static void hso_free_interface(struct usb_interface *interface)
-+{
-+      struct hso_serial *serial;
-+      int i;
-+
-+      for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {
-+              if (serial_table[i] &&
-+                  (serial_table[i]->interface == interface)) {
-+                      serial = dev2ser(serial_table[i]);
-+                      tty_port_tty_hangup(&serial->port, false);
-+                      mutex_lock(&serial->parent->mutex);
-+                      serial->parent->usb_gone = 1;
-+                      mutex_unlock(&serial->parent->mutex);
-+                      cancel_work_sync(&serial_table[i]->async_put_intf);
-+                      cancel_work_sync(&serial_table[i]->async_get_intf);
-+                      hso_serial_tty_unregister(serial);
-+                      kref_put(&serial_table[i]->ref, hso_serial_ref_free);
-+                      set_serial_by_index(i, NULL);
-+              }
-+      }
-+
-+      for (i = 0; i < HSO_MAX_NET_DEVICES; i++) {
-+              if (network_table[i] &&
-+                  (network_table[i]->interface == interface)) {
-+                      struct rfkill *rfk = dev2net(network_table[i])->rfkill;
-+                      /* hso_stop_net_device doesn't stop the net queue since
-+                       * traffic needs to start it again when suspended */
-+                      netif_stop_queue(dev2net(network_table[i])->net);
-+                      hso_stop_net_device(network_table[i]);
-+                      cancel_work_sync(&network_table[i]->async_put_intf);
-+                      cancel_work_sync(&network_table[i]->async_get_intf);
-+                      if (rfk) {
-+                              rfkill_unregister(rfk);
-+                              rfkill_destroy(rfk);
-+                      }
-+                      hso_free_net_device(network_table[i]);
-+              }
-+      }
-+}
-+
-+/* Helper functions */
-+
-+/* Get the endpoint ! */
-+static struct usb_endpoint_descriptor *hso_get_ep(struct usb_interface *intf,
-+                                                int type, int dir)
-+{
-+      int i;
-+      struct usb_host_interface *iface = intf->cur_altsetting;
-+      struct usb_endpoint_descriptor *endp;
-+
-+      for (i = 0; i < iface->desc.bNumEndpoints; i++) {
-+              endp = &iface->endpoint[i].desc;
-+              if (((endp->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == dir) &&
-+                  (usb_endpoint_type(endp) == type))
-+                      return endp;
-+      }
-+
-+      return NULL;
-+}
-+
-+/* Get the byte that describes which ports are enabled */
-+static int hso_get_mux_ports(struct usb_interface *intf, unsigned char *ports)
-+{
-+      int i;
-+      struct usb_host_interface *iface = intf->cur_altsetting;
-+
-+      if (iface->extralen == 3) {
-+              *ports = iface->extra[2];
-+              return 0;
-+      }
-+
-+      for (i = 0; i < iface->desc.bNumEndpoints; i++) {
-+              if (iface->endpoint[i].extralen == 3) {
-+                      *ports = iface->endpoint[i].extra[2];
-+                      return 0;
-+              }
-+      }
-+
-+      return -1;
-+}
-+
-+/* interrupt urb needs to be submitted, used for serial read of muxed port */
-+static int hso_mux_submit_intr_urb(struct hso_shared_int *shared_int,
-+                                 struct usb_device *usb, gfp_t gfp)
-+{
-+      int result;
-+
-+      usb_fill_int_urb(shared_int->shared_intr_urb, usb,
-+                       usb_rcvintpipe(usb,
-+                              shared_int->intr_endp->bEndpointAddress & 0x7F),
-+                       shared_int->shared_intr_buf,
-+                       1,
-+                       intr_callback, shared_int,
-+                       shared_int->intr_endp->bInterval);
-+
-+      result = usb_submit_urb(shared_int->shared_intr_urb, gfp);
-+      if (result)
-+              dev_warn(&usb->dev, "%s failed mux_intr_urb %d\n", __func__,
-+                      result);
-+
-+      return result;
-+}
-+
-+/* operations setup of the serial interface */
-+static const struct tty_operations hso_serial_ops = {
-+      .open = hso_serial_open,
-+      .close = hso_serial_close,
-+      .write = hso_serial_write,
-+      .write_room = hso_serial_write_room,
-+      .cleanup = hso_serial_cleanup,
-+      .ioctl = hso_serial_ioctl,
-+      .set_termios = hso_serial_set_termios,
-+      .chars_in_buffer = hso_serial_chars_in_buffer,
-+      .tiocmget = hso_serial_tiocmget,
-+      .tiocmset = hso_serial_tiocmset,
-+      .get_icount = hso_get_count,
-+      .unthrottle = hso_unthrottle
-+};
-+
-+static struct usb_driver hso_driver = {
-+      .name = driver_name,
-+      .probe = hso_probe,
-+      .disconnect = hso_disconnect,
-+      .id_table = hso_ids,
-+      .suspend = hso_suspend,
-+      .resume = hso_resume,
-+      .reset_resume = hso_resume,
-+      .supports_autosuspend = 1,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+static int __init hso_init(void)
-+{
-+      int i;
-+      int result;
-+
-+      /* put it in the log */
-+      printk(KERN_INFO "hso: %s\n", version);
-+
-+      /* Initialise the serial table semaphore and table */
-+      spin_lock_init(&serial_table_lock);
-+      for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++)
-+              serial_table[i] = NULL;
-+
-+      /* allocate our driver using the proper amount of supported minors */
-+      tty_drv = alloc_tty_driver(HSO_SERIAL_TTY_MINORS);
-+      if (!tty_drv)
-+              return -ENOMEM;
-+
-+      /* fill in all needed values */
-+      tty_drv->driver_name = driver_name;
-+      tty_drv->name = tty_filename;
-+
-+      /* if major number is provided as parameter, use that one */
-+      if (tty_major)
-+              tty_drv->major = tty_major;
-+
-+      tty_drv->minor_start = 0;
-+      tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
-+      tty_drv->subtype = SERIAL_TYPE_NORMAL;
-+      tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-+      tty_drv->init_termios = tty_std_termios;
-+      hso_init_termios(&tty_drv->init_termios);
-+      tty_set_operations(tty_drv, &hso_serial_ops);
-+
-+      /* register the tty driver */
-+      result = tty_register_driver(tty_drv);
-+      if (result) {
-+              printk(KERN_ERR "%s - tty_register_driver failed(%d)\n",
-+                      __func__, result);
-+              goto err_free_tty;
-+      }
-+
-+      /* register this module as an usb driver */
-+      result = usb_register(&hso_driver);
-+      if (result) {
-+              printk(KERN_ERR "Could not register hso driver? error: %d\n",
-+                      result);
-+              goto err_unreg_tty;
-+      }
-+
-+      /* done */
-+      return 0;
-+err_unreg_tty:
-+      tty_unregister_driver(tty_drv);
-+err_free_tty:
-+      put_tty_driver(tty_drv);
-+      return result;
-+}
-+
-+static void __exit hso_exit(void)
-+{
-+      printk(KERN_INFO "hso: unloaded\n");
-+
-+      tty_unregister_driver(tty_drv);
-+      put_tty_driver(tty_drv);
-+      /* deregister the usb driver */
-+      usb_deregister(&hso_driver);
-+}
-+
-+/* Module definitions */
-+module_init(hso_init);
-+module_exit(hso_exit);
-+
-+MODULE_AUTHOR(MOD_AUTHOR);
-+MODULE_DESCRIPTION(MOD_DESCRIPTION);
-+MODULE_LICENSE(MOD_LICENSE);
-+
-+/* change the debug level (eg: insmod hso.ko debug=0x04) */
-+MODULE_PARM_DESC(debug, "Level of debug [0x01 | 0x02 | 0x04 | 0x08 | 0x10]");
-+module_param(debug, int, S_IRUGO | S_IWUSR);
-+
-+/* set the major tty number (eg: insmod hso.ko tty_major=245) */
-+MODULE_PARM_DESC(tty_major, "Set the major tty number");
-+module_param(tty_major, int, S_IRUGO | S_IWUSR);
-+
-+/* disable network interface (eg: insmod hso.ko disable_net=1) */
-+MODULE_PARM_DESC(disable_net, "Disable the network interface");
-+module_param(disable_net, int, S_IRUGO | S_IWUSR);
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/huawei_cdc_ncm.c backports-4.2.6-1/drivers/net/usb/huawei_cdc_ncm.c
---- backports-4.2.6-1.org/drivers/net/usb/huawei_cdc_ncm.c     1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/huawei_cdc_ncm.c 2016-06-28 14:35:17.981973887 +0200
-@@ -0,0 +1,224 @@
-+/* huawei_cdc_ncm.c - handles Huawei devices using the CDC NCM protocol as
-+ * transport layer.
-+ * Copyright (C) 2013  Enrico Mioso <mrkiko.rs@gmail.com>
-+ *
-+ *
-+ * ABSTRACT:
-+ * This driver handles devices resembling the CDC NCM standard, but
-+ * encapsulating another protocol inside it. An example are some Huawei 3G
-+ * devices, exposing an embedded AT channel where you can set up the NCM
-+ * connection.
-+ * This code has been heavily inspired by the cdc_mbim.c driver, which is
-+ * Copyright (c) 2012  Smith Micro Software, Inc.
-+ * Copyright (c) 2012  Bjørn Mork <bjorn@mork.no>
-+ *
-+ * 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.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/if_vlan.h>
-+#include <linux/ip.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/usb/cdc.h>
-+#include <linux/usb/usbnet.h>
-+#include <linux/usb/cdc-wdm.h>
-+#include <linux/usb/cdc_ncm.h>
-+
-+/* Driver data */
-+struct huawei_cdc_ncm_state {
-+      struct cdc_ncm_ctx *ctx;
-+      atomic_t pmcount;
-+      struct usb_driver *subdriver;
-+      struct usb_interface *control;
-+      struct usb_interface *data;
-+};
-+
-+static int huawei_cdc_ncm_manage_power(struct usbnet *usbnet_dev, int on)
-+{
-+      struct huawei_cdc_ncm_state *drvstate = (void *)&usbnet_dev->data;
-+      int rv;
-+
-+      if ((on && atomic_add_return(1, &drvstate->pmcount) == 1) ||
-+                      (!on && atomic_dec_and_test(&drvstate->pmcount))) {
-+              rv = usb_autopm_get_interface(usbnet_dev->intf);
-+              usbnet_dev->intf->needs_remote_wakeup = on;
-+              if (!rv)
-+                      usb_autopm_put_interface(usbnet_dev->intf);
-+      }
-+      return 0;
-+}
-+
-+static int huawei_cdc_ncm_wdm_manage_power(struct usb_interface *intf,
-+                                         int status)
-+{
-+      struct usbnet *usbnet_dev = usb_get_intfdata(intf);
-+
-+      /* can be called while disconnecting */
-+      if (!usbnet_dev)
-+              return 0;
-+
-+      return huawei_cdc_ncm_manage_power(usbnet_dev, status);
-+}
-+
-+
-+static int huawei_cdc_ncm_bind(struct usbnet *usbnet_dev,
-+                             struct usb_interface *intf)
-+{
-+      struct cdc_ncm_ctx *ctx;
-+      struct usb_driver *subdriver = ERR_PTR(-ENODEV);
-+      int ret = -ENODEV;
-+      struct huawei_cdc_ncm_state *drvstate = (void *)&usbnet_dev->data;
-+      int drvflags = 0;
-+
-+      /* altsetting should always be 1 for NCM devices - so we hard-coded
-+       * it here. Some huawei devices will need the NDP part of the NCM package to
-+       * be at the end of the frame.
-+       */
-+      drvflags |= CDC_NCM_FLAG_NDP_TO_END;
-+      ret = cdc_ncm_bind_common(usbnet_dev, intf, 1, drvflags);
-+      if (ret)
-+              goto err;
-+
-+      ctx = drvstate->ctx;
-+
-+      if (usbnet_dev->status)
-+              /* The wMaxCommand buffer must be big enough to hold
-+               * any message from the modem. Experience has shown
-+               * that some replies are more than 256 bytes long
-+               */
-+              subdriver = usb_cdc_wdm_register(ctx->control,
-+                                               &usbnet_dev->status->desc,
-+                                               1024, /* wMaxCommand */
-+                                               huawei_cdc_ncm_wdm_manage_power);
-+      if (IS_ERR(subdriver)) {
-+              ret = PTR_ERR(subdriver);
-+              cdc_ncm_unbind(usbnet_dev, intf);
-+              goto err;
-+      }
-+
-+      /* Prevent usbnet from using the status descriptor */
-+      usbnet_dev->status = NULL;
-+
-+      drvstate->subdriver = subdriver;
-+
-+err:
-+      return ret;
-+}
-+
-+static void huawei_cdc_ncm_unbind(struct usbnet *usbnet_dev,
-+                                struct usb_interface *intf)
-+{
-+      struct huawei_cdc_ncm_state *drvstate = (void *)&usbnet_dev->data;
-+      struct cdc_ncm_ctx *ctx = drvstate->ctx;
-+
-+      if (drvstate->subdriver && drvstate->subdriver->disconnect)
-+              drvstate->subdriver->disconnect(ctx->control);
-+      drvstate->subdriver = NULL;
-+
-+      cdc_ncm_unbind(usbnet_dev, intf);
-+}
-+
-+static int huawei_cdc_ncm_suspend(struct usb_interface *intf,
-+                                pm_message_t message)
-+{
-+      int ret = 0;
-+      struct usbnet *usbnet_dev = usb_get_intfdata(intf);
-+      struct huawei_cdc_ncm_state *drvstate = (void *)&usbnet_dev->data;
-+      struct cdc_ncm_ctx *ctx = drvstate->ctx;
-+
-+      if (ctx == NULL) {
-+              ret = -ENODEV;
-+              goto error;
-+      }
-+
-+      ret = usbnet_suspend(intf, message);
-+      if (ret < 0)
-+              goto error;
-+
-+      if (intf == ctx->control &&
-+              drvstate->subdriver &&
-+              drvstate->subdriver->suspend)
-+              ret = drvstate->subdriver->suspend(intf, message);
-+      if (ret < 0)
-+              usbnet_resume(intf);
-+
-+error:
-+      return ret;
-+}
-+
-+static int huawei_cdc_ncm_resume(struct usb_interface *intf)
-+{
-+      int ret = 0;
-+      struct usbnet *usbnet_dev = usb_get_intfdata(intf);
-+      struct huawei_cdc_ncm_state *drvstate = (void *)&usbnet_dev->data;
-+      bool callsub;
-+      struct cdc_ncm_ctx *ctx = drvstate->ctx;
-+
-+      /* should we call subdriver's resume function? */
-+      callsub =
-+              (intf == ctx->control &&
-+              drvstate->subdriver &&
-+              drvstate->subdriver->resume);
-+
-+      if (callsub)
-+              ret = drvstate->subdriver->resume(intf);
-+      if (ret < 0)
-+              goto err;
-+      ret = usbnet_resume(intf);
-+      if (ret < 0 && callsub)
-+              drvstate->subdriver->suspend(intf, PMSG_SUSPEND);
-+err:
-+      return ret;
-+}
-+
-+static const struct driver_info huawei_cdc_ncm_info = {
-+      .description = "Huawei CDC NCM device",
-+      .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN,
-+      .bind = huawei_cdc_ncm_bind,
-+      .unbind = huawei_cdc_ncm_unbind,
-+      .manage_power = huawei_cdc_ncm_manage_power,
-+      .rx_fixup = cdc_ncm_rx_fixup,
-+      .tx_fixup = cdc_ncm_tx_fixup,
-+};
-+
-+static const struct usb_device_id huawei_cdc_ncm_devs[] = {
-+      /* Huawei NCM devices disguised as vendor specific */
-+      { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16),
-+        .driver_info = (unsigned long)&huawei_cdc_ncm_info,
-+      },
-+      { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46),
-+        .driver_info = (unsigned long)&huawei_cdc_ncm_info,
-+      },
-+      { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x76),
-+        .driver_info = (unsigned long)&huawei_cdc_ncm_info,
-+      },
-+      { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x03, 0x16),
-+        .driver_info = (unsigned long)&huawei_cdc_ncm_info,
-+      },
-+
-+      /* Terminating entry */
-+      {
-+      },
-+};
-+MODULE_DEVICE_TABLE(usb, huawei_cdc_ncm_devs);
-+
-+static struct usb_driver huawei_cdc_ncm_driver = {
-+      .name = "huawei_cdc_ncm",
-+      .id_table = huawei_cdc_ncm_devs,
-+      .probe = usbnet_probe,
-+      .disconnect = usbnet_disconnect,
-+      .suspend = huawei_cdc_ncm_suspend,
-+      .resume = huawei_cdc_ncm_resume,
-+      .reset_resume = huawei_cdc_ncm_resume,
-+      .supports_autosuspend = 1,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+module_usb_driver(huawei_cdc_ncm_driver);
-+MODULE_AUTHOR("Enrico Mioso <mrkiko.rs@gmail.com>");
-+MODULE_DESCRIPTION("USB CDC NCM host driver with encapsulated protocol support");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/int51x1.c backports-4.2.6-1/drivers/net/usb/int51x1.c
---- backports-4.2.6-1.org/drivers/net/usb/int51x1.c    1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/int51x1.c        2016-06-28 14:35:17.985307220 +0200
-@@ -0,0 +1,199 @@
-+/*
-+ * Copyright (c) 2009 Peter Holik
-+ *
-+ * Intellon usb PLC (Powerline Communications) usb net driver
-+ *
-+ * http://www.tandel.be/downloads/INT51X1_Datasheet.pdf
-+ *
-+ * Based on the work of Jan 'RedBully' Seiffert
-+ */
-+
-+/*
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/ctype.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/slab.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/usb/usbnet.h>
-+
-+#define INT51X1_VENDOR_ID     0x09e1
-+#define INT51X1_PRODUCT_ID    0x5121
-+
-+#define INT51X1_HEADER_SIZE   2       /* 2 byte header */
-+
-+#define PACKET_TYPE_PROMISCUOUS               (1 << 0)
-+#define PACKET_TYPE_ALL_MULTICAST     (1 << 1) /* no filter */
-+#define PACKET_TYPE_DIRECTED          (1 << 2)
-+#define PACKET_TYPE_BROADCAST         (1 << 3)
-+#define PACKET_TYPE_MULTICAST         (1 << 4) /* filtered */
-+
-+#define SET_ETHERNET_PACKET_FILTER    0x43
-+
-+static int int51x1_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      int len;
-+
-+      if (!(pskb_may_pull(skb, INT51X1_HEADER_SIZE))) {
-+              netdev_err(dev->net, "unexpected tiny rx frame\n");
-+              return 0;
-+      }
-+
-+      len = le16_to_cpu(*(__le16 *)&skb->data[skb->len - 2]);
-+
-+      skb_trim(skb, len);
-+
-+      return 1;
-+}
-+
-+static struct sk_buff *int51x1_tx_fixup(struct usbnet *dev,
-+              struct sk_buff *skb, gfp_t flags)
-+{
-+      int pack_len = skb->len;
-+      int pack_with_header_len = pack_len + INT51X1_HEADER_SIZE;
-+      int headroom = skb_headroom(skb);
-+      int tailroom = skb_tailroom(skb);
-+      int need_tail = 0;
-+      __le16 *len;
-+
-+      /* if packet and our header is smaler than 64 pad to 64 (+ ZLP) */
-+      if ((pack_with_header_len) < dev->maxpacket)
-+              need_tail = dev->maxpacket - pack_with_header_len + 1;
-+      /*
-+       * usbnet would send a ZLP if packetlength mod urbsize == 0 for us,
-+       * but we need to know ourself, because this would add to the length
-+       * we send down to the device...
-+       */
-+      else if (!(pack_with_header_len % dev->maxpacket))
-+              need_tail = 1;
-+
-+      if (!skb_cloned(skb) &&
-+                      (headroom + tailroom >= need_tail + INT51X1_HEADER_SIZE)) {
-+              if (headroom < INT51X1_HEADER_SIZE || tailroom < need_tail) {
-+                      skb->data = memmove(skb->head + INT51X1_HEADER_SIZE,
-+                                      skb->data, skb->len);
-+                      skb_set_tail_pointer(skb, skb->len);
-+              }
-+      } else {
-+              struct sk_buff *skb2;
-+
-+              skb2 = skb_copy_expand(skb,
-+                              INT51X1_HEADER_SIZE,
-+                              need_tail,
-+                              flags);
-+              dev_kfree_skb_any(skb);
-+              if (!skb2)
-+                      return NULL;
-+              skb = skb2;
-+      }
-+
-+      pack_len += need_tail;
-+      pack_len &= 0x07ff;
-+
-+      len = (__le16 *) __skb_push(skb, INT51X1_HEADER_SIZE);
-+      *len = cpu_to_le16(pack_len);
-+
-+      if(need_tail)
-+              memset(__skb_put(skb, need_tail), 0, need_tail);
-+
-+      return skb;
-+}
-+
-+static void int51x1_set_multicast(struct net_device *netdev)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      u16 filter = PACKET_TYPE_DIRECTED | PACKET_TYPE_BROADCAST;
-+
-+      if (netdev->flags & IFF_PROMISC) {
-+              /* do not expect to see traffic of other PLCs */
-+              filter |= PACKET_TYPE_PROMISCUOUS;
-+              netdev_info(dev->net, "promiscuous mode enabled\n");
-+      } else if (!netdev_mc_empty(netdev) ||
-+                (netdev->flags & IFF_ALLMULTI)) {
-+              filter |= PACKET_TYPE_ALL_MULTICAST;
-+              netdev_dbg(dev->net, "receive all multicast enabled\n");
-+      } else {
-+              /* ~PROMISCUOUS, ~MULTICAST */
-+              netdev_dbg(dev->net, "receive own packets only\n");
-+      }
-+
-+      usbnet_write_cmd_async(dev, SET_ETHERNET_PACKET_FILTER,
-+                             USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-+                             filter, 0, NULL, 0);
-+}
-+
-+static const struct net_device_ops int51x1_netdev_ops = {
-+      .ndo_open               = usbnet_open,
-+      .ndo_stop               = usbnet_stop,
-+      .ndo_start_xmit         = usbnet_start_xmit,
-+      .ndo_tx_timeout         = usbnet_tx_timeout,
-+      .ndo_change_mtu         = usbnet_change_mtu,
-+      .ndo_set_mac_address    = eth_mac_addr,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_set_rx_mode        = int51x1_set_multicast,
-+};
-+
-+static int int51x1_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      int status = usbnet_get_ethernet_addr(dev, 3);
-+
-+      if (status)
-+              return status;
-+
-+      dev->net->hard_header_len += INT51X1_HEADER_SIZE;
-+      dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
-+      dev->net->netdev_ops = &int51x1_netdev_ops;
-+
-+      return usbnet_get_endpoints(dev, intf);
-+}
-+
-+static const struct driver_info int51x1_info = {
-+      .description = "Intellon usb powerline adapter",
-+      .bind        = int51x1_bind,
-+      .rx_fixup    = int51x1_rx_fixup,
-+      .tx_fixup    = int51x1_tx_fixup,
-+      .in          = 1,
-+      .out         = 2,
-+      .flags       = FLAG_ETHER,
-+};
-+
-+static const struct usb_device_id products[] = {
-+      {
-+      USB_DEVICE(INT51X1_VENDOR_ID, INT51X1_PRODUCT_ID),
-+              .driver_info = (unsigned long) &int51x1_info,
-+      },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver int51x1_driver = {
-+      .name       = "int51x1",
-+      .id_table   = products,
-+      .probe      = usbnet_probe,
-+      .disconnect = usbnet_disconnect,
-+      .suspend    = usbnet_suspend,
-+      .resume     = usbnet_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(int51x1_driver);
-+
-+MODULE_AUTHOR("Peter Holik");
-+MODULE_DESCRIPTION("Intellon usb powerline adapter");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/ipheth.c backports-4.2.6-1/drivers/net/usb/ipheth.c
---- backports-4.2.6-1.org/drivers/net/usb/ipheth.c     1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/ipheth.c 2016-06-28 14:35:17.985307220 +0200
-@@ -0,0 +1,588 @@
-+/*
-+ * ipheth.c - Apple iPhone USB Ethernet driver
-+ *
-+ * Copyright (c) 2009 Diego Giagio <diego@giagio.com>
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in the
-+ *    documentation and/or other materials provided with the distribution.
-+ * 3. Neither the name of GIAGIO.COM nor the names of its contributors
-+ *    may be used to endorse or promote products derived from this software
-+ *    without specific prior written permission.
-+ *
-+ * Alternatively, provided that this notice is retained in full, this
-+ * software may be distributed under the terms of the GNU General
-+ * Public License ("GPL") version 2, in which case the provisions of the
-+ * GPL apply INSTEAD OF those given above.
-+ *
-+ * The provided data structures and external interfaces from this code
-+ * are not restricted to be used by modules with a GPL compatible license.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ *
-+ * Attention: iPhone device must be paired, otherwise it won't respond to our
-+ * driver. For more info: http://giagio.com/wiki/moin.cgi/iPhoneEthernetDriver
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/slab.h>
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/usb.h>
-+#include <linux/workqueue.h>
-+
-+#define USB_VENDOR_APPLE        0x05ac
-+#define USB_PRODUCT_IPHONE      0x1290
-+#define USB_PRODUCT_IPHONE_3G   0x1292
-+#define USB_PRODUCT_IPHONE_3GS  0x1294
-+#define USB_PRODUCT_IPHONE_4  0x1297
-+#define USB_PRODUCT_IPAD 0x129a
-+#define USB_PRODUCT_IPAD_2    0x12a2
-+#define USB_PRODUCT_IPAD_3    0x12a6
-+#define USB_PRODUCT_IPAD_MINI    0x12ab
-+#define USB_PRODUCT_IPHONE_4_VZW 0x129c
-+#define USB_PRODUCT_IPHONE_4S 0x12a0
-+#define USB_PRODUCT_IPHONE_5  0x12a8
-+
-+#define IPHETH_USBINTF_CLASS    255
-+#define IPHETH_USBINTF_SUBCLASS 253
-+#define IPHETH_USBINTF_PROTO    1
-+
-+#define IPHETH_BUF_SIZE         1516
-+#define IPHETH_IP_ALIGN               2       /* padding at front of URB */
-+#define IPHETH_TX_TIMEOUT       (5 * HZ)
-+
-+#define IPHETH_INTFNUM          2
-+#define IPHETH_ALT_INTFNUM      1
-+
-+#define IPHETH_CTRL_ENDP        0x00
-+#define IPHETH_CTRL_BUF_SIZE    0x40
-+#define IPHETH_CTRL_TIMEOUT     (5 * HZ)
-+
-+#define IPHETH_CMD_GET_MACADDR   0x00
-+#define IPHETH_CMD_CARRIER_CHECK 0x45
-+
-+#define IPHETH_CARRIER_CHECK_TIMEOUT round_jiffies_relative(1 * HZ)
-+#define IPHETH_CARRIER_ON       0x04
-+
-+static struct usb_device_id ipheth_table[] = {
-+      { USB_DEVICE_AND_INTERFACE_INFO(
-+              USB_VENDOR_APPLE, USB_PRODUCT_IPHONE,
-+              IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
-+              IPHETH_USBINTF_PROTO) },
-+      { USB_DEVICE_AND_INTERFACE_INFO(
-+              USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_3G,
-+              IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
-+              IPHETH_USBINTF_PROTO) },
-+      { USB_DEVICE_AND_INTERFACE_INFO(
-+              USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_3GS,
-+              IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
-+              IPHETH_USBINTF_PROTO) },
-+      { USB_DEVICE_AND_INTERFACE_INFO(
-+              USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4,
-+              IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
-+              IPHETH_USBINTF_PROTO) },
-+      { USB_DEVICE_AND_INTERFACE_INFO(
-+              USB_VENDOR_APPLE, USB_PRODUCT_IPAD,
-+              IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
-+              IPHETH_USBINTF_PROTO) },
-+      { USB_DEVICE_AND_INTERFACE_INFO(
-+              USB_VENDOR_APPLE, USB_PRODUCT_IPAD_2,
-+              IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
-+              IPHETH_USBINTF_PROTO) },
-+      { USB_DEVICE_AND_INTERFACE_INFO(
-+              USB_VENDOR_APPLE, USB_PRODUCT_IPAD_3,
-+              IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
-+              IPHETH_USBINTF_PROTO) },
-+      { USB_DEVICE_AND_INTERFACE_INFO(
-+              USB_VENDOR_APPLE, USB_PRODUCT_IPAD_MINI,
-+              IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
-+              IPHETH_USBINTF_PROTO) },
-+      { USB_DEVICE_AND_INTERFACE_INFO(
-+              USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW,
-+              IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
-+              IPHETH_USBINTF_PROTO) },
-+      { USB_DEVICE_AND_INTERFACE_INFO(
-+              USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S,
-+              IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
-+              IPHETH_USBINTF_PROTO) },
-+      { USB_DEVICE_AND_INTERFACE_INFO(
-+              USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5,
-+              IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
-+              IPHETH_USBINTF_PROTO) },
-+      { }
-+};
-+MODULE_DEVICE_TABLE(usb, ipheth_table);
-+
-+struct ipheth_device {
-+      struct usb_device *udev;
-+      struct usb_interface *intf;
-+      struct net_device *net;
-+      struct sk_buff *tx_skb;
-+      struct urb *tx_urb;
-+      struct urb *rx_urb;
-+      unsigned char *tx_buf;
-+      unsigned char *rx_buf;
-+      unsigned char *ctrl_buf;
-+      u8 bulk_in;
-+      u8 bulk_out;
-+      struct delayed_work carrier_work;
-+};
-+
-+static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags);
-+
-+static int ipheth_alloc_urbs(struct ipheth_device *iphone)
-+{
-+      struct urb *tx_urb = NULL;
-+      struct urb *rx_urb = NULL;
-+      u8 *tx_buf = NULL;
-+      u8 *rx_buf = NULL;
-+
-+      tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (tx_urb == NULL)
-+              goto error_nomem;
-+
-+      rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (rx_urb == NULL)
-+              goto free_tx_urb;
-+
-+      tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE,
-+                                  GFP_KERNEL, &tx_urb->transfer_dma);
-+      if (tx_buf == NULL)
-+              goto free_rx_urb;
-+
-+      rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE,
-+                                  GFP_KERNEL, &rx_urb->transfer_dma);
-+      if (rx_buf == NULL)
-+              goto free_tx_buf;
-+
-+
-+      iphone->tx_urb = tx_urb;
-+      iphone->rx_urb = rx_urb;
-+      iphone->tx_buf = tx_buf;
-+      iphone->rx_buf = rx_buf;
-+      return 0;
-+
-+free_tx_buf:
-+      usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, tx_buf,
-+                        tx_urb->transfer_dma);
-+free_rx_urb:
-+      usb_free_urb(rx_urb);
-+free_tx_urb:
-+      usb_free_urb(tx_urb);
-+error_nomem:
-+      return -ENOMEM;
-+}
-+
-+static void ipheth_free_urbs(struct ipheth_device *iphone)
-+{
-+      usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->rx_buf,
-+                        iphone->rx_urb->transfer_dma);
-+      usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf,
-+                        iphone->tx_urb->transfer_dma);
-+      usb_free_urb(iphone->rx_urb);
-+      usb_free_urb(iphone->tx_urb);
-+}
-+
-+static void ipheth_kill_urbs(struct ipheth_device *dev)
-+{
-+      usb_kill_urb(dev->tx_urb);
-+      usb_kill_urb(dev->rx_urb);
-+}
-+
-+static void ipheth_rcvbulk_callback(struct urb *urb)
-+{
-+      struct ipheth_device *dev;
-+      struct sk_buff *skb;
-+      int status;
-+      char *buf;
-+      int len;
-+
-+      dev = urb->context;
-+      if (dev == NULL)
-+              return;
-+
-+      status = urb->status;
-+      switch (status) {
-+      case -ENOENT:
-+      case -ECONNRESET:
-+      case -ESHUTDOWN:
-+              return;
-+      case 0:
-+              break;
-+      default:
-+              dev_err(&dev->intf->dev, "%s: urb status: %d\n",
-+                      __func__, status);
-+              return;
-+      }
-+
-+      if (urb->actual_length <= IPHETH_IP_ALIGN) {
-+              dev->net->stats.rx_length_errors++;
-+              return;
-+      }
-+      len = urb->actual_length - IPHETH_IP_ALIGN;
-+      buf = urb->transfer_buffer + IPHETH_IP_ALIGN;
-+
-+      skb = dev_alloc_skb(len);
-+      if (!skb) {
-+              dev_err(&dev->intf->dev, "%s: dev_alloc_skb: -ENOMEM\n",
-+                      __func__);
-+              dev->net->stats.rx_dropped++;
-+              return;
-+      }
-+
-+      memcpy(skb_put(skb, len), buf, len);
-+      skb->dev = dev->net;
-+      skb->protocol = eth_type_trans(skb, dev->net);
-+
-+      dev->net->stats.rx_packets++;
-+      dev->net->stats.rx_bytes += len;
-+
-+      netif_rx(skb);
-+      ipheth_rx_submit(dev, GFP_ATOMIC);
-+}
-+
-+static void ipheth_sndbulk_callback(struct urb *urb)
-+{
-+      struct ipheth_device *dev;
-+      int status = urb->status;
-+
-+      dev = urb->context;
-+      if (dev == NULL)
-+              return;
-+
-+      if (status != 0 &&
-+          status != -ENOENT &&
-+          status != -ECONNRESET &&
-+          status != -ESHUTDOWN)
-+              dev_err(&dev->intf->dev, "%s: urb status: %d\n",
-+              __func__, status);
-+
-+      dev_kfree_skb_irq(dev->tx_skb);
-+      netif_wake_queue(dev->net);
-+}
-+
-+static int ipheth_carrier_set(struct ipheth_device *dev)
-+{
-+      struct usb_device *udev = dev->udev;
-+      int retval;
-+
-+      retval = usb_control_msg(udev,
-+                      usb_rcvctrlpipe(udev, IPHETH_CTRL_ENDP),
-+                      IPHETH_CMD_CARRIER_CHECK, /* request */
-+                      0xc0, /* request type */
-+                      0x00, /* value */
-+                      0x02, /* index */
-+                      dev->ctrl_buf, IPHETH_CTRL_BUF_SIZE,
-+                      IPHETH_CTRL_TIMEOUT);
-+      if (retval < 0) {
-+              dev_err(&dev->intf->dev, "%s: usb_control_msg: %d\n",
-+                      __func__, retval);
-+              return retval;
-+      }
-+
-+      if (dev->ctrl_buf[0] == IPHETH_CARRIER_ON)
-+              netif_carrier_on(dev->net);
-+      else
-+              netif_carrier_off(dev->net);
-+
-+      return 0;
-+}
-+
-+static void ipheth_carrier_check_work(struct work_struct *work)
-+{
-+      struct ipheth_device *dev = container_of(work, struct ipheth_device,
-+                                               carrier_work.work);
-+
-+      ipheth_carrier_set(dev);
-+      schedule_delayed_work(&dev->carrier_work, IPHETH_CARRIER_CHECK_TIMEOUT);
-+}
-+
-+static int ipheth_get_macaddr(struct ipheth_device *dev)
-+{
-+      struct usb_device *udev = dev->udev;
-+      struct net_device *net = dev->net;
-+      int retval;
-+
-+      retval = usb_control_msg(udev,
-+                               usb_rcvctrlpipe(udev, IPHETH_CTRL_ENDP),
-+                               IPHETH_CMD_GET_MACADDR, /* request */
-+                               0xc0, /* request type */
-+                               0x00, /* value */
-+                               0x02, /* index */
-+                               dev->ctrl_buf,
-+                               IPHETH_CTRL_BUF_SIZE,
-+                               IPHETH_CTRL_TIMEOUT);
-+      if (retval < 0) {
-+              dev_err(&dev->intf->dev, "%s: usb_control_msg: %d\n",
-+                      __func__, retval);
-+      } else if (retval < ETH_ALEN) {
-+              dev_err(&dev->intf->dev,
-+                      "%s: usb_control_msg: short packet: %d bytes\n",
-+                      __func__, retval);
-+              retval = -EINVAL;
-+      } else {
-+              memcpy(net->dev_addr, dev->ctrl_buf, ETH_ALEN);
-+              retval = 0;
-+      }
-+
-+      return retval;
-+}
-+
-+static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags)
-+{
-+      struct usb_device *udev = dev->udev;
-+      int retval;
-+
-+      usb_fill_bulk_urb(dev->rx_urb, udev,
-+                        usb_rcvbulkpipe(udev, dev->bulk_in),
-+                        dev->rx_buf, IPHETH_BUF_SIZE,
-+                        ipheth_rcvbulk_callback,
-+                        dev);
-+      dev->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-+
-+      retval = usb_submit_urb(dev->rx_urb, mem_flags);
-+      if (retval)
-+              dev_err(&dev->intf->dev, "%s: usb_submit_urb: %d\n",
-+                      __func__, retval);
-+      return retval;
-+}
-+
-+static int ipheth_open(struct net_device *net)
-+{
-+      struct ipheth_device *dev = netdev_priv(net);
-+      struct usb_device *udev = dev->udev;
-+      int retval = 0;
-+
-+      usb_set_interface(udev, IPHETH_INTFNUM, IPHETH_ALT_INTFNUM);
-+
-+      retval = ipheth_carrier_set(dev);
-+      if (retval)
-+              return retval;
-+
-+      retval = ipheth_rx_submit(dev, GFP_KERNEL);
-+      if (retval)
-+              return retval;
-+
-+      schedule_delayed_work(&dev->carrier_work, IPHETH_CARRIER_CHECK_TIMEOUT);
-+      netif_start_queue(net);
-+      return retval;
-+}
-+
-+static int ipheth_close(struct net_device *net)
-+{
-+      struct ipheth_device *dev = netdev_priv(net);
-+
-+      cancel_delayed_work_sync(&dev->carrier_work);
-+      netif_stop_queue(net);
-+      return 0;
-+}
-+
-+static int ipheth_tx(struct sk_buff *skb, struct net_device *net)
-+{
-+      struct ipheth_device *dev = netdev_priv(net);
-+      struct usb_device *udev = dev->udev;
-+      int retval;
-+
-+      /* Paranoid */
-+      if (skb->len > IPHETH_BUF_SIZE) {
-+              WARN(1, "%s: skb too large: %d bytes\n", __func__, skb->len);
-+              dev->net->stats.tx_dropped++;
-+              dev_kfree_skb_irq(skb);
-+              return NETDEV_TX_OK;
-+      }
-+
-+      memcpy(dev->tx_buf, skb->data, skb->len);
-+      if (skb->len < IPHETH_BUF_SIZE)
-+              memset(dev->tx_buf + skb->len, 0, IPHETH_BUF_SIZE - skb->len);
-+
-+      usb_fill_bulk_urb(dev->tx_urb, udev,
-+                        usb_sndbulkpipe(udev, dev->bulk_out),
-+                        dev->tx_buf, IPHETH_BUF_SIZE,
-+                        ipheth_sndbulk_callback,
-+                        dev);
-+      dev->tx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-+
-+      retval = usb_submit_urb(dev->tx_urb, GFP_ATOMIC);
-+      if (retval) {
-+              dev_err(&dev->intf->dev, "%s: usb_submit_urb: %d\n",
-+                      __func__, retval);
-+              dev->net->stats.tx_errors++;
-+              dev_kfree_skb_irq(skb);
-+      } else {
-+              dev->tx_skb = skb;
-+
-+              dev->net->stats.tx_packets++;
-+              dev->net->stats.tx_bytes += skb->len;
-+              netif_stop_queue(net);
-+      }
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+static void ipheth_tx_timeout(struct net_device *net)
-+{
-+      struct ipheth_device *dev = netdev_priv(net);
-+
-+      dev_err(&dev->intf->dev, "%s: TX timeout\n", __func__);
-+      dev->net->stats.tx_errors++;
-+      usb_unlink_urb(dev->tx_urb);
-+}
-+
-+static u32 ipheth_ethtool_op_get_link(struct net_device *net)
-+{
-+      struct ipheth_device *dev = netdev_priv(net);
-+      return netif_carrier_ok(dev->net);
-+}
-+
-+static const struct ethtool_ops ops = {
-+      .get_link = ipheth_ethtool_op_get_link
-+};
-+
-+static const struct net_device_ops ipheth_netdev_ops = {
-+      .ndo_open = ipheth_open,
-+      .ndo_stop = ipheth_close,
-+      .ndo_start_xmit = ipheth_tx,
-+      .ndo_tx_timeout = ipheth_tx_timeout,
-+};
-+
-+static int ipheth_probe(struct usb_interface *intf,
-+                      const struct usb_device_id *id)
-+{
-+      struct usb_device *udev = interface_to_usbdev(intf);
-+      struct usb_host_interface *hintf;
-+      struct usb_endpoint_descriptor *endp;
-+      struct ipheth_device *dev;
-+      struct net_device *netdev;
-+      int i;
-+      int retval;
-+
-+      netdev = alloc_etherdev(sizeof(struct ipheth_device));
-+      if (!netdev)
-+              return -ENOMEM;
-+
-+      netdev->netdev_ops = &ipheth_netdev_ops;
-+      netdev->watchdog_timeo = IPHETH_TX_TIMEOUT;
-+      strcpy(netdev->name, "eth%d");
-+
-+      dev = netdev_priv(netdev);
-+      dev->udev = udev;
-+      dev->net = netdev;
-+      dev->intf = intf;
-+
-+      /* Set up endpoints */
-+      hintf = usb_altnum_to_altsetting(intf, IPHETH_ALT_INTFNUM);
-+      if (hintf == NULL) {
-+              retval = -ENODEV;
-+              dev_err(&intf->dev, "Unable to find alternate settings interface\n");
-+              goto err_endpoints;
-+      }
-+
-+      for (i = 0; i < hintf->desc.bNumEndpoints; i++) {
-+              endp = &hintf->endpoint[i].desc;
-+              if (usb_endpoint_is_bulk_in(endp))
-+                      dev->bulk_in = endp->bEndpointAddress;
-+              else if (usb_endpoint_is_bulk_out(endp))
-+                      dev->bulk_out = endp->bEndpointAddress;
-+      }
-+      if (!(dev->bulk_in && dev->bulk_out)) {
-+              retval = -ENODEV;
-+              dev_err(&intf->dev, "Unable to find endpoints\n");
-+              goto err_endpoints;
-+      }
-+
-+      dev->ctrl_buf = kmalloc(IPHETH_CTRL_BUF_SIZE, GFP_KERNEL);
-+      if (dev->ctrl_buf == NULL) {
-+              retval = -ENOMEM;
-+              goto err_alloc_ctrl_buf;
-+      }
-+
-+      retval = ipheth_get_macaddr(dev);
-+      if (retval)
-+              goto err_get_macaddr;
-+
-+      INIT_DELAYED_WORK(&dev->carrier_work, ipheth_carrier_check_work);
-+
-+      retval = ipheth_alloc_urbs(dev);
-+      if (retval) {
-+              dev_err(&intf->dev, "error allocating urbs: %d\n", retval);
-+              goto err_alloc_urbs;
-+      }
-+
-+      usb_set_intfdata(intf, dev);
-+
-+      SET_NETDEV_DEV(netdev, &intf->dev);
-+      netdev->ethtool_ops = &ops;
-+
-+      retval = register_netdev(netdev);
-+      if (retval) {
-+              dev_err(&intf->dev, "error registering netdev: %d\n", retval);
-+              retval = -EIO;
-+              goto err_register_netdev;
-+      }
-+
-+      dev_info(&intf->dev, "Apple iPhone USB Ethernet device attached\n");
-+      return 0;
-+
-+err_register_netdev:
-+      ipheth_free_urbs(dev);
-+err_alloc_urbs:
-+err_get_macaddr:
-+err_alloc_ctrl_buf:
-+      kfree(dev->ctrl_buf);
-+err_endpoints:
-+      free_netdev(netdev);
-+      return retval;
-+}
-+
-+static void ipheth_disconnect(struct usb_interface *intf)
-+{
-+      struct ipheth_device *dev;
-+
-+      dev = usb_get_intfdata(intf);
-+      if (dev != NULL) {
-+              unregister_netdev(dev->net);
-+              ipheth_kill_urbs(dev);
-+              ipheth_free_urbs(dev);
-+              kfree(dev->ctrl_buf);
-+              free_netdev(dev->net);
-+      }
-+      usb_set_intfdata(intf, NULL);
-+      dev_info(&intf->dev, "Apple iPhone USB Ethernet now disconnected\n");
-+}
-+
-+static struct usb_driver ipheth_driver = {
-+      .name =         "ipheth",
-+      .probe =        ipheth_probe,
-+      .disconnect =   ipheth_disconnect,
-+      .id_table =     ipheth_table,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(ipheth_driver);
-+
-+MODULE_AUTHOR("Diego Giagio <diego@giagio.com>");
-+MODULE_DESCRIPTION("Apple iPhone USB Ethernet driver");
-+MODULE_LICENSE("Dual BSD/GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/kalmia.c backports-4.2.6-1/drivers/net/usb/kalmia.c
---- backports-4.2.6-1.org/drivers/net/usb/kalmia.c     1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/kalmia.c 2016-06-28 14:35:17.985307220 +0200
-@@ -0,0 +1,366 @@
-+/*
-+ * USB network interface driver for Samsung Kalmia based LTE USB modem like the
-+ * Samsung GT-B3730 and GT-B3710.
-+ *
-+ * Copyright (C) 2011 Marius Bjoernstad Kotsbak <marius@kotsbak.com>
-+ *
-+ * Sponsored by Quicklink Video Distribution Services Ltd.
-+ *
-+ * Based on the cdc_eem module.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ctype.h>
-+#include <linux/ethtool.h>
-+#include <linux/workqueue.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/crc32.h>
-+#include <linux/usb/cdc.h>
-+#include <linux/usb/usbnet.h>
-+#include <linux/gfp.h>
-+
-+/*
-+ * The Samsung Kalmia based LTE USB modems have a CDC ACM port for modem control
-+ * handled by the "option" module and an ethernet data port handled by this
-+ * module.
-+ *
-+ * The stick must first be switched into modem mode by usb_modeswitch
-+ * or similar tool. Then the modem gets sent two initialization packets by
-+ * this module, which gives the MAC address of the device. User space can then
-+ * connect the modem using AT commands through the ACM port and then use
-+ * DHCP on the network interface exposed by this module. Network packets are
-+ * sent to and from the modem in a proprietary format discovered after watching
-+ * the behavior of the windows driver for the modem.
-+ *
-+ * More information about the use of the modem is available in usb_modeswitch
-+ * forum and the project page:
-+ *
-+ * http://www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?t=465
-+ * https://github.com/mkotsbak/Samsung-GT-B3730-linux-driver
-+ */
-+
-+/* #define    DEBUG */
-+/* #define    VERBOSE */
-+
-+#define KALMIA_HEADER_LENGTH 6
-+#define KALMIA_ALIGN_SIZE 4
-+#define KALMIA_USB_TIMEOUT 10000
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static int
-+kalmia_send_init_packet(struct usbnet *dev, u8 *init_msg, u8 init_msg_len,
-+      u8 *buffer, u8 expected_len)
-+{
-+      int act_len;
-+      int status;
-+
-+      netdev_dbg(dev->net, "Sending init packet");
-+
-+      status = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 0x02),
-+              init_msg, init_msg_len, &act_len, KALMIA_USB_TIMEOUT);
-+      if (status != 0) {
-+              netdev_err(dev->net,
-+                      "Error sending init packet. Status %i, length %i\n",
-+                      status, act_len);
-+              return status;
-+      }
-+      else if (act_len != init_msg_len) {
-+              netdev_err(dev->net,
-+                      "Did not send all of init packet. Bytes sent: %i",
-+                      act_len);
-+      }
-+      else {
-+              netdev_dbg(dev->net, "Successfully sent init packet.");
-+      }
-+
-+      status = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, 0x81),
-+              buffer, expected_len, &act_len, KALMIA_USB_TIMEOUT);
-+
-+      if (status != 0)
-+              netdev_err(dev->net,
-+                      "Error receiving init result. Status %i, length %i\n",
-+                      status, act_len);
-+      else if (act_len != expected_len)
-+              netdev_err(dev->net, "Unexpected init result length: %i\n",
-+                      act_len);
-+
-+      return status;
-+}
-+
-+static int
-+kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr)
-+{
-+      static const char init_msg_1[] =
-+              { 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
-+              0x00, 0x00 };
-+      static const char init_msg_2[] =
-+              { 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf4,
-+              0x00, 0x00 };
-+      static const int buflen = 28;
-+      char *usb_buf;
-+      int status;
-+
-+      usb_buf = kmalloc(buflen, GFP_DMA | GFP_KERNEL);
-+      if (!usb_buf)
-+              return -ENOMEM;
-+
-+      memcpy(usb_buf, init_msg_1, 12);
-+      status = kalmia_send_init_packet(dev, usb_buf, sizeof(init_msg_1)
-+              / sizeof(init_msg_1[0]), usb_buf, 24);
-+      if (status != 0)
-+              return status;
-+
-+      memcpy(usb_buf, init_msg_2, 12);
-+      status = kalmia_send_init_packet(dev, usb_buf, sizeof(init_msg_2)
-+              / sizeof(init_msg_2[0]), usb_buf, 28);
-+      if (status != 0)
-+              return status;
-+
-+      memcpy(ethernet_addr, usb_buf + 10, ETH_ALEN);
-+
-+      kfree(usb_buf);
-+      return status;
-+}
-+
-+static int
-+kalmia_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      int status;
-+      u8 ethernet_addr[ETH_ALEN];
-+
-+      /* Don't bind to AT command interface */
-+      if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
-+              return -EINVAL;
-+
-+      dev->in = usb_rcvbulkpipe(dev->udev, 0x81 & USB_ENDPOINT_NUMBER_MASK);
-+      dev->out = usb_sndbulkpipe(dev->udev, 0x02 & USB_ENDPOINT_NUMBER_MASK);
-+      dev->status = NULL;
-+
-+      dev->net->hard_header_len += KALMIA_HEADER_LENGTH;
-+      dev->hard_mtu = 1400;
-+      dev->rx_urb_size = dev->hard_mtu * 10; // Found as optimal after testing
-+
-+      status = kalmia_init_and_get_ethernet_addr(dev, ethernet_addr);
-+
-+      if (status < 0) {
-+              usb_set_intfdata(intf, NULL);
-+              usb_driver_release_interface(driver_of(intf), intf);
-+              return status;
-+      }
-+
-+      memcpy(dev->net->dev_addr, ethernet_addr, ETH_ALEN);
-+
-+      return status;
-+}
-+
-+static struct sk_buff *
-+kalmia_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
-+{
-+      struct sk_buff *skb2 = NULL;
-+      u16 content_len;
-+      unsigned char *header_start;
-+      unsigned char ether_type_1, ether_type_2;
-+      u8 remainder, padlen = 0;
-+
-+      if (!skb_cloned(skb)) {
-+              int headroom = skb_headroom(skb);
-+              int tailroom = skb_tailroom(skb);
-+
-+              if ((tailroom >= KALMIA_ALIGN_SIZE) && (headroom
-+                      >= KALMIA_HEADER_LENGTH))
-+                      goto done;
-+
-+              if ((headroom + tailroom) > (KALMIA_HEADER_LENGTH
-+                      + KALMIA_ALIGN_SIZE)) {
-+                      skb->data = memmove(skb->head + KALMIA_HEADER_LENGTH,
-+                              skb->data, skb->len);
-+                      skb_set_tail_pointer(skb, skb->len);
-+                      goto done;
-+              }
-+      }
-+
-+      skb2 = skb_copy_expand(skb, KALMIA_HEADER_LENGTH,
-+              KALMIA_ALIGN_SIZE, flags);
-+      if (!skb2)
-+              return NULL;
-+
-+      dev_kfree_skb_any(skb);
-+      skb = skb2;
-+
-+done:
-+      header_start = skb_push(skb, KALMIA_HEADER_LENGTH);
-+      ether_type_1 = header_start[KALMIA_HEADER_LENGTH + 12];
-+      ether_type_2 = header_start[KALMIA_HEADER_LENGTH + 13];
-+
-+      netdev_dbg(dev->net, "Sending etherType: %02x%02x", ether_type_1,
-+              ether_type_2);
-+
-+      /* According to empiric data for data packages */
-+      header_start[0] = 0x57;
-+      header_start[1] = 0x44;
-+      content_len = skb->len - KALMIA_HEADER_LENGTH;
-+
-+      put_unaligned_le16(content_len, &header_start[2]);
-+      header_start[4] = ether_type_1;
-+      header_start[5] = ether_type_2;
-+
-+      /* Align to 4 bytes by padding with zeros */
-+      remainder = skb->len % KALMIA_ALIGN_SIZE;
-+      if (remainder > 0) {
-+              padlen = KALMIA_ALIGN_SIZE - remainder;
-+              memset(skb_put(skb, padlen), 0, padlen);
-+      }
-+
-+      netdev_dbg(dev->net,
-+              "Sending package with length %i and padding %i. Header: %6phC.",
-+              content_len, padlen, header_start);
-+
-+      return skb;
-+}
-+
-+static int
-+kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      /*
-+       * Our task here is to strip off framing, leaving skb with one
-+       * data frame for the usbnet framework code to process.
-+       */
-+      static const u8 HEADER_END_OF_USB_PACKET[] =
-+              { 0x57, 0x5a, 0x00, 0x00, 0x08, 0x00 };
-+      static const u8 EXPECTED_UNKNOWN_HEADER_1[] =
-+              { 0x57, 0x43, 0x1e, 0x00, 0x15, 0x02 };
-+      static const u8 EXPECTED_UNKNOWN_HEADER_2[] =
-+              { 0x57, 0x50, 0x0e, 0x00, 0x00, 0x00 };
-+      int i = 0;
-+
-+      /* incomplete header? */
-+      if (skb->len < KALMIA_HEADER_LENGTH)
-+              return 0;
-+
-+      do {
-+              struct sk_buff *skb2 = NULL;
-+              u8 *header_start;
-+              u16 usb_packet_length, ether_packet_length;
-+              int is_last;
-+
-+              header_start = skb->data;
-+
-+              if (unlikely(header_start[0] != 0x57 || header_start[1] != 0x44)) {
-+                      if (!memcmp(header_start, EXPECTED_UNKNOWN_HEADER_1,
-+                              sizeof(EXPECTED_UNKNOWN_HEADER_1)) || !memcmp(
-+                              header_start, EXPECTED_UNKNOWN_HEADER_2,
-+                              sizeof(EXPECTED_UNKNOWN_HEADER_2))) {
-+                              netdev_dbg(dev->net,
-+                                      "Received expected unknown frame header: %6phC. Package length: %i\n",
-+                                      header_start,
-+                                      skb->len - KALMIA_HEADER_LENGTH);
-+                      }
-+                      else {
-+                              netdev_err(dev->net,
-+                                      "Received unknown frame header: %6phC. Package length: %i\n",
-+                                      header_start,
-+                                      skb->len - KALMIA_HEADER_LENGTH);
-+                              return 0;
-+                      }
-+              }
-+              else
-+                      netdev_dbg(dev->net,
-+                              "Received header: %6phC. Package length: %i\n",
-+                              header_start, skb->len - KALMIA_HEADER_LENGTH);
-+
-+              /* subtract start header and end header */
-+              usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH);
-+              ether_packet_length = get_unaligned_le16(&header_start[2]);
-+              skb_pull(skb, KALMIA_HEADER_LENGTH);
-+
-+              /* Some small packets misses end marker */
-+              if (usb_packet_length < ether_packet_length) {
-+                      ether_packet_length = usb_packet_length
-+                              + KALMIA_HEADER_LENGTH;
-+                      is_last = true;
-+              }
-+              else {
-+                      netdev_dbg(dev->net, "Correct package length #%i", i
-+                              + 1);
-+
-+                      is_last = (memcmp(skb->data + ether_packet_length,
-+                              HEADER_END_OF_USB_PACKET,
-+                              sizeof(HEADER_END_OF_USB_PACKET)) == 0);
-+                      if (!is_last) {
-+                              header_start = skb->data + ether_packet_length;
-+                              netdev_dbg(dev->net,
-+                                      "End header: %6phC. Package length: %i\n",
-+                                      header_start,
-+                                      skb->len - KALMIA_HEADER_LENGTH);
-+                      }
-+              }
-+
-+              if (is_last) {
-+                      skb2 = skb;
-+              }
-+              else {
-+                      skb2 = skb_clone(skb, GFP_ATOMIC);
-+                      if (unlikely(!skb2))
-+                              return 0;
-+              }
-+
-+              skb_trim(skb2, ether_packet_length);
-+
-+              if (is_last) {
-+                      return 1;
-+              }
-+              else {
-+                      usbnet_skb_return(dev, skb2);
-+                      skb_pull(skb, ether_packet_length);
-+              }
-+
-+              i++;
-+      }
-+      while (skb->len);
-+
-+      return 1;
-+}
-+
-+static const struct driver_info kalmia_info = {
-+      .description = "Samsung Kalmia LTE USB dongle",
-+      .flags = FLAG_WWAN,
-+      .bind = kalmia_bind,
-+      .rx_fixup = kalmia_rx_fixup,
-+      .tx_fixup = kalmia_tx_fixup
-+};
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static const struct usb_device_id products[] = {
-+      /* The unswitched USB ID, to get the module auto loaded: */
-+      { USB_DEVICE(0x04e8, 0x689a) },
-+      /* The stick swithed into modem (by e.g. usb_modeswitch): */
-+      { USB_DEVICE(0x04e8, 0x6889),
-+              .driver_info = (unsigned long) &kalmia_info, },
-+      { /* EMPTY == end of list */} };
-+MODULE_DEVICE_TABLE( usb, products);
-+
-+static struct usb_driver kalmia_driver = {
-+      .name = "kalmia",
-+      .id_table = products,
-+      .probe = usbnet_probe,
-+      .disconnect = usbnet_disconnect,
-+      .suspend = usbnet_suspend,
-+      .resume = usbnet_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(kalmia_driver);
-+
-+MODULE_AUTHOR("Marius Bjoernstad Kotsbak <marius@kotsbak.com>");
-+MODULE_DESCRIPTION("Samsung Kalmia USB network driver");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/kaweth.c backports-4.2.6-1/drivers/net/usb/kaweth.c
---- backports-4.2.6-1.org/drivers/net/usb/kaweth.c     1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/kaweth.c 2016-06-28 14:35:17.988640553 +0200
-@@ -0,0 +1,1331 @@
-+/****************************************************************
-+ *
-+ *     kaweth.c - driver for KL5KUSB101 based USB->Ethernet
-+ *
-+ *     (c) 2000 Interlan Communications
-+ *     (c) 2000 Stephane Alnet
-+ *     (C) 2001 Brad Hards
-+ *     (C) 2002 Oliver Neukum
-+ *
-+ *     Original author: The Zapman <zapman@interlan.net>
-+ *     Inspired by, and much credit goes to Michael Rothwell
-+ *     <rothwell@interlan.net> for the test equipment, help, and patience
-+ *     Based off of (and with thanks to) Petko Manolov's pegaus.c driver.
-+ *     Also many thanks to Joel Silverman and Ed Surprenant at Kawasaki
-+ *     for providing the firmware and driver resources.
-+ *
-+ *     This program is free software; you can redistribute it and/or
-+ *     modify it under the terms of the GNU General Public License as
-+ *     published by the Free Software Foundation; either version 2, or
-+ *     (at your option) any later version.
-+ *
-+ *     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, see <http://www.gnu.org/licenses/>.
-+ *
-+ ****************************************************************/
-+
-+/* TODO:
-+ * Develop test procedures for USB net interfaces
-+ * Run test procedures
-+ * Fix bugs from previous two steps
-+ * Snoop other OSs for any tricks we're not doing
-+ * Reduce arbitrary timeouts
-+ * Smart multicast support
-+ * Temporary MAC change support
-+ * Tunable SOFs parameter - ioctl()?
-+ * Ethernet stats collection
-+ * Code formatting improvements
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/string.h>
-+#include <linux/delay.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/usb.h>
-+#include <linux/types.h>
-+#include <linux/ethtool.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/wait.h>
-+#include <linux/firmware.h>
-+#include <asm/uaccess.h>
-+#include <asm/byteorder.h>
-+
-+#undef DEBUG
-+
-+#define KAWETH_MTU                    1514
-+#define KAWETH_BUF_SIZE                       1664
-+#define KAWETH_TX_TIMEOUT             (5 * HZ)
-+#define KAWETH_SCRATCH_SIZE           32
-+#define KAWETH_FIRMWARE_BUF_SIZE      4096
-+#define KAWETH_CONTROL_TIMEOUT                (30000)
-+
-+#define KAWETH_STATUS_BROKEN          0x0000001
-+#define KAWETH_STATUS_CLOSING         0x0000002
-+#define KAWETH_STATUS_SUSPENDING      0x0000004
-+
-+#define KAWETH_STATUS_BLOCKED (KAWETH_STATUS_CLOSING | KAWETH_STATUS_SUSPENDING)
-+
-+#define KAWETH_PACKET_FILTER_PROMISCUOUS      0x01
-+#define KAWETH_PACKET_FILTER_ALL_MULTICAST    0x02
-+#define KAWETH_PACKET_FILTER_DIRECTED         0x04
-+#define KAWETH_PACKET_FILTER_BROADCAST                0x08
-+#define KAWETH_PACKET_FILTER_MULTICAST                0x10
-+
-+/* Table 7 */
-+#define KAWETH_COMMAND_GET_ETHERNET_DESC      0x00
-+#define KAWETH_COMMAND_MULTICAST_FILTERS        0x01
-+#define KAWETH_COMMAND_SET_PACKET_FILTER      0x02
-+#define KAWETH_COMMAND_STATISTICS               0x03
-+#define KAWETH_COMMAND_SET_TEMP_MAC           0x06
-+#define KAWETH_COMMAND_GET_TEMP_MAC             0x07
-+#define KAWETH_COMMAND_SET_URB_SIZE           0x08
-+#define KAWETH_COMMAND_SET_SOFS_WAIT          0x09
-+#define KAWETH_COMMAND_SCAN                   0xFF
-+
-+#define KAWETH_SOFS_TO_WAIT                   0x05
-+
-+#define INTBUFFERSIZE                         4
-+
-+#define STATE_OFFSET                          0
-+#define STATE_MASK                            0x40
-+#define       STATE_SHIFT                             5
-+
-+#define IS_BLOCKED(s) (s & KAWETH_STATUS_BLOCKED)
-+
-+
-+MODULE_AUTHOR("Michael Zappe <zapman@interlan.net>, Stephane Alnet <stephane@u-picardie.fr>, Brad Hards <bhards@bigpond.net.au> and Oliver Neukum <oliver@neukum.org>");
-+MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver");
-+MODULE_LICENSE("GPL");
-+MODULE_FIRMWARE("kaweth/new_code.bin");
-+MODULE_FIRMWARE("kaweth/new_code_fix.bin");
-+MODULE_FIRMWARE("kaweth/trigger_code.bin");
-+MODULE_FIRMWARE("kaweth/trigger_code_fix.bin");
-+
-+static const char driver_name[] = "kaweth";
-+
-+static int kaweth_probe(
-+              struct usb_interface *intf,
-+              const struct usb_device_id *id  /* from id_table */
-+      );
-+static void kaweth_disconnect(struct usb_interface *intf);
-+static int kaweth_internal_control_msg(struct usb_device *usb_dev,
-+                                     unsigned int pipe,
-+                                     struct usb_ctrlrequest *cmd, void *data,
-+                                     int len, int timeout);
-+static int kaweth_suspend(struct usb_interface *intf, pm_message_t message);
-+static int kaweth_resume(struct usb_interface *intf);
-+
-+/****************************************************************
-+ *     usb_device_id
-+ ****************************************************************/
-+static struct usb_device_id usb_klsi_table[] = {
-+      { USB_DEVICE(0x03e8, 0x0008) }, /* AOX Endpoints USB Ethernet */
-+      { USB_DEVICE(0x04bb, 0x0901) }, /* I-O DATA USB-ET/T */
-+      { USB_DEVICE(0x0506, 0x03e8) }, /* 3Com 3C19250 */
-+      { USB_DEVICE(0x0506, 0x11f8) }, /* 3Com 3C460 */
-+      { USB_DEVICE(0x0557, 0x2002) }, /* ATEN USB Ethernet */
-+      { USB_DEVICE(0x0557, 0x4000) }, /* D-Link DSB-650C */
-+      { USB_DEVICE(0x0565, 0x0002) }, /* Peracom Enet */
-+      { USB_DEVICE(0x0565, 0x0003) }, /* Optus@Home UEP1045A */
-+      { USB_DEVICE(0x0565, 0x0005) }, /* Peracom Enet2 */
-+      { USB_DEVICE(0x05e9, 0x0008) }, /* KLSI KL5KUSB101B */
-+      { USB_DEVICE(0x05e9, 0x0009) }, /* KLSI KL5KUSB101B (Board change) */
-+      { USB_DEVICE(0x066b, 0x2202) }, /* Linksys USB10T */
-+      { USB_DEVICE(0x06e1, 0x0008) }, /* ADS USB-10BT */
-+      { USB_DEVICE(0x06e1, 0x0009) }, /* ADS USB-10BT */
-+      { USB_DEVICE(0x0707, 0x0100) }, /* SMC 2202USB */
-+      { USB_DEVICE(0x07aa, 0x0001) }, /* Correga K.K. */
-+      { USB_DEVICE(0x07b8, 0x4000) }, /* D-Link DU-E10 */
-+      { USB_DEVICE(0x07c9, 0xb010) }, /* Allied Telesyn AT-USB10 USB Ethernet Adapter */
-+      { USB_DEVICE(0x0846, 0x1001) }, /* NetGear EA-101 */
-+      { USB_DEVICE(0x0846, 0x1002) }, /* NetGear EA-101 */
-+      { USB_DEVICE(0x085a, 0x0008) }, /* PortGear Ethernet Adapter */
-+      { USB_DEVICE(0x085a, 0x0009) }, /* PortGear Ethernet Adapter */
-+      { USB_DEVICE(0x087d, 0x5704) }, /* Jaton USB Ethernet Device Adapter */
-+      { USB_DEVICE(0x0951, 0x0008) }, /* Kingston Technology USB Ethernet Adapter */
-+      { USB_DEVICE(0x095a, 0x3003) }, /* Portsmith Express Ethernet Adapter */
-+      { USB_DEVICE(0x10bd, 0x1427) }, /* ASANTE USB To Ethernet Adapter */
-+      { USB_DEVICE(0x1342, 0x0204) }, /* Mobility USB-Ethernet Adapter */
-+      { USB_DEVICE(0x13d2, 0x0400) }, /* Shark Pocket Adapter */
-+      { USB_DEVICE(0x1485, 0x0001) }, /* Silicom U2E */
-+      { USB_DEVICE(0x1485, 0x0002) }, /* Psion Dacom Gold Port Ethernet */
-+      { USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */
-+      { USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */
-+      { USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */
-+      { USB_DEVICE(0x1668, 0x0323) }, /* Actiontec USB Ethernet */
-+      { USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */
-+      {} /* Null terminator */
-+};
-+
-+MODULE_DEVICE_TABLE (usb, usb_klsi_table);
-+
-+/****************************************************************
-+ *     kaweth_driver
-+ ****************************************************************/
-+static struct usb_driver kaweth_driver = {
-+      .name =         driver_name,
-+      .probe =        kaweth_probe,
-+      .disconnect =   kaweth_disconnect,
-+      .suspend =      kaweth_suspend,
-+      .resume =       kaweth_resume,
-+      .id_table =     usb_klsi_table,
-+      .supports_autosuspend = 1,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+typedef __u8 eth_addr_t[6];
-+
-+/****************************************************************
-+ *     usb_eth_dev
-+ ****************************************************************/
-+struct usb_eth_dev {
-+      char *name;
-+      __u16 vendor;
-+      __u16 device;
-+      void *pdata;
-+};
-+
-+/****************************************************************
-+ *     kaweth_ethernet_configuration
-+ *     Refer Table 8
-+ ****************************************************************/
-+struct kaweth_ethernet_configuration
-+{
-+      __u8 size;
-+      __u8 reserved1;
-+      __u8 reserved2;
-+      eth_addr_t hw_addr;
-+      __u32 statistics_mask;
-+      __le16 segment_size;
-+      __u16 max_multicast_filters;
-+      __u8 reserved3;
-+} __packed;
-+
-+/****************************************************************
-+ *     kaweth_device
-+ ****************************************************************/
-+struct kaweth_device
-+{
-+      spinlock_t device_lock;
-+
-+      __u32 status;
-+      int end;
-+      int suspend_lowmem_rx;
-+      int suspend_lowmem_ctrl;
-+      int linkstate;
-+      int opened;
-+      struct delayed_work lowmem_work;
-+
-+      struct usb_device *dev;
-+      struct usb_interface *intf;
-+      struct net_device *net;
-+      wait_queue_head_t term_wait;
-+
-+      struct urb *rx_urb;
-+      struct urb *tx_urb;
-+      struct urb *irq_urb;
-+
-+      dma_addr_t intbufferhandle;
-+      __u8 *intbuffer;
-+      dma_addr_t rxbufferhandle;
-+      __u8 *rx_buf;
-+
-+      
-+      struct sk_buff *tx_skb;
-+
-+      __u8 *firmware_buf;
-+      __u8 scratch[KAWETH_SCRATCH_SIZE];
-+      __u16 packet_filter_bitmap;
-+
-+      struct kaweth_ethernet_configuration configuration;
-+
-+      struct net_device_stats stats;
-+};
-+
-+/****************************************************************
-+ *     kaweth_control
-+ ****************************************************************/
-+static int kaweth_control(struct kaweth_device *kaweth,
-+                        unsigned int pipe,
-+                        __u8 request,
-+                        __u8 requesttype,
-+                        __u16 value,
-+                        __u16 index,
-+                        void *data,
-+                        __u16 size,
-+                        int timeout)
-+{
-+      struct usb_ctrlrequest *dr;
-+      int retval;
-+
-+      netdev_dbg(kaweth->net, "kaweth_control()\n");
-+
-+      if(in_interrupt()) {
-+              netdev_dbg(kaweth->net, "in_interrupt()\n");
-+              return -EBUSY;
-+      }
-+
-+      dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
-+      if (!dr)
-+              return -ENOMEM;
-+
-+      dr->bRequestType = requesttype;
-+      dr->bRequest = request;
-+      dr->wValue = cpu_to_le16(value);
-+      dr->wIndex = cpu_to_le16(index);
-+      dr->wLength = cpu_to_le16(size);
-+
-+      retval = kaweth_internal_control_msg(kaweth->dev,
-+                                           pipe,
-+                                           dr,
-+                                           data,
-+                                           size,
-+                                           timeout);
-+
-+      kfree(dr);
-+      return retval;
-+}
-+
-+/****************************************************************
-+ *     kaweth_read_configuration
-+ ****************************************************************/
-+static int kaweth_read_configuration(struct kaweth_device *kaweth)
-+{
-+      int retval;
-+
-+      netdev_dbg(kaweth->net, "Reading kaweth configuration\n");
-+
-+      retval = kaweth_control(kaweth,
-+                              usb_rcvctrlpipe(kaweth->dev, 0),
-+                              KAWETH_COMMAND_GET_ETHERNET_DESC,
-+                              USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
-+                              0,
-+                              0,
-+                              (void *)&kaweth->configuration,
-+                              sizeof(kaweth->configuration),
-+                              KAWETH_CONTROL_TIMEOUT);
-+
-+      return retval;
-+}
-+
-+/****************************************************************
-+ *     kaweth_set_urb_size
-+ ****************************************************************/
-+static int kaweth_set_urb_size(struct kaweth_device *kaweth, __u16 urb_size)
-+{
-+      int retval;
-+
-+      netdev_dbg(kaweth->net, "Setting URB size to %d\n", (unsigned)urb_size);
-+
-+      retval = kaweth_control(kaweth,
-+                              usb_sndctrlpipe(kaweth->dev, 0),
-+                              KAWETH_COMMAND_SET_URB_SIZE,
-+                              USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-+                              urb_size,
-+                              0,
-+                              (void *)&kaweth->scratch,
-+                              0,
-+                              KAWETH_CONTROL_TIMEOUT);
-+
-+      return retval;
-+}
-+
-+/****************************************************************
-+ *     kaweth_set_sofs_wait
-+ ****************************************************************/
-+static int kaweth_set_sofs_wait(struct kaweth_device *kaweth, __u16 sofs_wait)
-+{
-+      int retval;
-+
-+      netdev_dbg(kaweth->net, "Set SOFS wait to %d\n", (unsigned)sofs_wait);
-+
-+      retval = kaweth_control(kaweth,
-+                              usb_sndctrlpipe(kaweth->dev, 0),
-+                              KAWETH_COMMAND_SET_SOFS_WAIT,
-+                              USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-+                              sofs_wait,
-+                              0,
-+                              (void *)&kaweth->scratch,
-+                              0,
-+                              KAWETH_CONTROL_TIMEOUT);
-+
-+      return retval;
-+}
-+
-+/****************************************************************
-+ *     kaweth_set_receive_filter
-+ ****************************************************************/
-+static int kaweth_set_receive_filter(struct kaweth_device *kaweth,
-+                                   __u16 receive_filter)
-+{
-+      int retval;
-+
-+      netdev_dbg(kaweth->net, "Set receive filter to %d\n",
-+                 (unsigned)receive_filter);
-+
-+      retval = kaweth_control(kaweth,
-+                              usb_sndctrlpipe(kaweth->dev, 0),
-+                              KAWETH_COMMAND_SET_PACKET_FILTER,
-+                              USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-+                              receive_filter,
-+                              0,
-+                              (void *)&kaweth->scratch,
-+                              0,
-+                              KAWETH_CONTROL_TIMEOUT);
-+
-+      return retval;
-+}
-+
-+/****************************************************************
-+ *     kaweth_download_firmware
-+ ****************************************************************/
-+static int kaweth_download_firmware(struct kaweth_device *kaweth,
-+                                  const char *fwname,
-+                                  __u8 interrupt,
-+                                  __u8 type)
-+{
-+      const struct firmware *fw;
-+      int data_len;
-+      int ret;
-+
-+      ret = request_firmware(&fw, fwname, &kaweth->dev->dev);
-+      if (ret) {
-+              dev_err(&kaweth->intf->dev, "Firmware request failed\n");
-+              return ret;
-+      }
-+
-+      if (fw->size > KAWETH_FIRMWARE_BUF_SIZE) {
-+              dev_err(&kaweth->intf->dev, "Firmware too big: %zu\n",
-+                      fw->size);
-+              release_firmware(fw);
-+              return -ENOSPC;
-+      }
-+      data_len = fw->size;
-+      memcpy(kaweth->firmware_buf, fw->data, fw->size);
-+
-+      release_firmware(fw);
-+
-+      kaweth->firmware_buf[2] = (data_len & 0xFF) - 7;
-+      kaweth->firmware_buf[3] = data_len >> 8;
-+      kaweth->firmware_buf[4] = type;
-+      kaweth->firmware_buf[5] = interrupt;
-+
-+      netdev_dbg(kaweth->net, "High: %i, Low:%i\n", kaweth->firmware_buf[3],
-+                 kaweth->firmware_buf[2]);
-+
-+      netdev_dbg(kaweth->net,
-+                 "Downloading firmware at %p to kaweth device at %p\n",
-+                 kaweth->firmware_buf, kaweth);
-+      netdev_dbg(kaweth->net, "Firmware length: %d\n", data_len);
-+
-+      return kaweth_control(kaweth,
-+                            usb_sndctrlpipe(kaweth->dev, 0),
-+                            KAWETH_COMMAND_SCAN,
-+                            USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-+                            0,
-+                            0,
-+                            (void *)kaweth->firmware_buf,
-+                            data_len,
-+                            KAWETH_CONTROL_TIMEOUT);
-+}
-+
-+/****************************************************************
-+ *     kaweth_trigger_firmware
-+ ****************************************************************/
-+static int kaweth_trigger_firmware(struct kaweth_device *kaweth,
-+                                 __u8 interrupt)
-+{
-+      kaweth->firmware_buf[0] = 0xB6;
-+      kaweth->firmware_buf[1] = 0xC3;
-+      kaweth->firmware_buf[2] = 0x01;
-+      kaweth->firmware_buf[3] = 0x00;
-+      kaweth->firmware_buf[4] = 0x06;
-+      kaweth->firmware_buf[5] = interrupt;
-+      kaweth->firmware_buf[6] = 0x00;
-+      kaweth->firmware_buf[7] = 0x00;
-+
-+      netdev_dbg(kaweth->net, "Triggering firmware\n");
-+
-+      return kaweth_control(kaweth,
-+                            usb_sndctrlpipe(kaweth->dev, 0),
-+                            KAWETH_COMMAND_SCAN,
-+                            USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-+                            0,
-+                            0,
-+                            (void *)kaweth->firmware_buf,
-+                            8,
-+                            KAWETH_CONTROL_TIMEOUT);
-+}
-+
-+/****************************************************************
-+ *     kaweth_reset
-+ ****************************************************************/
-+static int kaweth_reset(struct kaweth_device *kaweth)
-+{
-+      int result;
-+
-+      netdev_dbg(kaweth->net, "kaweth_reset(%p)\n", kaweth);
-+      result = usb_reset_configuration(kaweth->dev);
-+      mdelay(10);
-+
-+      netdev_dbg(kaweth->net, "kaweth_reset() returns %d.\n", result);
-+
-+      return result;
-+}
-+
-+static void kaweth_usb_receive(struct urb *);
-+static int kaweth_resubmit_rx_urb(struct kaweth_device *, gfp_t);
-+
-+/****************************************************************
-+      int_callback
-+*****************************************************************/
-+
-+static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, gfp_t mf)
-+{
-+      int status;
-+
-+      status = usb_submit_urb (kaweth->irq_urb, mf);
-+      if (unlikely(status == -ENOMEM)) {
-+              kaweth->suspend_lowmem_ctrl = 1;
-+              schedule_delayed_work(&kaweth->lowmem_work, HZ/4);
-+      } else {
-+              kaweth->suspend_lowmem_ctrl = 0;
-+      }
-+
-+      if (status)
-+              dev_err(&kaweth->intf->dev,
-+                      "can't resubmit intr, %s-%s, status %d\n",
-+                      kaweth->dev->bus->bus_name,
-+                      kaweth->dev->devpath, status);
-+}
-+
-+static void int_callback(struct urb *u)
-+{
-+      struct kaweth_device *kaweth = u->context;
-+      int act_state;
-+      int status = u->status;
-+
-+      switch (status) {
-+      case 0:                 /* success */
-+              break;
-+      case -ECONNRESET:       /* unlink */
-+      case -ENOENT:
-+      case -ESHUTDOWN:
-+              return;
-+      /* -EPIPE:  should clear the halt */
-+      default:                /* error */
-+              goto resubmit;
-+      }
-+
-+      /* we check the link state to report changes */
-+      if (kaweth->linkstate != (act_state = ( kaweth->intbuffer[STATE_OFFSET] | STATE_MASK) >> STATE_SHIFT)) {
-+              if (act_state)
-+                      netif_carrier_on(kaweth->net);
-+              else
-+                      netif_carrier_off(kaweth->net);
-+
-+              kaweth->linkstate = act_state;
-+      }
-+resubmit:
-+      kaweth_resubmit_int_urb(kaweth, GFP_ATOMIC);
-+}
-+
-+static void kaweth_resubmit_tl(struct work_struct *work)
-+{
-+      struct kaweth_device *kaweth =
-+              container_of(work, struct kaweth_device, lowmem_work.work);
-+
-+      if (IS_BLOCKED(kaweth->status))
-+              return;
-+
-+      if (kaweth->suspend_lowmem_rx)
-+              kaweth_resubmit_rx_urb(kaweth, GFP_NOIO);
-+
-+      if (kaweth->suspend_lowmem_ctrl)
-+              kaweth_resubmit_int_urb(kaweth, GFP_NOIO);
-+}
-+
-+
-+/****************************************************************
-+ *     kaweth_resubmit_rx_urb
-+ ****************************************************************/
-+static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth,
-+                                              gfp_t mem_flags)
-+{
-+      int result;
-+
-+      usb_fill_bulk_urb(kaweth->rx_urb,
-+                    kaweth->dev,
-+                    usb_rcvbulkpipe(kaweth->dev, 1),
-+                    kaweth->rx_buf,
-+                    KAWETH_BUF_SIZE,
-+                    kaweth_usb_receive,
-+                    kaweth);
-+      kaweth->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-+      kaweth->rx_urb->transfer_dma = kaweth->rxbufferhandle;
-+
-+      if((result = usb_submit_urb(kaweth->rx_urb, mem_flags))) {
-+              if (result == -ENOMEM) {
-+                      kaweth->suspend_lowmem_rx = 1;
-+                      schedule_delayed_work(&kaweth->lowmem_work, HZ/4);
-+              }
-+              dev_err(&kaweth->intf->dev, "resubmitting rx_urb %d failed\n",
-+                      result);
-+      } else {
-+              kaweth->suspend_lowmem_rx = 0;
-+      }
-+
-+      return result;
-+}
-+
-+static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth);
-+
-+/****************************************************************
-+ *     kaweth_usb_receive
-+ ****************************************************************/
-+static void kaweth_usb_receive(struct urb *urb)
-+{
-+      struct device *dev = &urb->dev->dev;
-+      struct kaweth_device *kaweth = urb->context;
-+      struct net_device *net = kaweth->net;
-+      int status = urb->status;
-+
-+      int count = urb->actual_length;
-+      int count2 = urb->transfer_buffer_length;
-+
-+      __u16 pkt_len = le16_to_cpup((__le16 *)kaweth->rx_buf);
-+
-+      struct sk_buff *skb;
-+
-+      if (unlikely(status == -EPIPE)) {
-+              kaweth->stats.rx_errors++;
-+              kaweth->end = 1;
-+              wake_up(&kaweth->term_wait);
-+              dev_dbg(dev, "Status was -EPIPE.\n");
-+              return;
-+      }
-+      if (unlikely(status == -ECONNRESET || status == -ESHUTDOWN)) {
-+              /* we are killed - set a flag and wake the disconnect handler */
-+              kaweth->end = 1;
-+              wake_up(&kaweth->term_wait);
-+              dev_dbg(dev, "Status was -ECONNRESET or -ESHUTDOWN.\n");
-+              return;
-+      }
-+      if (unlikely(status == -EPROTO || status == -ETIME ||
-+                   status == -EILSEQ)) {
-+              kaweth->stats.rx_errors++;
-+              dev_dbg(dev, "Status was -EPROTO, -ETIME, or -EILSEQ.\n");
-+              return;
-+      }
-+      if (unlikely(status == -EOVERFLOW)) {
-+              kaweth->stats.rx_errors++;
-+              dev_dbg(dev, "Status was -EOVERFLOW.\n");
-+      }
-+      spin_lock(&kaweth->device_lock);
-+      if (IS_BLOCKED(kaweth->status)) {
-+              spin_unlock(&kaweth->device_lock);
-+              return;
-+      }
-+      spin_unlock(&kaweth->device_lock);
-+
-+      if(status && status != -EREMOTEIO && count != 1) {
-+              dev_err(&kaweth->intf->dev,
-+                      "%s RX status: %d count: %d packet_len: %d\n",
-+                      net->name, status, count, (int)pkt_len);
-+              kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
-+                return;
-+      }
-+
-+      if(kaweth->net && (count > 2)) {
-+              if(pkt_len > (count - 2)) {
-+                      dev_err(&kaweth->intf->dev,
-+                              "Packet length too long for USB frame (pkt_len: %x, count: %x)\n",
-+                              pkt_len, count);
-+                      dev_err(&kaweth->intf->dev, "Packet len & 2047: %x\n",
-+                              pkt_len & 2047);
-+                      dev_err(&kaweth->intf->dev, "Count 2: %x\n", count2);
-+                      kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
-+                        return;
-+                }
-+
-+              if(!(skb = dev_alloc_skb(pkt_len+2))) {
-+                      kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
-+                        return;
-+              }
-+
-+              skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
-+
-+              skb_copy_to_linear_data(skb, kaweth->rx_buf + 2, pkt_len);
-+
-+              skb_put(skb, pkt_len);
-+
-+              skb->protocol = eth_type_trans(skb, net);
-+
-+              netif_rx(skb);
-+
-+              kaweth->stats.rx_packets++;
-+              kaweth->stats.rx_bytes += pkt_len;
-+      }
-+
-+      kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
-+}
-+
-+/****************************************************************
-+ *     kaweth_open
-+ ****************************************************************/
-+static int kaweth_open(struct net_device *net)
-+{
-+      struct kaweth_device *kaweth = netdev_priv(net);
-+      int res;
-+
-+      netdev_dbg(kaweth->net, "Opening network device.\n");
-+
-+      res = usb_autopm_get_interface(kaweth->intf);
-+      if (res) {
-+              dev_err(&kaweth->intf->dev, "Interface cannot be resumed.\n");
-+              return -EIO;
-+      }
-+      res = kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL);
-+      if (res)
-+              goto err_out;
-+
-+      usb_fill_int_urb(
-+              kaweth->irq_urb,
-+              kaweth->dev,
-+              usb_rcvintpipe(kaweth->dev, 3),
-+              kaweth->intbuffer,
-+              INTBUFFERSIZE,
-+              int_callback,
-+              kaweth,
-+              250); /* overriding the descriptor */
-+      kaweth->irq_urb->transfer_dma = kaweth->intbufferhandle;
-+      kaweth->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-+
-+      res = usb_submit_urb(kaweth->irq_urb, GFP_KERNEL);
-+      if (res) {
-+              usb_kill_urb(kaweth->rx_urb);
-+              goto err_out;
-+      }
-+      kaweth->opened = 1;
-+
-+      netif_start_queue(net);
-+
-+      kaweth_async_set_rx_mode(kaweth);
-+      return 0;
-+
-+err_out:
-+      usb_autopm_put_interface(kaweth->intf);
-+      return -EIO;
-+}
-+
-+/****************************************************************
-+ *     kaweth_kill_urbs
-+ ****************************************************************/
-+static void kaweth_kill_urbs(struct kaweth_device *kaweth)
-+{
-+      usb_kill_urb(kaweth->irq_urb);
-+      usb_kill_urb(kaweth->rx_urb);
-+      usb_kill_urb(kaweth->tx_urb);
-+
-+      cancel_delayed_work_sync(&kaweth->lowmem_work);
-+
-+      /* a scheduled work may have resubmitted,
-+         we hit them again */
-+      usb_kill_urb(kaweth->irq_urb);
-+      usb_kill_urb(kaweth->rx_urb);
-+}
-+
-+/****************************************************************
-+ *     kaweth_close
-+ ****************************************************************/
-+static int kaweth_close(struct net_device *net)
-+{
-+      struct kaweth_device *kaweth = netdev_priv(net);
-+
-+      netif_stop_queue(net);
-+      kaweth->opened = 0;
-+
-+      kaweth->status |= KAWETH_STATUS_CLOSING;
-+
-+      kaweth_kill_urbs(kaweth);
-+
-+      kaweth->status &= ~KAWETH_STATUS_CLOSING;
-+
-+      usb_autopm_put_interface(kaweth->intf);
-+
-+      return 0;
-+}
-+
-+static u32 kaweth_get_link(struct net_device *dev)
-+{
-+      struct kaweth_device *kaweth = netdev_priv(dev);
-+
-+      return kaweth->linkstate;
-+}
-+
-+static const struct ethtool_ops ops = {
-+      .get_link       = kaweth_get_link
-+};
-+
-+/****************************************************************
-+ *     kaweth_usb_transmit_complete
-+ ****************************************************************/
-+static void kaweth_usb_transmit_complete(struct urb *urb)
-+{
-+      struct kaweth_device *kaweth = urb->context;
-+      struct sk_buff *skb = kaweth->tx_skb;
-+      int status = urb->status;
-+
-+      if (unlikely(status != 0))
-+              if (status != -ENOENT)
-+                      dev_dbg(&urb->dev->dev, "%s: TX status %d.\n",
-+                              kaweth->net->name, status);
-+
-+      netif_wake_queue(kaweth->net);
-+      dev_kfree_skb_irq(skb);
-+}
-+
-+/****************************************************************
-+ *     kaweth_start_xmit
-+ ****************************************************************/
-+static netdev_tx_t kaweth_start_xmit(struct sk_buff *skb,
-+                                         struct net_device *net)
-+{
-+      struct kaweth_device *kaweth = netdev_priv(net);
-+      __le16 *private_header;
-+
-+      int res;
-+
-+      spin_lock_irq(&kaweth->device_lock);
-+
-+      kaweth_async_set_rx_mode(kaweth);
-+      netif_stop_queue(net);
-+      if (IS_BLOCKED(kaweth->status)) {
-+              goto skip;
-+      }
-+
-+      /* We now decide whether we can put our special header into the sk_buff */
-+      if (skb_cloned(skb) || skb_headroom(skb) < 2) {
-+              /* no such luck - we make our own */
-+              struct sk_buff *copied_skb;
-+              copied_skb = skb_copy_expand(skb, 2, 0, GFP_ATOMIC);
-+              dev_kfree_skb_irq(skb);
-+              skb = copied_skb;
-+              if (!copied_skb) {
-+                      kaweth->stats.tx_errors++;
-+                      netif_start_queue(net);
-+                      spin_unlock_irq(&kaweth->device_lock);
-+                      return NETDEV_TX_OK;
-+              }
-+      }
-+
-+      private_header = (__le16 *)__skb_push(skb, 2);
-+      *private_header = cpu_to_le16(skb->len-2);
-+      kaweth->tx_skb = skb;
-+
-+      usb_fill_bulk_urb(kaweth->tx_urb,
-+                    kaweth->dev,
-+                    usb_sndbulkpipe(kaweth->dev, 2),
-+                    private_header,
-+                    skb->len,
-+                    kaweth_usb_transmit_complete,
-+                    kaweth);
-+      kaweth->end = 0;
-+
-+      if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC)))
-+      {
-+              dev_warn(&net->dev, "kaweth failed tx_urb %d\n", res);
-+skip:
-+              kaweth->stats.tx_errors++;
-+
-+              netif_start_queue(net);
-+              dev_kfree_skb_irq(skb);
-+      }
-+      else
-+      {
-+              kaweth->stats.tx_packets++;
-+              kaweth->stats.tx_bytes += skb->len;
-+      }
-+
-+      spin_unlock_irq(&kaweth->device_lock);
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+/****************************************************************
-+ *     kaweth_set_rx_mode
-+ ****************************************************************/
-+static void kaweth_set_rx_mode(struct net_device *net)
-+{
-+      struct kaweth_device *kaweth = netdev_priv(net);
-+
-+      __u16 packet_filter_bitmap = KAWETH_PACKET_FILTER_DIRECTED |
-+                                     KAWETH_PACKET_FILTER_BROADCAST |
-+                                   KAWETH_PACKET_FILTER_MULTICAST;
-+
-+      netdev_dbg(net, "Setting Rx mode to %d\n", packet_filter_bitmap);
-+
-+      netif_stop_queue(net);
-+
-+      if (net->flags & IFF_PROMISC) {
-+              packet_filter_bitmap |= KAWETH_PACKET_FILTER_PROMISCUOUS;
-+      }
-+      else if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI)) {
-+              packet_filter_bitmap |= KAWETH_PACKET_FILTER_ALL_MULTICAST;
-+      }
-+
-+      kaweth->packet_filter_bitmap = packet_filter_bitmap;
-+      netif_wake_queue(net);
-+}
-+
-+/****************************************************************
-+ *     kaweth_async_set_rx_mode
-+ ****************************************************************/
-+static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth)
-+{
-+      int result;
-+      __u16 packet_filter_bitmap = kaweth->packet_filter_bitmap;
-+
-+      kaweth->packet_filter_bitmap = 0;
-+      if (packet_filter_bitmap == 0)
-+              return;
-+
-+      if (in_interrupt())
-+              return;
-+
-+      result = kaweth_control(kaweth,
-+                              usb_sndctrlpipe(kaweth->dev, 0),
-+                              KAWETH_COMMAND_SET_PACKET_FILTER,
-+                              USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-+                              packet_filter_bitmap,
-+                              0,
-+                              (void *)&kaweth->scratch,
-+                              0,
-+                              KAWETH_CONTROL_TIMEOUT);
-+
-+      if(result < 0) {
-+              dev_err(&kaweth->intf->dev, "Failed to set Rx mode: %d\n",
-+                      result);
-+      }
-+      else {
-+              netdev_dbg(kaweth->net, "Set Rx mode to %d\n",
-+                         packet_filter_bitmap);
-+      }
-+}
-+
-+/****************************************************************
-+ *     kaweth_netdev_stats
-+ ****************************************************************/
-+static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev)
-+{
-+      struct kaweth_device *kaweth = netdev_priv(dev);
-+      return &kaweth->stats;
-+}
-+
-+/****************************************************************
-+ *     kaweth_tx_timeout
-+ ****************************************************************/
-+static void kaweth_tx_timeout(struct net_device *net)
-+{
-+      struct kaweth_device *kaweth = netdev_priv(net);
-+
-+      dev_warn(&net->dev, "%s: Tx timed out. Resetting.\n", net->name);
-+      kaweth->stats.tx_errors++;
-+      net->trans_start = jiffies;
-+
-+      usb_unlink_urb(kaweth->tx_urb);
-+}
-+
-+/****************************************************************
-+ *     kaweth_suspend
-+ ****************************************************************/
-+static int kaweth_suspend(struct usb_interface *intf, pm_message_t message)
-+{
-+      struct kaweth_device *kaweth = usb_get_intfdata(intf);
-+      unsigned long flags;
-+
-+      dev_dbg(&intf->dev, "Suspending device\n");
-+      spin_lock_irqsave(&kaweth->device_lock, flags);
-+      kaweth->status |= KAWETH_STATUS_SUSPENDING;
-+      spin_unlock_irqrestore(&kaweth->device_lock, flags);
-+
-+      kaweth_kill_urbs(kaweth);
-+      return 0;
-+}
-+
-+/****************************************************************
-+ *     kaweth_resume
-+ ****************************************************************/
-+static int kaweth_resume(struct usb_interface *intf)
-+{
-+      struct kaweth_device *kaweth = usb_get_intfdata(intf);
-+      unsigned long flags;
-+
-+      dev_dbg(&intf->dev, "Resuming device\n");
-+      spin_lock_irqsave(&kaweth->device_lock, flags);
-+      kaweth->status &= ~KAWETH_STATUS_SUSPENDING;
-+      spin_unlock_irqrestore(&kaweth->device_lock, flags);
-+
-+      if (!kaweth->opened)
-+              return 0;
-+      kaweth_resubmit_rx_urb(kaweth, GFP_NOIO);
-+      kaweth_resubmit_int_urb(kaweth, GFP_NOIO);
-+
-+      return 0;
-+}
-+
-+/****************************************************************
-+ *     kaweth_probe
-+ ****************************************************************/
-+
-+
-+static const struct net_device_ops kaweth_netdev_ops = {
-+      .ndo_open =                     kaweth_open,
-+      .ndo_stop =                     kaweth_close,
-+      .ndo_start_xmit =               kaweth_start_xmit,
-+      .ndo_tx_timeout =               kaweth_tx_timeout,
-+      .ndo_set_rx_mode =              kaweth_set_rx_mode,
-+      .ndo_get_stats =                kaweth_netdev_stats,
-+      .ndo_change_mtu =               eth_change_mtu,
-+      .ndo_set_mac_address =          eth_mac_addr,
-+      .ndo_validate_addr =            eth_validate_addr,
-+};
-+
-+static int kaweth_probe(
-+              struct usb_interface *intf,
-+              const struct usb_device_id *id      /* from id_table */
-+      )
-+{
-+      struct device *dev = &intf->dev;
-+      struct usb_device *udev = interface_to_usbdev(intf);
-+      struct kaweth_device *kaweth;
-+      struct net_device *netdev;
-+      const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-+      int result = 0;
-+
-+      dev_dbg(dev,
-+              "Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x\n",
-+              udev->devnum, le16_to_cpu(udev->descriptor.idVendor),
-+              le16_to_cpu(udev->descriptor.idProduct),
-+              le16_to_cpu(udev->descriptor.bcdDevice));
-+
-+      dev_dbg(dev, "Device at %p\n", udev);
-+
-+      dev_dbg(dev, "Descriptor length: %x type: %x\n",
-+              (int)udev->descriptor.bLength,
-+              (int)udev->descriptor.bDescriptorType);
-+
-+      netdev = alloc_etherdev(sizeof(*kaweth));
-+      if (!netdev)
-+              return -ENOMEM;
-+
-+      kaweth = netdev_priv(netdev);
-+      kaweth->dev = udev;
-+      kaweth->net = netdev;
-+
-+      spin_lock_init(&kaweth->device_lock);
-+      init_waitqueue_head(&kaweth->term_wait);
-+
-+      dev_dbg(dev, "Resetting.\n");
-+
-+      kaweth_reset(kaweth);
-+
-+      /*
-+       * If high byte of bcdDevice is nonzero, firmware is already
-+       * downloaded. Don't try to do it again, or we'll hang the device.
-+       */
-+
-+      if (le16_to_cpu(udev->descriptor.bcdDevice) >> 8) {
-+              dev_info(dev, "Firmware present in device.\n");
-+      } else {
-+              /* Download the firmware */
-+              dev_info(dev, "Downloading firmware...\n");
-+              kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL);
-+              if ((result = kaweth_download_firmware(kaweth,
-+                                                    "kaweth/new_code.bin",
-+                                                    100,
-+                                                    2)) < 0) {
-+                      dev_err(dev, "Error downloading firmware (%d)\n",
-+                              result);
-+                      goto err_fw;
-+              }
-+
-+              if ((result = kaweth_download_firmware(kaweth,
-+                                                    "kaweth/new_code_fix.bin",
-+                                                    100,
-+                                                    3)) < 0) {
-+                      dev_err(dev, "Error downloading firmware fix (%d)\n",
-+                              result);
-+                      goto err_fw;
-+              }
-+
-+              if ((result = kaweth_download_firmware(kaweth,
-+                                                    "kaweth/trigger_code.bin",
-+                                                    126,
-+                                                    2)) < 0) {
-+                      dev_err(dev, "Error downloading trigger code (%d)\n",
-+                              result);
-+                      goto err_fw;
-+
-+              }
-+
-+              if ((result = kaweth_download_firmware(kaweth,
-+                                                    "kaweth/trigger_code_fix.bin",
-+                                                    126,
-+                                                    3)) < 0) {
-+                      dev_err(dev, "Error downloading trigger code fix (%d)\n", result);
-+                      goto err_fw;
-+              }
-+
-+
-+              if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) {
-+                      dev_err(dev, "Error triggering firmware (%d)\n", result);
-+                      goto err_fw;
-+              }
-+
-+              /* Device will now disappear for a moment...  */
-+              dev_info(dev, "Firmware loaded.  I'll be back...\n");
-+err_fw:
-+              free_page((unsigned long)kaweth->firmware_buf);
-+              free_netdev(netdev);
-+              return -EIO;
-+      }
-+
-+      result = kaweth_read_configuration(kaweth);
-+
-+      if(result < 0) {
-+              dev_err(dev, "Error reading configuration (%d), no net device created\n", result);
-+              goto err_free_netdev;
-+      }
-+
-+      dev_info(dev, "Statistics collection: %x\n", kaweth->configuration.statistics_mask);
-+      dev_info(dev, "Multicast filter limit: %x\n", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1));
-+      dev_info(dev, "MTU: %d\n", le16_to_cpu(kaweth->configuration.segment_size));
-+      dev_info(dev, "Read MAC address %pM\n", kaweth->configuration.hw_addr);
-+
-+      if(!memcmp(&kaweth->configuration.hw_addr,
-+                   &bcast_addr,
-+                 sizeof(bcast_addr))) {
-+              dev_err(dev, "Firmware not functioning properly, no net device created\n");
-+              goto err_free_netdev;
-+      }
-+
-+      if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) {
-+              dev_dbg(dev, "Error setting URB size\n");
-+              goto err_free_netdev;
-+      }
-+
-+      if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) {
-+              dev_err(dev, "Error setting SOFS wait\n");
-+              goto err_free_netdev;
-+      }
-+
-+      result = kaweth_set_receive_filter(kaweth,
-+                                           KAWETH_PACKET_FILTER_DIRECTED |
-+                                           KAWETH_PACKET_FILTER_BROADCAST |
-+                                           KAWETH_PACKET_FILTER_MULTICAST);
-+
-+      if(result < 0) {
-+              dev_err(dev, "Error setting receive filter\n");
-+              goto err_free_netdev;
-+      }
-+
-+      dev_dbg(dev, "Initializing net device.\n");
-+
-+      kaweth->intf = intf;
-+
-+      kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!kaweth->tx_urb)
-+              goto err_free_netdev;
-+      kaweth->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!kaweth->rx_urb)
-+              goto err_only_tx;
-+      kaweth->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!kaweth->irq_urb)
-+              goto err_tx_and_rx;
-+
-+      kaweth->intbuffer = usb_alloc_coherent( kaweth->dev,
-+                                              INTBUFFERSIZE,
-+                                              GFP_KERNEL,
-+                                              &kaweth->intbufferhandle);
-+      if (!kaweth->intbuffer)
-+              goto err_tx_and_rx_and_irq;
-+      kaweth->rx_buf = usb_alloc_coherent(    kaweth->dev,
-+                                              KAWETH_BUF_SIZE,
-+                                              GFP_KERNEL,
-+                                              &kaweth->rxbufferhandle);
-+      if (!kaweth->rx_buf)
-+              goto err_all_but_rxbuf;
-+
-+      memcpy(netdev->broadcast, &bcast_addr, sizeof(bcast_addr));
-+      memcpy(netdev->dev_addr, &kaweth->configuration.hw_addr,
-+               sizeof(kaweth->configuration.hw_addr));
-+
-+      netdev->netdev_ops = &kaweth_netdev_ops;
-+      netdev->watchdog_timeo = KAWETH_TX_TIMEOUT;
-+      netdev->mtu = le16_to_cpu(kaweth->configuration.segment_size);
-+      netdev->ethtool_ops = &ops;
-+
-+      /* kaweth is zeroed as part of alloc_netdev */
-+      INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl);
-+      usb_set_intfdata(intf, kaweth);
-+
-+#if 0
-+// dma_supported() is deeply broken on almost all architectures
-+      if (dma_supported (dev, 0xffffffffffffffffULL))
-+              kaweth->net->features |= NETIF_F_HIGHDMA;
-+#endif
-+
-+      SET_NETDEV_DEV(netdev, dev);
-+      if (register_netdev(netdev) != 0) {
-+              dev_err(dev, "Error registering netdev.\n");
-+              goto err_intfdata;
-+      }
-+
-+      dev_info(dev, "kaweth interface created at %s\n",
-+               kaweth->net->name);
-+
-+      dev_dbg(dev, "Kaweth probe returning.\n");
-+
-+      return 0;
-+
-+err_intfdata:
-+      usb_set_intfdata(intf, NULL);
-+      usb_free_coherent(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);
-+err_all_but_rxbuf:
-+      usb_free_coherent(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);
-+err_tx_and_rx_and_irq:
-+      usb_free_urb(kaweth->irq_urb);
-+err_tx_and_rx:
-+      usb_free_urb(kaweth->rx_urb);
-+err_only_tx:
-+      usb_free_urb(kaweth->tx_urb);
-+err_free_netdev:
-+      free_netdev(netdev);
-+
-+      return -EIO;
-+}
-+
-+/****************************************************************
-+ *     kaweth_disconnect
-+ ****************************************************************/
-+static void kaweth_disconnect(struct usb_interface *intf)
-+{
-+      struct kaweth_device *kaweth = usb_get_intfdata(intf);
-+      struct net_device *netdev;
-+
-+      dev_info(&intf->dev, "Unregistering\n");
-+
-+      usb_set_intfdata(intf, NULL);
-+      if (!kaweth) {
-+              dev_warn(&intf->dev, "unregistering non-existent device\n");
-+              return;
-+      }
-+      netdev = kaweth->net;
-+
-+      netdev_dbg(kaweth->net, "Unregistering net device\n");
-+      unregister_netdev(netdev);
-+
-+      usb_free_urb(kaweth->rx_urb);
-+      usb_free_urb(kaweth->tx_urb);
-+      usb_free_urb(kaweth->irq_urb);
-+
-+      usb_free_coherent(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);
-+      usb_free_coherent(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);
-+
-+      free_netdev(netdev);
-+}
-+
-+
-+// FIXME this completion stuff is a modified clone of
-+// an OLD version of some stuff in usb.c ...
-+struct usb_api_data {
-+      wait_queue_head_t wqh;
-+      int done;
-+};
-+
-+/*-------------------------------------------------------------------*
-+ * completion handler for compatibility wrappers (sync control/bulk) *
-+ *-------------------------------------------------------------------*/
-+static void usb_api_blocking_completion(struct urb *urb)
-+{
-+        struct usb_api_data *awd = (struct usb_api_data *)urb->context;
-+
-+      awd->done=1;
-+      wake_up(&awd->wqh);
-+}
-+
-+/*-------------------------------------------------------------------*
-+ *                         COMPATIBILITY STUFF                       *
-+ *-------------------------------------------------------------------*/
-+
-+// Starts urb and waits for completion or timeout
-+static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
-+{
-+      struct usb_api_data awd;
-+        int status;
-+
-+        init_waitqueue_head(&awd.wqh);
-+        awd.done = 0;
-+
-+        urb->context = &awd;
-+        status = usb_submit_urb(urb, GFP_ATOMIC);
-+        if (status) {
-+                // something went wrong
-+                usb_free_urb(urb);
-+                return status;
-+        }
-+
-+      if (!wait_event_timeout(awd.wqh, awd.done, timeout)) {
-+                // timeout
-+                dev_warn(&urb->dev->dev, "usb_control/bulk_msg: timeout\n");
-+                usb_kill_urb(urb);  // remove urb safely
-+                status = -ETIMEDOUT;
-+        }
-+      else {
-+                status = urb->status;
-+      }
-+
-+        if (actual_length) {
-+                *actual_length = urb->actual_length;
-+      }
-+
-+        usb_free_urb(urb);
-+        return status;
-+}
-+
-+/*-------------------------------------------------------------------*/
-+// returns status (negative) or length (positive)
-+static int kaweth_internal_control_msg(struct usb_device *usb_dev,
-+                                     unsigned int pipe,
-+                                     struct usb_ctrlrequest *cmd, void *data,
-+                                     int len, int timeout)
-+{
-+        struct urb *urb;
-+        int retv;
-+        int length = 0; /* shut up GCC */
-+
-+      urb = usb_alloc_urb(0, GFP_ATOMIC);
-+        if (!urb)
-+                return -ENOMEM;
-+
-+        usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char*)cmd, data,
-+                       len, usb_api_blocking_completion, NULL);
-+
-+        retv = usb_start_wait_urb(urb, timeout, &length);
-+        if (retv < 0) {
-+                return retv;
-+      }
-+        else {
-+                return length;
-+      }
-+}
-+
-+module_usb_driver(kaweth_driver);
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/Kconfig backports-4.2.6-1/drivers/net/usb/Kconfig
---- backports-4.2.6-1.org/drivers/net/usb/Kconfig      2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/Kconfig  2016-06-28 14:35:17.991973886 +0200
-@@ -13,7 +13,6 @@
- if USB_NET_DRIVERS
- config USB_CATC
--      depends on n
-       tristate "USB CATC NetMate-based Ethernet device support"
-       depends on m
-       depends on CRC32
-@@ -34,7 +33,6 @@
-         module will be called catc.
- config USB_KAWETH
--      depends on n
-       tristate "USB KLSI KL5USB101-based ethernet device support"
-       depends on m
-       ---help---
-@@ -75,7 +73,6 @@
-         module will be called kaweth.
- config USB_PEGASUS
--      depends on n
-       tristate "USB Pegasus/Pegasus-II based ethernet device support"
-       depends on m
-       select BPAUTO_MII
-@@ -92,7 +89,6 @@
-         module will be called pegasus.
- config USB_RTL8150
--      depends on n
-       tristate "USB RTL8150 based ethernet device support"
-       depends on m
-       select BPAUTO_MII
-@@ -105,7 +101,6 @@
-         module will be called rtl8150.
- config USB_RTL8152
--      depends on n
-       tristate "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
-       depends on m
-       select BPAUTO_MII
-@@ -153,7 +148,6 @@
-         module will be called usbnet.
- config USB_NET_AX8817X
--      depends on n
-       tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters"
-       depends on m
-       depends on USB_USBNET
-@@ -184,7 +178,6 @@
-         what other networking devices you have in use.
- config USB_NET_AX88179_178A
--      depends on n
-       tristate "ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet"
-       depends on m
-       depends on USB_USBNET
-@@ -233,7 +226,6 @@
-         name is used instead.
- config USB_NET_CDC_EEM
--      depends on n
-       tristate "CDC EEM support"
-       depends on m
-       depends on USB_USBNET
-@@ -269,7 +261,6 @@
-           * Ericsson F5521gw Mobile Broadband Module
- config USB_NET_HUAWEI_CDC_NCM
--      depends on n
-       tristate "Huawei NCM embedded AT channel support"
-       depends on m
-       depends on USB_USBNET
-@@ -305,7 +296,6 @@
-         module will be called cdc_mbim.
- config USB_NET_DM9601
--      depends on n
-       tristate "Davicom DM96xx based USB 10/100 ethernet devices"
-       depends on m
-       depends on USB_USBNET
-@@ -315,7 +305,6 @@
-         based USB 10/100 Ethernet adapters.
- config USB_NET_SR9700
--      depends on n
-       tristate "CoreChip-sz SR9700 based USB 1.1 10/100 ethernet devices"
-       depends on m
-       depends on USB_USBNET
-@@ -325,7 +314,6 @@
-         10/100 Ethernet adapters.
- config USB_NET_SR9800
--      depends on n
-       tristate "CoreChip-sz SR9800 based USB 2.0 10/100 ethernet devices"
-       depends on m
-       depends on USB_USBNET
-@@ -342,7 +330,6 @@
-         module will be called sr9800.
- config USB_NET_SMSC75XX
--      depends on n
-       tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices"
-       depends on m
-       depends on USB_USBNET
-@@ -354,7 +341,6 @@
-         Gigabit Ethernet adapters.
- config USB_NET_SMSC95XX
--      depends on n
-       tristate "SMSC LAN95XX based USB 2.0 10/100 ethernet devices"
-       depends on m
-       depends on USB_USBNET
-@@ -366,7 +352,6 @@
-         10/100 Ethernet adapters.
- config USB_NET_GL620A
--      depends on n
-       tristate "GeneSys GL620USB-A based cables"
-       depends on m
-       depends on USB_USBNET
-@@ -377,7 +362,6 @@
-         Note that the half-duplex "GL620USB" is not supported.
- config USB_NET_NET1080
--      depends on n
-       tristate "NetChip 1080 based cables (Laplink, ...)"
-       depends on m
-       default y
-@@ -388,7 +372,6 @@
-         optionally with LEDs that indicate traffic
- config USB_NET_PLUSB
--      depends on n
-       tristate "Prolific PL-2301/2302/25A1 based cables"
-       depends on m
-       # if the handshake/init/reset problems, from original 'plusb',
-@@ -399,7 +382,6 @@
-         with one of these chips.
- config USB_NET_MCS7830
--      depends on n
-       tristate "MosChip MCS7830 based Ethernet adapters"
-       depends on m
-       depends on USB_USBNET
-@@ -425,7 +407,6 @@
-         (and for) Microsoft; it isn't an "Open" ecosystem or market.
- config USB_NET_CDC_SUBSET
--      depends on n
-       tristate "Simple USB Network Links (CDC Ethernet subset)"
-       depends on m
-       depends on USB_USBNET
-@@ -497,7 +478,6 @@
-         with one of these chips.
- config USB_NET_ZAURUS
--      depends on n
-       tristate "Sharp Zaurus (stock ROMs) and compatible"
-       depends on m
-       depends on USB_USBNET
-@@ -517,7 +497,6 @@
-         some cases CDC MDLM) protocol, not "g_ether".
- config USB_NET_CX82310_ETH
--      depends on n
-       tristate "Conexant CX82310 USB ethernet port"
-       depends on m
-       depends on USB_USBNET
-@@ -527,7 +506,6 @@
-         it will not work with ADSL modems (use cxacru driver instead).
- config USB_NET_KALMIA
--      depends on n
-       tristate "Samsung Kalmia based LTE USB modem"
-       depends on m
-       depends on USB_USBNET
-@@ -562,7 +540,6 @@
-         module will be called qmi_wwan.
- config USB_HSO
--      depends on n
-       tristate "Option USB High Speed Mobile Devices"
-       depends on m
-       depends on USB && RFKILL && TTY
-@@ -575,7 +552,6 @@
-         module will be called hso.
- config USB_NET_INT51X1
--      depends on n
-       tristate "Intellon PLC based usb adapter"
-       depends on m
-       depends on USB_USBNET
-@@ -585,7 +561,6 @@
-         INT51x1/INT5200 chip, like the "devolo dLan duo".
- config USB_CDC_PHONET
--      depends on n
-       tristate "CDC Phonet support"
-       depends on m
-       depends on PHONET
-@@ -595,7 +570,6 @@
-         "PC suite" USB profile.
- config USB_IPHETH
--      depends on n
-       tristate "Apple iPhone USB Ethernet driver"
-       depends on m
-       default n
-@@ -619,11 +593,10 @@
-         module will be called sierra_net.
- config USB_VL600
--      depends on n
-       tristate "LG VL600 modem dongle"
-       depends on m
-       depends on USB_NET_CDCETHER && TTY
--      select USB_ACM
-+#     depends on USB_ACM
-       help
-         Select this if you want to use an LG Electronics 4G/LTE usb modem
-         called VL600.  This driver only handles the ethernet
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/Kconfig.orig backports-4.2.6-1/drivers/net/usb/Kconfig.orig
---- backports-4.2.6-1.org/drivers/net/usb/Kconfig.orig 1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/Kconfig.orig     2016-06-28 14:35:17.991973886 +0200
-@@ -0,0 +1,638 @@
-+#
-+# USB Network devices configuration
-+#
-+comment "Host-side USB support is needed for USB Network Adapter support"
-+      depends on !USB && NET
-+
-+menuconfig USB_NET_DRIVERS
-+      tristate "USB Network Adapters"
-+      depends on m
-+      default USB if USB
-+      depends on USB && NET
-+
-+if USB_NET_DRIVERS
-+
-+config USB_CATC
-+      depends on n
-+      tristate "USB CATC NetMate-based Ethernet device support"
-+      depends on m
-+      depends on CRC32
-+      ---help---
-+        Say Y if you want to use one of the following 10Mbps USB Ethernet
-+        device based on the EL1210A chip. Supported devices are:
-+        Belkin F5U011
-+        Belkin F5U111
-+        CATC NetMate
-+        CATC NetMate II
-+        smartBridges smartNIC
-+
-+        This driver makes the adapter appear as a normal Ethernet interface,
-+        typically on eth0, if it is the only ethernet device, or perhaps on
-+        eth1, if you have a PCI or ISA ethernet card installed.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called catc.
-+
-+config USB_KAWETH
-+      depends on n
-+      tristate "USB KLSI KL5USB101-based ethernet device support"
-+      depends on m
-+      ---help---
-+        Say Y here if you want to use one of the following 10Mbps only
-+        USB Ethernet adapters based on the KLSI KL5KUSB101B chipset:
-+        3Com 3C19250
-+        ADS USB-10BT
-+        ATEN USB Ethernet
-+        ASANTE USB To Ethernet Adapter
-+        AOX Endpoints USB Ethernet
-+        Correga K.K.
-+        D-Link DSB-650C and DU-E10
-+        Entrega / Portgear E45
-+        I-O DATA USB-ET/T
-+        Jaton USB Ethernet Device Adapter
-+        Kingston Technology USB Ethernet Adapter
-+        Linksys USB10T
-+        Mobility USB-Ethernet Adapter
-+        NetGear EA-101
-+        Peracom Enet and Enet2
-+        Portsmith Express Ethernet Adapter
-+        Shark Pocket Adapter
-+        SMC 2202USB
-+        Sony Vaio port extender
-+
-+        This driver is likely to work with most 10Mbps only USB Ethernet
-+        adapters, including some "no brand" devices. It does NOT work on
-+        SmartBridges smartNIC or on Belkin F5U111 devices - you should use
-+        the CATC NetMate driver for those. If you are not sure which one
-+        you need, select both, and the correct one should be selected for
-+        you.
-+
-+        This driver makes the adapter appear as a normal Ethernet interface,
-+        typically on eth0, if it is the only ethernet device, or perhaps on
-+        eth1, if you have a PCI or ISA ethernet card installed.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called kaweth.
-+
-+config USB_PEGASUS
-+      depends on n
-+      tristate "USB Pegasus/Pegasus-II based ethernet device support"
-+      depends on m
-+      select BPAUTO_MII
-+      ---help---
-+        Say Y here if you know you have Pegasus or Pegasus-II based adapter.
-+        If in doubt then look at <file:drivers/net/usb/pegasus.h> for the
-+        complete list of supported devices.
-+
-+        If your particular adapter is not in the list and you are _sure_ it
-+        is Pegasus or Pegasus II based then send me
-+        <petkan@users.sourceforge.net> vendor and device IDs.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called pegasus.
-+
-+config USB_RTL8150
-+      depends on n
-+      tristate "USB RTL8150 based ethernet device support"
-+      depends on m
-+      select BPAUTO_MII
-+      help
-+        Say Y here if you have RTL8150 based usb-ethernet adapter.
-+        Send me <petkan@users.sourceforge.net> any comments you may have.
-+        You can also check for updates at <http://pegasus2.sourceforge.net/>.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called rtl8150.
-+
-+config USB_RTL8152
-+      depends on n
-+      tristate "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
-+      depends on m
-+      select BPAUTO_MII
-+      help
-+        This option adds support for Realtek RTL8152 based USB 2.0
-+        10/100 Ethernet adapters and RTL8153 based USB 3.0 10/100/1000
-+        Ethernet adapters.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called r8152.
-+
-+config USB_USBNET
-+      tristate "Multi-purpose USB Networking Framework"
-+      depends on m
-+      select BPAUTO_MII
-+      ---help---
-+        This driver supports several kinds of network links over USB,
-+        with "minidrivers" built around a common network driver core
-+        that supports deep queues for efficient transfers.  (This gives
-+        better performance with small packets and at high speeds).
-+
-+        The USB host runs "usbnet", and the other end of the link might be:
-+
-+        - Another USB host, when using USB "network" or "data transfer"
-+          cables.  These are often used to network laptops to PCs, like
-+          "Laplink" parallel cables or some motherboards.  These rely
-+          on specialized chips from many suppliers.
-+
-+        - An intelligent USB gadget, perhaps embedding a Linux system.
-+          These include PDAs running Linux (iPaq, Yopy, Zaurus, and
-+          others), and devices that interoperate using the standard
-+          CDC-Ethernet specification (including many cable modems).
-+
-+        - Network adapter hardware (like those for 10/100 Ethernet) which
-+          uses this driver framework.
-+
-+        The link will appear with a name like "usb0", when the link is
-+        a two-node link, or "eth0" for most CDC-Ethernet devices.  Those
-+        two-node links are most easily managed with Ethernet Bridging
-+        (CONFIG_BRIDGE) instead of routing.
-+
-+        For more information see <http://www.linux-usb.org/usbnet/>.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called usbnet.
-+
-+config USB_NET_AX8817X
-+      depends on n
-+      tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters"
-+      depends on m
-+      depends on USB_USBNET
-+      depends on CRC32
-+      depends on PHYLIB
-+      default y
-+      help
-+        This option adds support for ASIX AX88xxx based USB 2.0
-+        10/100 Ethernet adapters.
-+
-+        This driver should work with at least the following devices:
-+          * Aten UC210T
-+          * ASIX AX88172
-+          * Billionton Systems, USB2AR
-+          * Buffalo LUA-U2-KTX
-+          * Corega FEther USB2-TX
-+          * D-Link DUB-E100
-+          * Hawking UF200
-+          * Linksys USB200M
-+          * Netgear FA120
-+          * Sitecom LN-029
-+          * Sitecom LN-028
-+          * Intellinet USB 2.0 Ethernet
-+          * ST Lab USB 2.0 Ethernet
-+          * TrendNet TU2-ET100
-+
-+        This driver creates an interface named "ethX", where X depends on
-+        what other networking devices you have in use.
-+
-+config USB_NET_AX88179_178A
-+      depends on n
-+      tristate "ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet"
-+      depends on m
-+      depends on USB_USBNET
-+      depends on CRC32
-+      depends on PHYLIB
-+      default y
-+      help
-+        This option adds support for ASIX AX88179 based USB 3.0/2.0
-+        to Gigabit Ethernet adapters.
-+
-+        This driver should work with at least the following devices:
-+          * ASIX AX88179
-+          * ASIX AX88178A
-+          * Sitcomm LN-032
-+
-+        This driver creates an interface named "ethX", where X depends on
-+        what other networking devices you have in use.
-+
-+config USB_NET_CDCETHER
-+      tristate "CDC Ethernet support (smart devices such as cable modems)"
-+      depends on m
-+      depends on USB_USBNET
-+      default y
-+      help
-+        This option supports devices conforming to the Communication Device
-+        Class (CDC) Ethernet Control Model, a specification that's easy to
-+        implement in device firmware.  The CDC specifications are available
-+        from <http://www.usb.org/>.
-+
-+        CDC Ethernet is an implementation option for DOCSIS cable modems
-+        that support USB connectivity, used for non-Microsoft USB hosts.
-+        The Linux-USB CDC Ethernet Gadget driver is an open implementation.
-+        This driver should work with at least the following devices:
-+
-+          * Dell Wireless 5530 HSPA
-+          * Ericsson PipeRider (all variants)
-+          * Ericsson Mobile Broadband Module (all variants)
-+          * Motorola (DM100 and SB4100)
-+          * Broadcom Cable Modem (reference design)
-+          * Toshiba (PCX1100U and F3507g/F3607gw)
-+          * ...
-+
-+        This driver creates an interface named "ethX", where X depends on
-+        what other networking devices you have in use.  However, if the
-+        IEEE 802 "local assignment" bit is set in the address, a "usbX"
-+        name is used instead.
-+
-+config USB_NET_CDC_EEM
-+      depends on n
-+      tristate "CDC EEM support"
-+      depends on m
-+      depends on USB_USBNET
-+      help
-+        This option supports devices conforming to the Communication Device
-+        Class (CDC) Ethernet Emulation Model, a specification that's easy to
-+        implement in device firmware.  The CDC EEM specifications are available
-+        from <http://www.usb.org/>.
-+
-+        This driver creates an interface named "ethX", where X depends on
-+        what other networking devices you have in use.  However, if the
-+        IEEE 802 "local assignment" bit is set in the address, a "usbX"
-+        name is used instead.
-+
-+config USB_NET_CDC_NCM
-+      tristate "CDC NCM support"
-+      depends on m
-+      depends on USB_USBNET
-+      default y
-+      help
-+        This driver provides support for CDC NCM (Network Control Model
-+        Device USB Class Specification). The CDC NCM specification is
-+        available from <http://www.usb.org/>.
-+
-+        Say "y" to link the driver statically, or "m" to build a
-+        dynamically linked module.
-+
-+        This driver should work with at least the following devices:
-+          * ST-Ericsson M700 LTE FDD/TDD Mobile Broadband Modem (ref. design)
-+          * ST-Ericsson M5730 HSPA+ Mobile Broadband Modem (reference design)
-+          * ST-Ericsson M570 HSPA+ Mobile Broadband Modem (reference design)
-+          * ST-Ericsson M343 HSPA Mobile Broadband Modem (reference design)
-+          * Ericsson F5521gw Mobile Broadband Module
-+
-+config USB_NET_HUAWEI_CDC_NCM
-+      depends on n
-+      tristate "Huawei NCM embedded AT channel support"
-+      depends on m
-+      depends on USB_USBNET
-+      select USB_WDM
-+      select USB_NET_CDC_NCM
-+      help
-+              This driver supports huawei-style NCM devices, that use NCM as a
-+              transport for other protocols, usually an embedded AT channel.
-+              Good examples are:
-+              * Huawei E3131
-+              * Huawei E3251
-+
-+              To compile this driver as a module, choose M here: the module will be
-+              called huawei_cdc_ncm.ko.
-+
-+config USB_NET_CDC_MBIM
-+      tristate "CDC MBIM support"
-+      depends on m
-+      depends on USB_USBNET
-+      select USB_WDM
-+      select USB_NET_CDC_NCM
-+      help
-+        This driver provides support for CDC MBIM (Mobile Broadband
-+        Interface Model) devices. The CDC MBIM specification is
-+        available from <http://www.usb.org/>.
-+
-+        MBIM devices require configuration using the management
-+        protocol defined by the MBIM specification.  This driver
-+        provides unfiltered access to the MBIM control channel
-+        through the associated /dev/cdc-wdmx character device.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called cdc_mbim.
-+
-+config USB_NET_DM9601
-+      depends on n
-+      tristate "Davicom DM96xx based USB 10/100 ethernet devices"
-+      depends on m
-+      depends on USB_USBNET
-+      depends on CRC32
-+      help
-+        This option adds support for Davicom DM9601/DM9620/DM9621A
-+        based USB 10/100 Ethernet adapters.
-+
-+config USB_NET_SR9700
-+      depends on n
-+      tristate "CoreChip-sz SR9700 based USB 1.1 10/100 ethernet devices"
-+      depends on m
-+      depends on USB_USBNET
-+      depends on CRC32
-+      help
-+        This option adds support for CoreChip-sz SR9700 based USB 1.1
-+        10/100 Ethernet adapters.
-+
-+config USB_NET_SR9800
-+      depends on n
-+      tristate "CoreChip-sz SR9800 based USB 2.0 10/100 ethernet devices"
-+      depends on m
-+      depends on USB_USBNET
-+      depends on CRC32
-+      ---help---
-+        Say Y if you want to use one of the following 100Mbps USB Ethernet
-+        device based on the CoreChip-sz SR9800 chip.
-+
-+        This driver makes the adapter appear as a normal Ethernet interface,
-+        typically on eth0, if it is the only ethernet device, or perhaps on
-+        eth1, if you have a PCI or ISA ethernet card installed.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called sr9800.
-+
-+config USB_NET_SMSC75XX
-+      depends on n
-+      tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices"
-+      depends on m
-+      depends on USB_USBNET
-+      depends on BITREVERSE
-+      depends on CRC16
-+      depends on CRC32
-+      help
-+        This option adds support for SMSC LAN75XX based USB 2.0
-+        Gigabit Ethernet adapters.
-+
-+config USB_NET_SMSC95XX
-+      depends on n
-+      tristate "SMSC LAN95XX based USB 2.0 10/100 ethernet devices"
-+      depends on m
-+      depends on USB_USBNET
-+      depends on BITREVERSE
-+      depends on CRC16
-+      depends on CRC32
-+      help
-+        This option adds support for SMSC LAN95XX based USB 2.0
-+        10/100 Ethernet adapters.
-+
-+config USB_NET_GL620A
-+      depends on n
-+      tristate "GeneSys GL620USB-A based cables"
-+      depends on m
-+      depends on USB_USBNET
-+      help
-+        Choose this option if you're using a host-to-host cable,
-+        or PC2PC motherboard, with this chip.
-+
-+        Note that the half-duplex "GL620USB" is not supported.
-+
-+config USB_NET_NET1080
-+      depends on n
-+      tristate "NetChip 1080 based cables (Laplink, ...)"
-+      depends on m
-+      default y
-+      depends on USB_USBNET
-+      help
-+        Choose this option if you're using a host-to-host cable based
-+        on this design:  one NetChip 1080 chip and supporting logic,
-+        optionally with LEDs that indicate traffic
-+
-+config USB_NET_PLUSB
-+      depends on n
-+      tristate "Prolific PL-2301/2302/25A1 based cables"
-+      depends on m
-+      # if the handshake/init/reset problems, from original 'plusb',
-+      # are ever resolved ... then remove "experimental"
-+      depends on USB_USBNET
-+      help
-+        Choose this option if you're using a host-to-host cable
-+        with one of these chips.
-+
-+config USB_NET_MCS7830
-+      depends on n
-+      tristate "MosChip MCS7830 based Ethernet adapters"
-+      depends on m
-+      depends on USB_USBNET
-+      help
-+        Choose this option if you're using a 10/100 Ethernet USB2
-+        adapter based on the MosChip 7830 controller. This includes
-+        adapters marketed under the DeLOCK brand.
-+
-+config USB_NET_RNDIS_HOST
-+      tristate "Host for RNDIS and ActiveSync devices"
-+      depends on m
-+      depends on USB_USBNET
-+      select USB_NET_CDCETHER
-+      help
-+        This option enables hosting "Remote NDIS" USB networking links,
-+        as encouraged by Microsoft (instead of CDC Ethernet!) for use in
-+        various devices that may only support this protocol.  A variant
-+        of this protocol (with even less public documentation) seems to
-+        be at the root of Microsoft's "ActiveSync" too.
-+
-+        Avoid using this protocol unless you have no better options.
-+        The protocol specification is incomplete, and is controlled by
-+        (and for) Microsoft; it isn't an "Open" ecosystem or market.
-+
-+config USB_NET_CDC_SUBSET
-+      depends on n
-+      tristate "Simple USB Network Links (CDC Ethernet subset)"
-+      depends on m
-+      depends on USB_USBNET
-+      default y
-+      help
-+        This driver module supports USB network devices that can work
-+        without any device-specific information.  Select it if you have
-+        one of these drivers.
-+
-+        Note that while many USB host-to-host cables can work in this mode,
-+        that may mean not being able to talk to Win32 systems or more
-+        commonly not being able to handle certain events (like replugging
-+        the host on the other end) very well.  Also, these devices will
-+        not generally have permanently assigned Ethernet addresses.
-+
-+config USB_ALI_M5632
-+      bool "ALi M5632 based 'USB 2.0 Data Link' cables"
-+      depends on USB_NET_CDC_SUBSET
-+      help
-+        Choose this option if you're using a host-to-host cable
-+        based on this design, which supports USB 2.0 high speed.
-+
-+config USB_AN2720
-+      bool "AnchorChips 2720 based cables (Xircom PGUNET, ...)"
-+      depends on USB_NET_CDC_SUBSET
-+      help
-+        Choose this option if you're using a host-to-host cable
-+        based on this design.  Note that AnchorChips is now a
-+        Cypress brand.
-+
-+config USB_BELKIN
-+      bool "eTEK based host-to-host cables (Advance, Belkin, ...)"
-+      depends on USB_NET_CDC_SUBSET
-+      default y
-+      help
-+        Choose this option if you're using a host-to-host cable
-+        based on this design:  two NetChip 2890 chips and an Atmel
-+        microcontroller, with LEDs that indicate traffic.
-+
-+config USB_ARMLINUX
-+      bool "Embedded ARM Linux links (iPaq, ...)"
-+      depends on USB_NET_CDC_SUBSET
-+      default y
-+      help
-+        Choose this option to support the "usb-eth" networking driver
-+        used by most of the ARM Linux community with device controllers
-+        such as the SA-11x0 and PXA-25x UDCs, or the tftp capabilities
-+        in some PXA versions of the "blob" boot loader.
-+
-+        Linux-based "Gumstix" PXA-25x based systems use this protocol
-+        to talk with other Linux systems.
-+
-+        Although the ROMs shipped with Sharp Zaurus products use a
-+        different link level framing protocol, you can have them use
-+        this simpler protocol by installing a different kernel.
-+
-+config USB_EPSON2888
-+      bool "Epson 2888 based firmware (DEVELOPMENT)"
-+      depends on USB_NET_CDC_SUBSET
-+      help
-+        Choose this option to support the usb networking links used
-+        by some sample firmware from Epson.
-+
-+config USB_KC2190
-+      bool "KT Technology KC2190 based cables (InstaNet)"
-+      depends on USB_NET_CDC_SUBSET
-+      help
-+        Choose this option if you're using a host-to-host cable
-+        with one of these chips.
-+
-+config USB_NET_ZAURUS
-+      depends on n
-+      tristate "Sharp Zaurus (stock ROMs) and compatible"
-+      depends on m
-+      depends on USB_USBNET
-+      select USB_NET_CDCETHER
-+      depends on CRC32
-+      default y
-+      help
-+        Choose this option to support the usb networking links used by
-+        Zaurus models like the SL-5000D, SL-5500, SL-5600, A-300, B-500.
-+        This also supports some related device firmware, as used in some
-+        PDAs from Olympus and some cell phones from Motorola.
-+
-+        If you install an alternate image, such as the Linux 2.6 based
-+        versions of OpenZaurus, you should no longer need to support this
-+        protocol.  Only the "eth-fd" or "net_fd" drivers in these devices
-+        really need this non-conformant variant of CDC Ethernet (or in
-+        some cases CDC MDLM) protocol, not "g_ether".
-+
-+config USB_NET_CX82310_ETH
-+      depends on n
-+      tristate "Conexant CX82310 USB ethernet port"
-+      depends on m
-+      depends on USB_USBNET
-+      help
-+        Choose this option if you're using a Conexant CX82310-based ADSL
-+        router with USB ethernet port. This driver is for routers only,
-+        it will not work with ADSL modems (use cxacru driver instead).
-+
-+config USB_NET_KALMIA
-+      depends on n
-+      tristate "Samsung Kalmia based LTE USB modem"
-+      depends on m
-+      depends on USB_USBNET
-+      help
-+        Choose this option if you have a Samsung Kalmia based USB modem
-+        as Samsung GT-B3730.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called kalmia.
-+
-+config USB_NET_QMI_WWAN
-+      tristate "QMI WWAN driver for Qualcomm MSM based 3G and LTE modems"
-+      depends on m
-+      depends on USB_USBNET
-+      select USB_WDM
-+      help
-+        Support WWAN LTE/3G devices based on Qualcomm Mobile Data Modem
-+        (MDM) chipsets.  Examples of such devices are
-+          * Huawei E392/E398
-+
-+        This driver will only drive the ethernet part of the chips.
-+        The devices require additional configuration to be usable.
-+        Multiple management interfaces with linux drivers are
-+        available:
-+
-+          * option: AT commands on /dev/ttyUSBx
-+          * cdc-wdm: Qualcomm MSM Interface (QMI) protocol on /dev/cdc-wdmx
-+
-+        A modem manager with support for QMI is recommended.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called qmi_wwan.
-+
-+config USB_HSO
-+      depends on n
-+      tristate "Option USB High Speed Mobile Devices"
-+      depends on m
-+      depends on USB && RFKILL && TTY
-+      default n
-+      help
-+        Choose this option if you have an Option HSDPA/HSUPA card.
-+        These cards support downlink speeds of 7.2Mbps or greater.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called hso.
-+
-+config USB_NET_INT51X1
-+      depends on n
-+      tristate "Intellon PLC based usb adapter"
-+      depends on m
-+      depends on USB_USBNET
-+      help
-+        Choose this option if you're using a 14Mb USB-based PLC
-+        (Powerline Communications) solution with an Intellon
-+        INT51x1/INT5200 chip, like the "devolo dLan duo".
-+
-+config USB_CDC_PHONET
-+      depends on n
-+      tristate "CDC Phonet support"
-+      depends on m
-+      depends on PHONET
-+      help
-+        Choose this option to support the Phonet interface to a Nokia
-+        cellular modem, as found on most Nokia handsets with the
-+        "PC suite" USB profile.
-+
-+config USB_IPHETH
-+      depends on n
-+      tristate "Apple iPhone USB Ethernet driver"
-+      depends on m
-+      default n
-+      ---help---
-+        Module used to share Internet connection (tethering) from your
-+        iPhone (Original, 3G and 3GS) to your system.
-+        Note that you need userspace libraries and programs that are needed
-+        to pair your device with your system and that understand the iPhone
-+        protocol.
-+
-+        For more information: http://giagio.com/wiki/moin.cgi/iPhoneEthernetDriver
-+
-+config USB_SIERRA_NET
-+      tristate "USB-to-WWAN Driver for Sierra Wireless modems"
-+      depends on m
-+      depends on USB_USBNET
-+      help
-+        Choose this option if you have a Sierra Wireless USB-to-WWAN device.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called sierra_net.
-+
-+config USB_VL600
-+      depends on n
-+      tristate "LG VL600 modem dongle"
-+      depends on m
-+      depends on USB_NET_CDCETHER && TTY
-+      select USB_ACM
-+      help
-+        Select this if you want to use an LG Electronics 4G/LTE usb modem
-+        called VL600.  This driver only handles the ethernet
-+        interface exposed by the modem firmware.  To establish a connection
-+        you will first need a userspace program that sends the right
-+        command to the modem through its CDC ACM port, and most
-+        likely also a DHCP client.  See this thread about using the
-+        4G modem from Verizon:
-+
-+        http://ubuntuforums.org/showpost.php?p=10589647&postcount=17
-+
-+endif # USB_NET_DRIVERS
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/lg-vl600.c backports-4.2.6-1/drivers/net/usb/lg-vl600.c
---- backports-4.2.6-1.org/drivers/net/usb/lg-vl600.c   1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/lg-vl600.c       2016-06-28 14:35:17.991973886 +0200
-@@ -0,0 +1,353 @@
-+/*
-+ * Ethernet interface part of the LG VL600 LTE modem (4G dongle)
-+ *
-+ * Copyright (C) 2011 Intel Corporation
-+ * Author: Andrzej Zaborowski <balrogg@gmail.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ */
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/usb/cdc.h>
-+#include <linux/usb/usbnet.h>
-+#include <linux/if_ether.h>
-+#include <linux/if_arp.h>
-+#include <linux/inetdevice.h>
-+#include <linux/module.h>
-+
-+/*
-+ * The device has a CDC ACM port for modem control (it claims to be
-+ * CDC ACM anyway) and a CDC Ethernet port for actual network data.
-+ * It will however ignore data on both ports that is not encapsulated
-+ * in a specific way, any data returned is also encapsulated the same
-+ * way.  The headers don't seem to follow any popular standard.
-+ *
-+ * This driver adds and strips these headers from the ethernet frames
-+ * sent/received from the CDC Ethernet port.  The proprietary header
-+ * replaces the standard ethernet header in a packet so only actual
-+ * ethernet frames are allowed.  The headers allow some form of
-+ * multiplexing by using non standard values of the .h_proto field.
-+ * Windows/Mac drivers do send a couple of such frames to the device
-+ * during initialisation, with protocol set to 0x0906 or 0x0b06 and (what
-+ * seems to be) a flag in the .dummy_flags.  This doesn't seem necessary
-+ * for modem operation but can possibly be used for GPS or other funcitons.
-+ */
-+
-+struct vl600_frame_hdr {
-+      __le32 len;
-+      __le32 serial;
-+      __le32 pkt_cnt;
-+      __le32 dummy_flags;
-+      __le32 dummy;
-+      __le32 magic;
-+} __attribute__((packed));
-+
-+struct vl600_pkt_hdr {
-+      __le32 dummy[2];
-+      __le32 len;
-+      __be16 h_proto;
-+} __attribute__((packed));
-+
-+struct vl600_state {
-+      struct sk_buff *current_rx_buf;
-+};
-+
-+static int vl600_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      int ret;
-+      struct vl600_state *s = kzalloc(sizeof(struct vl600_state), GFP_KERNEL);
-+
-+      if (!s)
-+              return -ENOMEM;
-+
-+      ret = usbnet_cdc_bind(dev, intf);
-+      if (ret) {
-+              kfree(s);
-+              return ret;
-+      }
-+
-+      dev->driver_priv = s;
-+
-+      /* ARP packets don't go through, but they're also of no use.  The
-+       * subnet has only two hosts anyway: us and the gateway / DHCP
-+       * server (probably simulated by modem firmware or network operator)
-+       * whose address changes everytime we connect to the intarwebz and
-+       * who doesn't bother answering ARP requests either.  So hardware
-+       * addresses have no meaning, the destination and the source of every
-+       * packet depend only on whether it is on the IN or OUT endpoint.  */
-+      dev->net->flags |= IFF_NOARP;
-+      /* IPv6 NDP relies on multicast.  Enable it by default. */
-+      dev->net->flags |= IFF_MULTICAST;
-+
-+      return ret;
-+}
-+
-+static void vl600_unbind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      struct vl600_state *s = dev->driver_priv;
-+
-+      if (s->current_rx_buf)
-+              dev_kfree_skb(s->current_rx_buf);
-+
-+      kfree(s);
-+
-+      return usbnet_cdc_unbind(dev, intf);
-+}
-+
-+static int vl600_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      struct vl600_frame_hdr *frame;
-+      struct vl600_pkt_hdr *packet;
-+      struct ethhdr *ethhdr;
-+      int packet_len, count;
-+      struct sk_buff *buf = skb;
-+      struct sk_buff *clone;
-+      struct vl600_state *s = dev->driver_priv;
-+
-+      /* Frame lengths are generally 4B multiplies but every couple of
-+       * hours there's an odd number of bytes sized yet correct frame,
-+       * so don't require this.  */
-+
-+      /* Allow a packet (or multiple packets batched together) to be
-+       * split across many frames.  We don't allow a new batch to
-+       * begin in the same frame another one is ending however, and no
-+       * leading or trailing pad bytes.  */
-+      if (s->current_rx_buf) {
-+              frame = (struct vl600_frame_hdr *) s->current_rx_buf->data;
-+              if (skb->len + s->current_rx_buf->len >
-+                              le32_to_cpup(&frame->len)) {
-+                      netif_err(dev, ifup, dev->net, "Fragment too long\n");
-+                      dev->net->stats.rx_length_errors++;
-+                      goto error;
-+              }
-+
-+              buf = s->current_rx_buf;
-+              memcpy(skb_put(buf, skb->len), skb->data, skb->len);
-+      } else if (skb->len < 4) {
-+              netif_err(dev, ifup, dev->net, "Frame too short\n");
-+              dev->net->stats.rx_length_errors++;
-+              goto error;
-+      }
-+
-+      frame = (struct vl600_frame_hdr *) buf->data;
-+      /* 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)) {
-+              /* Save this fragment for later assembly */
-+              if (s->current_rx_buf)
-+                      return 0;
-+
-+              s->current_rx_buf = skb_copy_expand(skb, 0,
-+                              le32_to_cpup(&frame->len), GFP_ATOMIC);
-+              if (!s->current_rx_buf) {
-+                      netif_err(dev, ifup, dev->net, "Reserving %i bytes "
-+                                      "for packet assembly failed.\n",
-+                                      le32_to_cpup(&frame->len));
-+                      dev->net->stats.rx_errors++;
-+              }
-+
-+              return 0;
-+      }
-+
-+      count = le32_to_cpup(&frame->pkt_cnt);
-+
-+      skb_pull(buf, sizeof(*frame));
-+
-+      while (count--) {
-+              if (buf->len < sizeof(*packet)) {
-+                      netif_err(dev, ifup, dev->net, "Packet too short\n");
-+                      goto error;
-+              }
-+
-+              packet = (struct vl600_pkt_hdr *) buf->data;
-+              packet_len = sizeof(*packet) + le32_to_cpup(&packet->len);
-+              if (packet_len > buf->len) {
-+                      netif_err(dev, ifup, dev->net,
-+                                      "Bad packet length stored in header\n");
-+                      goto error;
-+              }
-+
-+              /* Packet header is same size as the ethernet header
-+               * (sizeof(*packet) == sizeof(*ethhdr)), additionally
-+               * the h_proto field is in the same place so we just leave it
-+               * alone and fill in the remaining fields.
-+               */
-+              ethhdr = (struct ethhdr *) skb->data;
-+              if (be16_to_cpup(&ethhdr->h_proto) == ETH_P_ARP &&
-+                              buf->len > 0x26) {
-+                      /* Copy the addresses from packet contents */
-+                      memcpy(ethhdr->h_source,
-+                                      &buf->data[sizeof(*ethhdr) + 0x8],
-+                                      ETH_ALEN);
-+                      memcpy(ethhdr->h_dest,
-+                                      &buf->data[sizeof(*ethhdr) + 0x12],
-+                                      ETH_ALEN);
-+              } else {
-+                      eth_zero_addr(ethhdr->h_source);
-+                      memcpy(ethhdr->h_dest, dev->net->dev_addr, ETH_ALEN);
-+
-+                      /* Inbound IPv6 packets have an IPv4 ethertype (0x800)
-+                       * for some reason.  Peek at the L3 header to check
-+                       * for IPv6 packets, and set the ethertype to IPv6
-+                       * (0x86dd) so Linux can understand it.
-+                       */
-+                      if ((buf->data[sizeof(*ethhdr)] & 0xf0) == 0x60)
-+                              ethhdr->h_proto = htons(ETH_P_IPV6);
-+              }
-+
-+              if (count) {
-+                      /* Not the last packet in this batch */
-+                      clone = skb_clone(buf, GFP_ATOMIC);
-+                      if (!clone)
-+                              goto error;
-+
-+                      skb_trim(clone, packet_len);
-+                      usbnet_skb_return(dev, clone);
-+
-+                      skb_pull(buf, (packet_len + 3) & ~3);
-+              } else {
-+                      skb_trim(buf, packet_len);
-+
-+                      if (s->current_rx_buf) {
-+                              usbnet_skb_return(dev, buf);
-+                              s->current_rx_buf = NULL;
-+                              return 0;
-+                      }
-+
-+                      return 1;
-+              }
-+      }
-+
-+error:
-+      if (s->current_rx_buf) {
-+              dev_kfree_skb_any(s->current_rx_buf);
-+              s->current_rx_buf = NULL;
-+      }
-+      dev->net->stats.rx_errors++;
-+      return 0;
-+}
-+
-+static struct sk_buff *vl600_tx_fixup(struct usbnet *dev,
-+              struct sk_buff *skb, gfp_t flags)
-+{
-+      struct sk_buff *ret;
-+      struct vl600_frame_hdr *frame;
-+      struct vl600_pkt_hdr *packet;
-+      static uint32_t serial = 1;
-+      int orig_len = skb->len - sizeof(struct ethhdr);
-+      int full_len = (skb->len + sizeof(struct vl600_frame_hdr) + 3) & ~3;
-+
-+      frame = (struct vl600_frame_hdr *) skb->data;
-+      if (skb->len > sizeof(*frame) && skb->len == le32_to_cpup(&frame->len))
-+              return skb; /* Already encapsulated? */
-+
-+      if (skb->len < sizeof(struct ethhdr))
-+              /* Drop, device can only deal with ethernet packets */
-+              return NULL;
-+
-+      if (!skb_cloned(skb)) {
-+              int headroom = skb_headroom(skb);
-+              int tailroom = skb_tailroom(skb);
-+
-+              if (tailroom >= full_len - skb->len - sizeof(*frame) &&
-+                              headroom >= sizeof(*frame))
-+                      /* There's enough head and tail room */
-+                      goto encapsulate;
-+
-+              if (headroom + tailroom + skb->len >= full_len) {
-+                      /* There's enough total room, just readjust */
-+                      skb->data = memmove(skb->head + sizeof(*frame),
-+                                      skb->data, skb->len);
-+                      skb_set_tail_pointer(skb, skb->len);
-+                      goto encapsulate;
-+              }
-+      }
-+
-+      /* Alloc a new skb with the required size */
-+      ret = skb_copy_expand(skb, sizeof(struct vl600_frame_hdr), full_len -
-+                      skb->len - sizeof(struct vl600_frame_hdr), flags);
-+      dev_kfree_skb_any(skb);
-+      if (!ret)
-+              return ret;
-+      skb = ret;
-+
-+encapsulate:
-+      /* Packet header is same size as ethernet packet header
-+       * (sizeof(*packet) == sizeof(struct ethhdr)), additionally the
-+       * h_proto field is in the same place so we just leave it alone and
-+       * 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);
-+
-+      frame = (struct vl600_frame_hdr *) skb_push(skb, sizeof(*frame));
-+      memset(frame, 0, sizeof(*frame));
-+      frame->len = cpu_to_le32(full_len);
-+      frame->serial = cpu_to_le32(serial++);
-+      frame->pkt_cnt = cpu_to_le32(1);
-+
-+      if (skb->len < full_len) /* Pad */
-+              skb_put(skb, full_len - skb->len);
-+
-+      return skb;
-+}
-+
-+static const struct driver_info       vl600_info = {
-+      .description    = "LG VL600 modem",
-+      .flags          = FLAG_RX_ASSEMBLE | FLAG_WWAN,
-+      .bind           = vl600_bind,
-+      .unbind         = vl600_unbind,
-+      .status         = usbnet_cdc_status,
-+      .rx_fixup       = vl600_rx_fixup,
-+      .tx_fixup       = vl600_tx_fixup,
-+};
-+
-+static const struct usb_device_id products[] = {
-+      {
-+              USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM,
-+                              USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
-+              .driver_info    = (unsigned long) &vl600_info,
-+      },
-+      {},     /* End */
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver lg_vl600_driver = {
-+      .name           = "lg-vl600",
-+      .id_table       = products,
-+      .probe          = usbnet_probe,
-+      .disconnect     = usbnet_disconnect,
-+      .suspend        = usbnet_suspend,
-+      .resume         = usbnet_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(lg_vl600_driver);
-+
-+MODULE_AUTHOR("Anrzej Zaborowski");
-+MODULE_DESCRIPTION("LG-VL600 modem's ethernet link");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/Makefile backports-4.2.6-1/drivers/net/usb/Makefile
---- backports-4.2.6-1.org/drivers/net/usb/Makefile     2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/Makefile 2016-06-28 14:35:17.991973886 +0200
-@@ -1,39 +1,40 @@
- #
- # Makefile for USB Network drivers
- #
--#
--#obj-$(CPTCFG_USB_CATC)               += catc.o
--#obj-$(CPTCFG_USB_KAWETH)     += kaweth.o
--#obj-$(CPTCFG_USB_PEGASUS)    += pegasus.o
--#obj-$(CPTCFG_USB_RTL8150)    += rtl8150.o
--#obj-$(CPTCFG_USB_RTL8152)    += r8152.o
--#obj-$(CPTCFG_USB_HSO)                += hso.o
--#obj-$(CPTCFG_USB_NET_AX8817X)        += asix.o
--#obj-$(CPTCFG_USB_NET_AX88179_178A)      += ax88179_178a.o
-+
-+obj-$(CPTCFG_USB_CATC)                += catc.o
-+obj-$(CPTCFG_USB_KAWETH)      += kaweth.o
-+obj-$(CPTCFG_USB_PEGASUS)     += pegasus.o
-+obj-$(CPTCFG_USB_RTL8150)     += rtl8150.o
-+obj-$(CPTCFG_USB_RTL8152)     += r8152.o
-+obj-$(CPTCFG_USB_HSO)         += hso.o
-+obj-$(CPTCFG_USB_NET_AX8817X) += asix.o
-+asix-y := asix_devices.o asix_common.o ax88172a.o
-+obj-$(CPTCFG_USB_NET_AX88179_178A)      += ax88179_178a.o
- obj-$(CPTCFG_USB_NET_CDCETHER)        += cdc_ether.o
--#obj-$(CPTCFG_USB_NET_CDC_EEM)        += cdc_eem.o
--#obj-$(CPTCFG_USB_NET_DM9601) += dm9601.o
--#obj-$(CPTCFG_USB_NET_SR9700) += sr9700.o
--#obj-$(CPTCFG_USB_NET_SR9800) += sr9800.o
--#obj-$(CPTCFG_USB_NET_SMSC75XX)       += smsc75xx.o
--#obj-$(CPTCFG_USB_NET_SMSC95XX)       += smsc95xx.o
--#obj-$(CPTCFG_USB_NET_GL620A) += gl620a.o
--#obj-$(CPTCFG_USB_NET_NET1080)        += net1080.o
--#obj-$(CPTCFG_USB_NET_PLUSB)  += plusb.o
-+obj-$(CPTCFG_USB_NET_CDC_EEM) += cdc_eem.o
-+obj-$(CPTCFG_USB_NET_DM9601)  += dm9601.o
-+obj-$(CPTCFG_USB_NET_SR9700)  += sr9700.o
-+obj-$(CPTCFG_USB_NET_SR9800)  += sr9800.o
-+obj-$(CPTCFG_USB_NET_SMSC75XX)        += smsc75xx.o
-+obj-$(CPTCFG_USB_NET_SMSC95XX)        += smsc95xx.o
-+obj-$(CPTCFG_USB_NET_GL620A)  += gl620a.o
-+obj-$(CPTCFG_USB_NET_NET1080) += net1080.o
-+obj-$(CPTCFG_USB_NET_PLUSB)   += plusb.o
- obj-$(CPTCFG_USB_NET_RNDIS_HOST)      += rndis_host.o
--#obj-$(CPTCFG_USB_NET_CDC_SUBSET)     += cdc_subset.o
--#obj-$(CPTCFG_USB_NET_ZAURUS) += zaurus.o
--#obj-$(CPTCFG_USB_NET_MCS7830)        += mcs7830.o
-+obj-$(CPTCFG_USB_NET_CDC_SUBSET)      += cdc_subset.o
-+obj-$(CPTCFG_USB_NET_ZAURUS)  += zaurus.o
-+obj-$(CPTCFG_USB_NET_MCS7830) += mcs7830.o
- obj-$(CPTCFG_USB_USBNET)      += usbnet.o
--#obj-$(CPTCFG_USB_NET_INT51X1)        += int51x1.o
--#obj-$(CPTCFG_USB_CDC_PHONET) += cdc-phonet.o
--#obj-$(CPTCFG_USB_NET_KALMIA) += kalmia.o
--#obj-$(CPTCFG_USB_IPHETH)     += ipheth.o
-+obj-$(CPTCFG_USB_NET_INT51X1) += int51x1.o
-+obj-$(CPTCFG_USB_CDC_PHONET)  += cdc-phonet.o
-+obj-$(CPTCFG_USB_NET_KALMIA)  += kalmia.o
-+obj-$(CPTCFG_USB_IPHETH)      += ipheth.o
- obj-$(CPTCFG_USB_SIERRA_NET)  += sierra_net.o
--#obj-$(CPTCFG_USB_NET_CX82310_ETH)    += cx82310_eth.o
-+obj-$(CPTCFG_USB_NET_CX82310_ETH)     += cx82310_eth.o
- obj-$(CPTCFG_USB_NET_CDC_NCM) += cdc_ncm.o
--#obj-$(CPTCFG_USB_NET_HUAWEI_CDC_NCM) += huawei_cdc_ncm.o
--#obj-$(CPTCFG_USB_VL600)              += lg-vl600.o
-+obj-$(CPTCFG_USB_NET_HUAWEI_CDC_NCM)  += huawei_cdc_ncm.o
-+obj-$(CPTCFG_USB_VL600)               += lg-vl600.o
- obj-$(CPTCFG_USB_NET_QMI_WWAN)        += qmi_wwan.o
- obj-$(CPTCFG_USB_NET_CDC_MBIM)        += cdc_mbim.o
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/mcs7830.c backports-4.2.6-1/drivers/net/usb/mcs7830.c
---- backports-4.2.6-1.org/drivers/net/usb/mcs7830.c    1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/mcs7830.c        2016-06-28 14:35:17.995307218 +0200
-@@ -0,0 +1,643 @@
-+/*
-+ * MOSCHIP MCS7830 based (7730/7830/7832) USB 2.0 Ethernet Devices
-+ *
-+ * based on usbnet.c, asix.c and the vendor provided mcs7830 driver
-+ *
-+ * Copyright (C) 2010 Andreas Mohr <andi@lisas.de>
-+ * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>
-+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
-+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
-+ * Copyright (c) 2002-2003 TiVo Inc.
-+ *
-+ * Definitions gathered from MOSCHIP, Data Sheet_7830DA.pdf (thanks!).
-+ *
-+ * 2010-12-19: add 7832 USB PID ("functionality same as MCS7830"),
-+ *             per active notification by manufacturer
-+ *
-+ * TODO:
-+ * - support HIF_REG_CONFIG_SLEEPMODE/HIF_REG_CONFIG_TXENABLE (via autopm?)
-+ * - implement ethtool_ops get_pauseparam/set_pauseparam
-+ *   via HIF_REG_PAUSE_THRESHOLD (>= revision C only!)
-+ * - implement get_eeprom/[set_eeprom]
-+ * - switch PHY on/off on ifup/ifdown (perhaps in usbnet.c, via MII)
-+ * - mcs7830_get_regs() handling is weird: for rev 2 we return 32 regs,
-+ *   can access only ~ 24, remaining user buffer is uninitialized garbage
-+ * - anything else?
-+ *
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include <linux/crc32.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/slab.h>
-+#include <linux/usb.h>
-+#include <linux/usb/usbnet.h>
-+
-+/* requests */
-+#define MCS7830_RD_BMREQ      (USB_DIR_IN  | USB_TYPE_VENDOR | \
-+                               USB_RECIP_DEVICE)
-+#define MCS7830_WR_BMREQ      (USB_DIR_OUT | USB_TYPE_VENDOR | \
-+                               USB_RECIP_DEVICE)
-+#define MCS7830_RD_BREQ               0x0E
-+#define MCS7830_WR_BREQ               0x0D
-+
-+#define MCS7830_CTRL_TIMEOUT  1000
-+#define MCS7830_MAX_MCAST     64
-+
-+#define MCS7830_VENDOR_ID     0x9710
-+#define MCS7832_PRODUCT_ID    0x7832
-+#define MCS7830_PRODUCT_ID    0x7830
-+#define MCS7730_PRODUCT_ID    0x7730
-+
-+#define SITECOM_VENDOR_ID     0x0DF6
-+#define LN_030_PRODUCT_ID     0x0021
-+
-+#define MCS7830_MII_ADVERTISE (ADVERTISE_PAUSE_CAP | ADVERTISE_100FULL | \
-+                               ADVERTISE_100HALF | ADVERTISE_10FULL | \
-+                               ADVERTISE_10HALF | ADVERTISE_CSMA)
-+
-+/* HIF_REG_XX corresponding index value */
-+enum {
-+      HIF_REG_MULTICAST_HASH                  = 0x00,
-+      HIF_REG_PACKET_GAP1                     = 0x08,
-+      HIF_REG_PACKET_GAP2                     = 0x09,
-+      HIF_REG_PHY_DATA                        = 0x0a,
-+      HIF_REG_PHY_CMD1                        = 0x0c,
-+         HIF_REG_PHY_CMD1_READ                = 0x40,
-+         HIF_REG_PHY_CMD1_WRITE               = 0x20,
-+         HIF_REG_PHY_CMD1_PHYADDR             = 0x01,
-+      HIF_REG_PHY_CMD2                        = 0x0d,
-+         HIF_REG_PHY_CMD2_PEND_FLAG_BIT       = 0x80,
-+         HIF_REG_PHY_CMD2_READY_FLAG_BIT      = 0x40,
-+      HIF_REG_CONFIG                          = 0x0e,
-+      /* hmm, spec sez: "R/W", "Except bit 3" (likely TXENABLE). */
-+         HIF_REG_CONFIG_CFG                   = 0x80,
-+         HIF_REG_CONFIG_SPEED100              = 0x40,
-+         HIF_REG_CONFIG_FULLDUPLEX_ENABLE     = 0x20,
-+         HIF_REG_CONFIG_RXENABLE              = 0x10,
-+         HIF_REG_CONFIG_TXENABLE              = 0x08,
-+         HIF_REG_CONFIG_SLEEPMODE             = 0x04,
-+         HIF_REG_CONFIG_ALLMULTICAST          = 0x02,
-+         HIF_REG_CONFIG_PROMISCUOUS           = 0x01,
-+      HIF_REG_ETHERNET_ADDR                   = 0x0f,
-+      HIF_REG_FRAME_DROP_COUNTER              = 0x15, /* 0..ff; reset: 0 */
-+      HIF_REG_PAUSE_THRESHOLD                 = 0x16,
-+         HIF_REG_PAUSE_THRESHOLD_DEFAULT      = 0,
-+};
-+
-+/* Trailing status byte in Ethernet Rx frame */
-+enum {
-+      MCS7830_RX_SHORT_FRAME          = 0x01, /* < 64 bytes */
-+      MCS7830_RX_LENGTH_ERROR         = 0x02, /* framelen != Ethernet length field */
-+      MCS7830_RX_ALIGNMENT_ERROR      = 0x04, /* non-even number of nibbles */
-+      MCS7830_RX_CRC_ERROR            = 0x08,
-+      MCS7830_RX_LARGE_FRAME          = 0x10, /* > 1518 bytes */
-+      MCS7830_RX_FRAME_CORRECT        = 0x20, /* frame is correct */
-+      /* [7:6] reserved */
-+};
-+
-+struct mcs7830_data {
-+      u8 multi_filter[8];
-+      u8 config;
-+};
-+
-+static const char driver_name[] = "MOSCHIP usb-ethernet driver";
-+
-+static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data)
-+{
-+      return usbnet_read_cmd(dev, MCS7830_RD_BREQ, MCS7830_RD_BMREQ,
-+                              0x0000, index, data, size);
-+}
-+
-+static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, const void *data)
-+{
-+      return usbnet_write_cmd(dev, MCS7830_WR_BREQ, MCS7830_WR_BMREQ,
-+                              0x0000, index, data, size);
-+}
-+
-+static void mcs7830_set_reg_async(struct usbnet *dev, u16 index, u16 size, void *data)
-+{
-+      usbnet_write_cmd_async(dev, MCS7830_WR_BREQ, MCS7830_WR_BMREQ,
-+                              0x0000, index, data, size);
-+}
-+
-+static int mcs7830_hif_get_mac_address(struct usbnet *dev, unsigned char *addr)
-+{
-+      int ret = mcs7830_get_reg(dev, HIF_REG_ETHERNET_ADDR, ETH_ALEN, addr);
-+      if (ret < 0)
-+              return ret;
-+      return 0;
-+}
-+
-+static int mcs7830_hif_set_mac_address(struct usbnet *dev, unsigned char *addr)
-+{
-+      int ret = mcs7830_set_reg(dev, HIF_REG_ETHERNET_ADDR, ETH_ALEN, addr);
-+
-+      if (ret < 0)
-+              return ret;
-+      return 0;
-+}
-+
-+static int mcs7830_set_mac_address(struct net_device *netdev, void *p)
-+{
-+      int ret;
-+      struct usbnet *dev = netdev_priv(netdev);
-+      struct sockaddr *addr = p;
-+
-+      if (netif_running(netdev))
-+              return -EBUSY;
-+
-+      if (!is_valid_ether_addr(addr->sa_data))
-+              return -EADDRNOTAVAIL;
-+
-+      ret = mcs7830_hif_set_mac_address(dev, addr->sa_data);
-+
-+      if (ret < 0)
-+              return ret;
-+
-+      /* it worked --> adopt it on netdev side */
-+      memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-+
-+      return 0;
-+}
-+
-+static int mcs7830_read_phy(struct usbnet *dev, u8 index)
-+{
-+      int ret;
-+      int i;
-+      __le16 val;
-+
-+      u8 cmd[2] = {
-+              HIF_REG_PHY_CMD1_READ | HIF_REG_PHY_CMD1_PHYADDR,
-+              HIF_REG_PHY_CMD2_PEND_FLAG_BIT | index,
-+      };
-+
-+      mutex_lock(&dev->phy_mutex);
-+      /* write the MII command */
-+      ret = mcs7830_set_reg(dev, HIF_REG_PHY_CMD1, 2, cmd);
-+      if (ret < 0)
-+              goto out;
-+
-+      /* wait for the data to become valid, should be within < 1ms */
-+      for (i = 0; i < 10; i++) {
-+              ret = mcs7830_get_reg(dev, HIF_REG_PHY_CMD1, 2, cmd);
-+              if ((ret < 0) || (cmd[1] & HIF_REG_PHY_CMD2_READY_FLAG_BIT))
-+                      break;
-+              ret = -EIO;
-+              msleep(1);
-+      }
-+      if (ret < 0)
-+              goto out;
-+
-+      /* read actual register contents */
-+      ret = mcs7830_get_reg(dev, HIF_REG_PHY_DATA, 2, &val);
-+      if (ret < 0)
-+              goto out;
-+      ret = le16_to_cpu(val);
-+      dev_dbg(&dev->udev->dev, "read PHY reg %02x: %04x (%d tries)\n",
-+              index, val, i);
-+out:
-+      mutex_unlock(&dev->phy_mutex);
-+      return ret;
-+}
-+
-+static int mcs7830_write_phy(struct usbnet *dev, u8 index, u16 val)
-+{
-+      int ret;
-+      int i;
-+      __le16 le_val;
-+
-+      u8 cmd[2] = {
-+              HIF_REG_PHY_CMD1_WRITE | HIF_REG_PHY_CMD1_PHYADDR,
-+              HIF_REG_PHY_CMD2_PEND_FLAG_BIT | (index & 0x1F),
-+      };
-+
-+      mutex_lock(&dev->phy_mutex);
-+
-+      /* write the new register contents */
-+      le_val = cpu_to_le16(val);
-+      ret = mcs7830_set_reg(dev, HIF_REG_PHY_DATA, 2, &le_val);
-+      if (ret < 0)
-+              goto out;
-+
-+      /* write the MII command */
-+      ret = mcs7830_set_reg(dev, HIF_REG_PHY_CMD1, 2, cmd);
-+      if (ret < 0)
-+              goto out;
-+
-+      /* wait for the command to be accepted by the PHY */
-+      for (i = 0; i < 10; i++) {
-+              ret = mcs7830_get_reg(dev, HIF_REG_PHY_CMD1, 2, cmd);
-+              if ((ret < 0) || (cmd[1] & HIF_REG_PHY_CMD2_READY_FLAG_BIT))
-+                      break;
-+              ret = -EIO;
-+              msleep(1);
-+      }
-+      if (ret < 0)
-+              goto out;
-+
-+      ret = 0;
-+      dev_dbg(&dev->udev->dev, "write PHY reg %02x: %04x (%d tries)\n",
-+              index, val, i);
-+out:
-+      mutex_unlock(&dev->phy_mutex);
-+      return ret;
-+}
-+
-+/*
-+ * This algorithm comes from the original mcs7830 version 1.4 driver,
-+ * not sure if it is needed.
-+ */
-+static int mcs7830_set_autoneg(struct usbnet *dev, int ptrUserPhyMode)
-+{
-+      int ret;
-+      /* Enable all media types */
-+      ret = mcs7830_write_phy(dev, MII_ADVERTISE, MCS7830_MII_ADVERTISE);
-+
-+      /* First reset BMCR */
-+      if (!ret)
-+              ret = mcs7830_write_phy(dev, MII_BMCR, 0x0000);
-+      /* Enable Auto Neg */
-+      if (!ret)
-+              ret = mcs7830_write_phy(dev, MII_BMCR, BMCR_ANENABLE);
-+      /* Restart Auto Neg (Keep the Enable Auto Neg Bit Set) */
-+      if (!ret)
-+              ret = mcs7830_write_phy(dev, MII_BMCR,
-+                              BMCR_ANENABLE | BMCR_ANRESTART  );
-+      return ret;
-+}
-+
-+
-+/*
-+ * if we can read register 22, the chip revision is C or higher
-+ */
-+static int mcs7830_get_rev(struct usbnet *dev)
-+{
-+      u8 dummy[2];
-+      int ret;
-+      ret = mcs7830_get_reg(dev, HIF_REG_FRAME_DROP_COUNTER, 2, dummy);
-+      if (ret > 0)
-+              return 2; /* Rev C or later */
-+      return 1; /* earlier revision */
-+}
-+
-+/*
-+ * On rev. C we need to set the pause threshold
-+ */
-+static void mcs7830_rev_C_fixup(struct usbnet *dev)
-+{
-+      u8 pause_threshold = HIF_REG_PAUSE_THRESHOLD_DEFAULT;
-+      int retry;
-+
-+      for (retry = 0; retry < 2; retry++) {
-+              if (mcs7830_get_rev(dev) == 2) {
-+                      dev_info(&dev->udev->dev, "applying rev.C fixup\n");
-+                      mcs7830_set_reg(dev, HIF_REG_PAUSE_THRESHOLD,
-+                                      1, &pause_threshold);
-+              }
-+              msleep(1);
-+      }
-+}
-+
-+static int mcs7830_mdio_read(struct net_device *netdev, int phy_id,
-+                           int location)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      return mcs7830_read_phy(dev, location);
-+}
-+
-+static void mcs7830_mdio_write(struct net_device *netdev, int phy_id,
-+                              int location, int val)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      mcs7830_write_phy(dev, location, val);
-+}
-+
-+static int mcs7830_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
-+}
-+
-+static inline struct mcs7830_data *mcs7830_get_data(struct usbnet *dev)
-+{
-+      return (struct mcs7830_data *)&dev->data;
-+}
-+
-+static void mcs7830_hif_update_multicast_hash(struct usbnet *dev)
-+{
-+      struct mcs7830_data *data = mcs7830_get_data(dev);
-+      mcs7830_set_reg_async(dev, HIF_REG_MULTICAST_HASH,
-+                              sizeof data->multi_filter,
-+                              data->multi_filter);
-+}
-+
-+static void mcs7830_hif_update_config(struct usbnet *dev)
-+{
-+      /* implementation specific to data->config
-+           (argument needs to be heap-based anyway - USB DMA!) */
-+      struct mcs7830_data *data = mcs7830_get_data(dev);
-+      mcs7830_set_reg_async(dev, HIF_REG_CONFIG, 1, &data->config);
-+}
-+
-+static void mcs7830_data_set_multicast(struct net_device *net)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct mcs7830_data *data = mcs7830_get_data(dev);
-+
-+      memset(data->multi_filter, 0, sizeof data->multi_filter);
-+
-+      data->config = HIF_REG_CONFIG_TXENABLE;
-+
-+      /* this should not be needed, but it doesn't work otherwise */
-+      data->config |= HIF_REG_CONFIG_ALLMULTICAST;
-+
-+      if (net->flags & IFF_PROMISC) {
-+              data->config |= HIF_REG_CONFIG_PROMISCUOUS;
-+      } else if (net->flags & IFF_ALLMULTI ||
-+                 netdev_mc_count(net) > MCS7830_MAX_MCAST) {
-+              data->config |= HIF_REG_CONFIG_ALLMULTICAST;
-+      } else if (netdev_mc_empty(net)) {
-+              /* just broadcast and directed */
-+      } else {
-+              /* We use the 20 byte dev->data
-+               * for our 8 byte filter buffer
-+               * to avoid allocating memory that
-+               * is tricky to free later */
-+              struct netdev_hw_addr *ha;
-+              u32 crc_bits;
-+
-+              /* Build the multicast hash filter. */
-+              netdev_for_each_mc_addr(ha, net) {
-+                      crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
-+                      data->multi_filter[crc_bits >> 3] |= 1 << (crc_bits & 7);
-+              }
-+      }
-+}
-+
-+static int mcs7830_apply_base_config(struct usbnet *dev)
-+{
-+      int ret;
-+
-+      /* re-configure known MAC (suspend case etc.) */
-+      ret = mcs7830_hif_set_mac_address(dev, dev->net->dev_addr);
-+      if (ret) {
-+              dev_info(&dev->udev->dev, "Cannot set MAC address\n");
-+              goto out;
-+      }
-+
-+      /* Set up PHY */
-+      ret = mcs7830_set_autoneg(dev, 0);
-+      if (ret) {
-+              dev_info(&dev->udev->dev, "Cannot set autoneg\n");
-+              goto out;
-+      }
-+
-+      mcs7830_hif_update_multicast_hash(dev);
-+      mcs7830_hif_update_config(dev);
-+
-+      mcs7830_rev_C_fixup(dev);
-+      ret = 0;
-+out:
-+      return ret;
-+}
-+
-+/* credits go to asix_set_multicast */
-+static void mcs7830_set_multicast(struct net_device *net)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+
-+      mcs7830_data_set_multicast(net);
-+
-+      mcs7830_hif_update_multicast_hash(dev);
-+      mcs7830_hif_update_config(dev);
-+}
-+
-+static int mcs7830_get_regs_len(struct net_device *net)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+
-+      switch (mcs7830_get_rev(dev)) {
-+      case 1:
-+              return 21;
-+      case 2:
-+              return 32;
-+      }
-+      return 0;
-+}
-+
-+static void mcs7830_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *drvinfo)
-+{
-+      usbnet_get_drvinfo(net, drvinfo);
-+      drvinfo->regdump_len = mcs7830_get_regs_len(net);
-+}
-+
-+static void mcs7830_get_regs(struct net_device *net, struct ethtool_regs *regs, void *data)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+
-+      regs->version = mcs7830_get_rev(dev);
-+      mcs7830_get_reg(dev, 0, regs->len, data);
-+}
-+
-+static const struct ethtool_ops mcs7830_ethtool_ops = {
-+      .get_drvinfo            = mcs7830_get_drvinfo,
-+      .get_regs_len           = mcs7830_get_regs_len,
-+      .get_regs               = mcs7830_get_regs,
-+
-+      /* common usbnet calls */
-+      .get_link               = usbnet_get_link,
-+      .get_msglevel           = usbnet_get_msglevel,
-+      .set_msglevel           = usbnet_set_msglevel,
-+      .get_settings           = usbnet_get_settings,
-+      .set_settings           = usbnet_set_settings,
-+      .nway_reset             = usbnet_nway_reset,
-+};
-+
-+static const struct net_device_ops mcs7830_netdev_ops = {
-+      .ndo_open               = usbnet_open,
-+      .ndo_stop               = usbnet_stop,
-+      .ndo_start_xmit         = usbnet_start_xmit,
-+      .ndo_tx_timeout         = usbnet_tx_timeout,
-+      .ndo_change_mtu         = usbnet_change_mtu,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_do_ioctl           = mcs7830_ioctl,
-+      .ndo_set_rx_mode        = mcs7830_set_multicast,
-+      .ndo_set_mac_address    = mcs7830_set_mac_address,
-+};
-+
-+static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev)
-+{
-+      struct net_device *net = dev->net;
-+      int ret;
-+      int retry;
-+
-+      /* Initial startup: Gather MAC address setting from EEPROM */
-+      ret = -EINVAL;
-+      for (retry = 0; retry < 5 && ret; retry++)
-+              ret = mcs7830_hif_get_mac_address(dev, net->dev_addr);
-+      if (ret) {
-+              dev_warn(&dev->udev->dev, "Cannot read MAC address\n");
-+              goto out;
-+      }
-+
-+      mcs7830_data_set_multicast(net);
-+
-+      ret = mcs7830_apply_base_config(dev);
-+      if (ret)
-+              goto out;
-+
-+      net->ethtool_ops = &mcs7830_ethtool_ops;
-+      net->netdev_ops = &mcs7830_netdev_ops;
-+
-+      /* reserve space for the status byte on rx */
-+      dev->rx_urb_size = ETH_FRAME_LEN + 1;
-+
-+      dev->mii.mdio_read = mcs7830_mdio_read;
-+      dev->mii.mdio_write = mcs7830_mdio_write;
-+      dev->mii.dev = net;
-+      dev->mii.phy_id_mask = 0x3f;
-+      dev->mii.reg_num_mask = 0x1f;
-+      dev->mii.phy_id = *((u8 *) net->dev_addr + 1);
-+
-+      ret = usbnet_get_endpoints(dev, udev);
-+out:
-+      return ret;
-+}
-+
-+/* The chip always appends a status byte that we need to strip */
-+static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      u8 status;
-+
-+      /* This check is no longer done by usbnet */
-+      if (skb->len < dev->net->hard_header_len) {
-+              dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
-+              return 0;
-+      }
-+
-+      skb_trim(skb, skb->len - 1);
-+      status = skb->data[skb->len];
-+
-+      if (status != MCS7830_RX_FRAME_CORRECT) {
-+              dev_dbg(&dev->udev->dev, "rx fixup status %x\n", status);
-+
-+              /* hmm, perhaps usbnet.c already sees a globally visible
-+                 frame error and increments rx_errors on its own already? */
-+              dev->net->stats.rx_errors++;
-+
-+              if (status &    (MCS7830_RX_SHORT_FRAME
-+                              |MCS7830_RX_LENGTH_ERROR
-+                              |MCS7830_RX_LARGE_FRAME))
-+                      dev->net->stats.rx_length_errors++;
-+              if (status & MCS7830_RX_ALIGNMENT_ERROR)
-+                      dev->net->stats.rx_frame_errors++;
-+              if (status & MCS7830_RX_CRC_ERROR)
-+                      dev->net->stats.rx_crc_errors++;
-+      }
-+
-+      return skb->len > 0;
-+}
-+
-+static void mcs7830_status(struct usbnet *dev, struct urb *urb)
-+{
-+      u8 *buf = urb->transfer_buffer;
-+      bool link, link_changed;
-+
-+      if (urb->actual_length < 16)
-+              return;
-+
-+      link = !(buf[1] == 0x20);
-+      link_changed = netif_carrier_ok(dev->net) != link;
-+      if (link_changed) {
-+              usbnet_link_change(dev, link, 0);
-+              netdev_dbg(dev->net, "Link Status is: %d\n", link);
-+      }
-+}
-+
-+static const struct driver_info moschip_info = {
-+      .description    = "MOSCHIP 7830/7832/7730 usb-NET adapter",
-+      .bind           = mcs7830_bind,
-+      .rx_fixup       = mcs7830_rx_fixup,
-+      .flags          = FLAG_ETHER | FLAG_LINK_INTR,
-+      .status         = mcs7830_status,
-+      .in             = 1,
-+      .out            = 2,
-+};
-+
-+static const struct driver_info sitecom_info = {
-+      .description    = "Sitecom LN-30 usb-NET adapter",
-+      .bind           = mcs7830_bind,
-+      .rx_fixup       = mcs7830_rx_fixup,
-+      .flags          = FLAG_ETHER | FLAG_LINK_INTR,
-+      .status         = mcs7830_status,
-+      .in             = 1,
-+      .out            = 2,
-+};
-+
-+static const struct usb_device_id products[] = {
-+      {
-+              USB_DEVICE(MCS7830_VENDOR_ID, MCS7832_PRODUCT_ID),
-+              .driver_info = (unsigned long) &moschip_info,
-+      },
-+      {
-+              USB_DEVICE(MCS7830_VENDOR_ID, MCS7830_PRODUCT_ID),
-+              .driver_info = (unsigned long) &moschip_info,
-+      },
-+      {
-+              USB_DEVICE(MCS7830_VENDOR_ID, MCS7730_PRODUCT_ID),
-+              .driver_info = (unsigned long) &moschip_info,
-+      },
-+      {
-+              USB_DEVICE(SITECOM_VENDOR_ID, LN_030_PRODUCT_ID),
-+              .driver_info = (unsigned long) &sitecom_info,
-+      },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static int mcs7830_reset_resume (struct usb_interface *intf)
-+{
-+      /* YES, this function is successful enough that ethtool -d
-+           does show same output pre-/post-suspend */
-+
-+      struct usbnet           *dev = usb_get_intfdata(intf);
-+
-+      mcs7830_apply_base_config(dev);
-+
-+      usbnet_resume(intf);
-+
-+      return 0;
-+}
-+
-+static struct usb_driver mcs7830_driver = {
-+      .name = driver_name,
-+      .id_table = products,
-+      .probe = usbnet_probe,
-+      .disconnect = usbnet_disconnect,
-+      .suspend = usbnet_suspend,
-+      .resume = usbnet_resume,
-+      .reset_resume = mcs7830_reset_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(mcs7830_driver);
-+
-+MODULE_DESCRIPTION("USB to network adapter MCS7830)");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/net1080.c backports-4.2.6-1/drivers/net/usb/net1080.c
---- backports-4.2.6-1.org/drivers/net/usb/net1080.c    1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/net1080.c        2016-06-28 14:35:17.995307218 +0200
-@@ -0,0 +1,544 @@
-+/*
-+ * Net1080 based USB host-to-host cables
-+ * Copyright (C) 2000-2005 by David Brownell
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+// #define    DEBUG                   // error path messages, extra info
-+// #define    VERBOSE                 // more; success messages
-+
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/workqueue.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/usb/usbnet.h>
-+#include <linux/slab.h>
-+
-+#include <asm/unaligned.h>
-+
-+
-+/*
-+ * Netchip 1080 driver ... http://www.netchip.com
-+ * (Sept 2004:  End-of-life announcement has been sent.)
-+ * Used in (some) LapLink cables
-+ */
-+
-+#define frame_errors  data[1]
-+
-+/*
-+ * NetChip framing of ethernet packets, supporting additional error
-+ * checks for links that may drop bulk packets from inside messages.
-+ * Odd USB length == always short read for last usb packet.
-+ *    - nc_header
-+ *    - Ethernet header (14 bytes)
-+ *    - payload
-+ *    - (optional padding byte, if needed so length becomes odd)
-+ *    - nc_trailer
-+ *
-+ * This framing is to be avoided for non-NetChip devices.
-+ */
-+
-+struct nc_header {            // packed:
-+      __le16  hdr_len;                // sizeof nc_header (LE, all)
-+      __le16  packet_len;             // payload size (including ethhdr)
-+      __le16  packet_id;              // detects dropped packets
-+#define MIN_HEADER    6
-+
-+      // all else is optional, and must start with:
-+      // __le16       vendorId;       // from usb-if
-+      // __le16       productId;
-+} __packed;
-+
-+#define       PAD_BYTE        ((unsigned char)0xAC)
-+
-+struct nc_trailer {
-+      __le16  packet_id;
-+} __packed;
-+
-+// packets may use FLAG_FRAMING_NC and optional pad
-+#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
-+                              + sizeof (struct ethhdr) \
-+                              + (mtu) \
-+                              + 1 \
-+                              + sizeof (struct nc_trailer))
-+
-+#define MIN_FRAMED    FRAMED_SIZE(0)
-+
-+/* packets _could_ be up to 64KB... */
-+#define NC_MAX_PACKET 32767
-+
-+
-+/*
-+ * Zero means no timeout; else, how long a 64 byte bulk packet may be queued
-+ * before the hardware drops it.  If that's done, the driver will need to
-+ * frame network packets to guard against the dropped USB packets.  The win32
-+ * driver sets this for both sides of the link.
-+ */
-+#define       NC_READ_TTL_MS  ((u8)255)       // ms
-+
-+/*
-+ * We ignore most registers and EEPROM contents.
-+ */
-+#define       REG_USBCTL      ((u8)0x04)
-+#define REG_TTL               ((u8)0x10)
-+#define REG_STATUS    ((u8)0x11)
-+
-+/*
-+ * Vendor specific requests to read/write data
-+ */
-+#define       REQUEST_REGISTER        ((u8)0x10)
-+#define       REQUEST_EEPROM          ((u8)0x11)
-+
-+static int
-+nc_vendor_read(struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr)
-+{
-+      int status = usbnet_read_cmd(dev, req,
-+                                   USB_DIR_IN | USB_TYPE_VENDOR |
-+                                   USB_RECIP_DEVICE,
-+                                   0, regnum, retval_ptr,
-+                                   sizeof *retval_ptr);
-+      if (status > 0)
-+              status = 0;
-+      if (!status)
-+              le16_to_cpus(retval_ptr);
-+      return status;
-+}
-+
-+static inline int
-+nc_register_read(struct usbnet *dev, u8 regnum, u16 *retval_ptr)
-+{
-+      return nc_vendor_read(dev, REQUEST_REGISTER, regnum, retval_ptr);
-+}
-+
-+// no retval ... can become async, usable in_interrupt()
-+static void
-+nc_vendor_write(struct usbnet *dev, u8 req, u8 regnum, u16 value)
-+{
-+      usbnet_write_cmd(dev, req,
-+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+                       value, regnum, NULL, 0);
-+}
-+
-+static inline void
-+nc_register_write(struct usbnet *dev, u8 regnum, u16 value)
-+{
-+      nc_vendor_write(dev, REQUEST_REGISTER, regnum, value);
-+}
-+
-+
-+#if 0
-+static void nc_dump_registers(struct usbnet *dev)
-+{
-+      u8      reg;
-+      u16     *vp = kmalloc(sizeof (u16));
-+
-+      if (!vp)
-+              return;
-+
-+      netdev_dbg(dev->net, "registers:\n");
-+      for (reg = 0; reg < 0x20; reg++) {
-+              int retval;
-+
-+              // reading some registers is trouble
-+              if (reg >= 0x08 && reg <= 0xf)
-+                      continue;
-+              if (reg >= 0x12 && reg <= 0x1e)
-+                      continue;
-+
-+              retval = nc_register_read(dev, reg, vp);
-+              if (retval < 0)
-+                      netdev_dbg(dev->net, "reg [0x%x] ==> error %d\n",
-+                                 reg, retval);
-+              else
-+                      netdev_dbg(dev->net, "reg [0x%x] = 0x%x\n", reg, *vp);
-+      }
-+      kfree(vp);
-+}
-+#endif
-+
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/*
-+ * Control register
-+ */
-+
-+#define       USBCTL_WRITABLE_MASK    0x1f0f
-+// bits 15-13 reserved, r/o
-+#define       USBCTL_ENABLE_LANG      (1 << 12)
-+#define       USBCTL_ENABLE_MFGR      (1 << 11)
-+#define       USBCTL_ENABLE_PROD      (1 << 10)
-+#define       USBCTL_ENABLE_SERIAL    (1 << 9)
-+#define       USBCTL_ENABLE_DEFAULTS  (1 << 8)
-+// bits 7-4 reserved, r/o
-+#define       USBCTL_FLUSH_OTHER      (1 << 3)
-+#define       USBCTL_FLUSH_THIS       (1 << 2)
-+#define       USBCTL_DISCONN_OTHER    (1 << 1)
-+#define       USBCTL_DISCONN_THIS     (1 << 0)
-+
-+static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl)
-+{
-+      netif_dbg(dev, link, dev->net,
-+                "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s; this%s%s; other%s%s; r/o 0x%x\n",
-+                dev->udev->bus->bus_name, dev->udev->devpath,
-+                usbctl,
-+                (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "",
-+                (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "",
-+                (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "",
-+                (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "",
-+                (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "",
-+
-+                (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "",
-+                (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "",
-+
-+                (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "",
-+                (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "",
-+
-+                usbctl & ~USBCTL_WRITABLE_MASK);
-+}
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/*
-+ * Status register
-+ */
-+
-+#define       STATUS_PORT_A           (1 << 15)
-+
-+#define       STATUS_CONN_OTHER       (1 << 14)
-+#define       STATUS_SUSPEND_OTHER    (1 << 13)
-+#define       STATUS_MAILBOX_OTHER    (1 << 12)
-+#define       STATUS_PACKETS_OTHER(n) (((n) >> 8) & 0x03)
-+
-+#define       STATUS_CONN_THIS        (1 << 6)
-+#define       STATUS_SUSPEND_THIS     (1 << 5)
-+#define       STATUS_MAILBOX_THIS     (1 << 4)
-+#define       STATUS_PACKETS_THIS(n)  (((n) >> 0) & 0x03)
-+
-+#define       STATUS_UNSPEC_MASK      0x0c8c
-+#define       STATUS_NOISE_MASK       ((u16)~(0x0303|STATUS_UNSPEC_MASK))
-+
-+
-+static inline void nc_dump_status(struct usbnet *dev, u16 status)
-+{
-+      netif_dbg(dev, link, dev->net,
-+                "net1080 %s-%s status 0x%x: this (%c) PKT=%d%s%s%s; other PKT=%d%s%s%s; unspec 0x%x\n",
-+                dev->udev->bus->bus_name, dev->udev->devpath,
-+                status,
-+
-+                // XXX the packet counts don't seem right
-+                // (1 at reset, not 0); maybe UNSPEC too
-+
-+                (status & STATUS_PORT_A) ? 'A' : 'B',
-+                STATUS_PACKETS_THIS(status),
-+                (status & STATUS_CONN_THIS) ? " CON" : "",
-+                (status & STATUS_SUSPEND_THIS) ? " SUS" : "",
-+                (status & STATUS_MAILBOX_THIS) ? " MBOX" : "",
-+
-+                STATUS_PACKETS_OTHER(status),
-+                (status & STATUS_CONN_OTHER) ? " CON" : "",
-+                (status & STATUS_SUSPEND_OTHER) ? " SUS" : "",
-+                (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "",
-+
-+                status & STATUS_UNSPEC_MASK);
-+}
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/*
-+ * TTL register
-+ */
-+
-+#define       TTL_THIS(ttl)   (0x00ff & ttl)
-+#define       TTL_OTHER(ttl)  (0x00ff & (ttl >> 8))
-+#define MK_TTL(this,other)    ((u16)(((other)<<8)|(0x00ff&(this))))
-+
-+static inline void nc_dump_ttl(struct usbnet *dev, u16 ttl)
-+{
-+      netif_dbg(dev, link, dev->net, "net1080 %s-%s ttl 0x%x this = %d, other = %d\n",
-+                dev->udev->bus->bus_name, dev->udev->devpath,
-+                ttl, TTL_THIS(ttl), TTL_OTHER(ttl));
-+}
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static int net1080_reset(struct usbnet *dev)
-+{
-+      u16             usbctl, status, ttl;
-+      u16             vp;
-+      int             retval;
-+
-+      // nc_dump_registers(dev);
-+
-+      if ((retval = nc_register_read(dev, REG_STATUS, &vp)) < 0) {
-+              netdev_dbg(dev->net, "can't read %s-%s status: %d\n",
-+                         dev->udev->bus->bus_name, dev->udev->devpath, retval);
-+              goto done;
-+      }
-+      status = vp;
-+      nc_dump_status(dev, status);
-+
-+      if ((retval = nc_register_read(dev, REG_USBCTL, &vp)) < 0) {
-+              netdev_dbg(dev->net, "can't read USBCTL, %d\n", retval);
-+              goto done;
-+      }
-+      usbctl = vp;
-+      nc_dump_usbctl(dev, usbctl);
-+
-+      nc_register_write(dev, REG_USBCTL,
-+                      USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
-+
-+      if ((retval = nc_register_read(dev, REG_TTL, &vp)) < 0) {
-+              netdev_dbg(dev->net, "can't read TTL, %d\n", retval);
-+              goto done;
-+      }
-+      ttl = vp;
-+      // nc_dump_ttl(dev, ttl);
-+
-+      nc_register_write(dev, REG_TTL,
-+                      MK_TTL(NC_READ_TTL_MS, TTL_OTHER(ttl)) );
-+      netdev_dbg(dev->net, "assigned TTL, %d ms\n", NC_READ_TTL_MS);
-+
-+      netif_info(dev, link, dev->net, "port %c, peer %sconnected\n",
-+                 (status & STATUS_PORT_A) ? 'A' : 'B',
-+                 (status & STATUS_CONN_OTHER) ? "" : "dis");
-+      retval = 0;
-+
-+done:
-+      return retval;
-+}
-+
-+static int net1080_check_connect(struct usbnet *dev)
-+{
-+      int                     retval;
-+      u16                     status;
-+      u16                     vp;
-+
-+      retval = nc_register_read(dev, REG_STATUS, &vp);
-+      status = vp;
-+      if (retval != 0) {
-+              netdev_dbg(dev->net, "net1080_check_conn read - %d\n", retval);
-+              return retval;
-+      }
-+      if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER)
-+              return -ENOLINK;
-+      return 0;
-+}
-+
-+static void nc_ensure_sync(struct usbnet *dev)
-+{
-+      if (++dev->frame_errors <= 5)
-+              return;
-+
-+      if (usbnet_write_cmd_async(dev, REQUEST_REGISTER,
-+                                      USB_DIR_OUT | USB_TYPE_VENDOR |
-+                                      USB_RECIP_DEVICE,
-+                                      USBCTL_FLUSH_THIS |
-+                                      USBCTL_FLUSH_OTHER,
-+                                      REG_USBCTL, NULL, 0))
-+              return;
-+
-+      netif_dbg(dev, rx_err, dev->net,
-+                "flush net1080; too many framing errors\n");
-+      dev->frame_errors = 0;
-+}
-+
-+static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      struct nc_header        *header;
-+      struct nc_trailer       *trailer;
-+      u16                     hdr_len, packet_len;
-+
-+      /* This check is no longer done by usbnet */
-+      if (skb->len < dev->net->hard_header_len)
-+              return 0;
-+
-+      if (!(skb->len & 0x01)) {
-+              netdev_dbg(dev->net, "rx framesize %d range %d..%d mtu %d\n",
-+                         skb->len, dev->net->hard_header_len, dev->hard_mtu,
-+                         dev->net->mtu);
-+              dev->net->stats.rx_frame_errors++;
-+              nc_ensure_sync(dev);
-+              return 0;
-+      }
-+
-+      header = (struct nc_header *) skb->data;
-+      hdr_len = le16_to_cpup(&header->hdr_len);
-+      packet_len = le16_to_cpup(&header->packet_len);
-+      if (FRAMED_SIZE(packet_len) > NC_MAX_PACKET) {
-+              dev->net->stats.rx_frame_errors++;
-+              netdev_dbg(dev->net, "packet too big, %d\n", packet_len);
-+              nc_ensure_sync(dev);
-+              return 0;
-+      } else if (hdr_len < MIN_HEADER) {
-+              dev->net->stats.rx_frame_errors++;
-+              netdev_dbg(dev->net, "header too short, %d\n", hdr_len);
-+              nc_ensure_sync(dev);
-+              return 0;
-+      } else if (hdr_len > MIN_HEADER) {
-+              // out of band data for us?
-+              netdev_dbg(dev->net, "header OOB, %d bytes\n", hdr_len - MIN_HEADER);
-+              nc_ensure_sync(dev);
-+              // switch (vendor/product ids) { ... }
-+      }
-+      skb_pull(skb, hdr_len);
-+
-+      trailer = (struct nc_trailer *)
-+              (skb->data + skb->len - sizeof *trailer);
-+      skb_trim(skb, skb->len - sizeof *trailer);
-+
-+      if ((packet_len & 0x01) == 0) {
-+              if (skb->data [packet_len] != PAD_BYTE) {
-+                      dev->net->stats.rx_frame_errors++;
-+                      netdev_dbg(dev->net, "bad pad\n");
-+                      return 0;
-+              }
-+              skb_trim(skb, skb->len - 1);
-+      }
-+      if (skb->len != packet_len) {
-+              dev->net->stats.rx_frame_errors++;
-+              netdev_dbg(dev->net, "bad packet len %d (expected %d)\n",
-+                         skb->len, packet_len);
-+              nc_ensure_sync(dev);
-+              return 0;
-+      }
-+      if (header->packet_id != get_unaligned(&trailer->packet_id)) {
-+              dev->net->stats.rx_fifo_errors++;
-+              netdev_dbg(dev->net, "(2+ dropped) rx packet_id mismatch 0x%x 0x%x\n",
-+                         le16_to_cpu(header->packet_id),
-+                         le16_to_cpu(trailer->packet_id));
-+              return 0;
-+      }
-+#if 0
-+      netdev_dbg(dev->net, "frame <rx h %d p %d id %d\n", header->hdr_len,
-+                 header->packet_len, header->packet_id);
-+#endif
-+      dev->frame_errors = 0;
-+      return 1;
-+}
-+
-+static struct sk_buff *
-+net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
-+{
-+      struct sk_buff          *skb2;
-+      struct nc_header        *header = NULL;
-+      struct nc_trailer       *trailer = NULL;
-+      int                     padlen = sizeof (struct nc_trailer);
-+      int                     len = skb->len;
-+
-+      if (!((len + padlen + sizeof (struct nc_header)) & 0x01))
-+              padlen++;
-+      if (!skb_cloned(skb)) {
-+              int     headroom = skb_headroom(skb);
-+              int     tailroom = skb_tailroom(skb);
-+
-+              if (padlen <= tailroom &&
-+                  sizeof(struct nc_header) <= headroom)
-+                      /* There's enough head and tail room */
-+                      goto encapsulate;
-+
-+              if ((sizeof (struct nc_header) + padlen) <
-+                              (headroom + tailroom)) {
-+                      /* There's enough total room, so just readjust */
-+                      skb->data = memmove(skb->head
-+                                              + sizeof (struct nc_header),
-+                                          skb->data, skb->len);
-+                      skb_set_tail_pointer(skb, len);
-+                      goto encapsulate;
-+              }
-+      }
-+
-+      /* Create a new skb to use with the correct size */
-+      skb2 = skb_copy_expand(skb,
-+                              sizeof (struct nc_header),
-+                              padlen,
-+                              flags);
-+      dev_kfree_skb_any(skb);
-+      if (!skb2)
-+              return skb2;
-+      skb = skb2;
-+
-+encapsulate:
-+      /* header first */
-+      header = (struct nc_header *) skb_push(skb, sizeof *header);
-+      header->hdr_len = cpu_to_le16(sizeof (*header));
-+      header->packet_len = cpu_to_le16(len);
-+      header->packet_id = cpu_to_le16((u16)dev->xid++);
-+
-+      /* maybe pad; then trailer */
-+      if (!((skb->len + sizeof *trailer) & 0x01))
-+              *skb_put(skb, 1) = PAD_BYTE;
-+      trailer = (struct nc_trailer *) skb_put(skb, sizeof *trailer);
-+      put_unaligned(header->packet_id, &trailer->packet_id);
-+#if 0
-+      netdev_dbg(dev->net, "frame >tx h %d p %d id %d\n",
-+                 header->hdr_len, header->packet_len,
-+                 header->packet_id);
-+#endif
-+      return skb;
-+}
-+
-+static int net1080_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      unsigned        extra = sizeof (struct nc_header)
-+                              + 1
-+                              + sizeof (struct nc_trailer);
-+
-+      dev->net->hard_header_len += extra;
-+      dev->rx_urb_size = dev->net->hard_header_len + dev->net->mtu;
-+      dev->hard_mtu = NC_MAX_PACKET;
-+      return usbnet_get_endpoints (dev, intf);
-+}
-+
-+static const struct driver_info       net1080_info = {
-+      .description =  "NetChip TurboCONNECT",
-+      .flags =        FLAG_POINTTOPOINT | FLAG_FRAMING_NC,
-+      .bind =         net1080_bind,
-+      .reset =        net1080_reset,
-+      .check_connect = net1080_check_connect,
-+      .rx_fixup =     net1080_rx_fixup,
-+      .tx_fixup =     net1080_tx_fixup,
-+};
-+
-+static const struct usb_device_id     products [] = {
-+{
-+      USB_DEVICE(0x0525, 0x1080),     // NetChip ref design
-+      .driver_info =  (unsigned long) &net1080_info,
-+}, {
-+      USB_DEVICE(0x06D0, 0x0622),     // Laplink Gold
-+      .driver_info =  (unsigned long) &net1080_info,
-+},
-+      { },            // END
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver net1080_driver = {
-+      .name =         "net1080",
-+      .id_table =     products,
-+      .probe =        usbnet_probe,
-+      .disconnect =   usbnet_disconnect,
-+      .suspend =      usbnet_suspend,
-+      .resume =       usbnet_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(net1080_driver);
-+
-+MODULE_AUTHOR("David Brownell");
-+MODULE_DESCRIPTION("NetChip 1080 based USB Host-to-Host Links");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/pegasus.c backports-4.2.6-1/drivers/net/usb/pegasus.c
---- backports-4.2.6-1.org/drivers/net/usb/pegasus.c    1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/pegasus.c        2016-06-28 14:35:17.995307218 +0200
-@@ -0,0 +1,1335 @@
-+/*
-+ *  Copyright (c) 1999-2013 Petko Manolov (petkan@nucleusys.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.
-+ *
-+ *    ChangeLog:
-+ *            ....    Most of the time spent on reading sources & docs.
-+ *            v0.2.x  First official release for the Linux kernel.
-+ *            v0.3.0  Beutified and structured, some bugs fixed.
-+ *            v0.3.x  URBifying bulk requests and bugfixing. First relatively
-+ *                    stable release. Still can touch device's registers only
-+ *                    from top-halves.
-+ *            v0.4.0  Control messages remained unurbified are now URBs.
-+ *                    Now we can touch the HW at any time.
-+ *            v0.4.9  Control urbs again use process context to wait. Argh...
-+ *                    Some long standing bugs (enable_net_traffic) fixed.
-+ *                    Also nasty trick about resubmiting control urb from
-+ *                    interrupt context used. Please let me know how it
-+ *                    behaves. Pegasus II support added since this version.
-+ *                    TODO: suppressing HCD warnings spewage on disconnect.
-+ *            v0.4.13 Ethernet address is now set at probe(), not at open()
-+ *                    time as this seems to break dhcpd.
-+ *            v0.5.0  branch to 2.5.x kernels
-+ *            v0.5.1  ethtool support added
-+ *            v0.5.5  rx socket buffers are in a pool and the their allocation
-+ *                    is out of the interrupt routine.
-+ *            ...
-+ *            v0.9.3  simplified [get|set]_register(s), async update registers
-+ *                    logic revisited, receive skb_pool removed.
-+ */
-+
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/module.h>
-+#include <asm/byteorder.h>
-+#include <asm/uaccess.h>
-+#include "pegasus.h"
-+
-+/*
-+ * Version Information
-+ */
-+#define DRIVER_VERSION "v0.9.3 (2013/04/25)"
-+#define DRIVER_AUTHOR "Petko Manolov <petkan@nucleusys.com>"
-+#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
-+
-+static const char driver_name[] = "pegasus";
-+
-+#undef        PEGASUS_WRITE_EEPROM
-+#define       BMSR_MEDIA      (BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \
-+                      BMSR_100FULL | BMSR_ANEGCAPABLE)
-+
-+static bool loopback;
-+static bool mii_mode;
-+static char *devid;
-+
-+static struct usb_eth_dev usb_dev_id[] = {
-+#define       PEGASUS_DEV(pn, vid, pid, flags)        \
-+      {.name = pn, .vendor = vid, .device = pid, .private = flags},
-+#define PEGASUS_DEV_CLASS(pn, vid, pid, dclass, flags) \
-+      PEGASUS_DEV(pn, vid, pid, flags)
-+#include "pegasus.h"
-+#undef        PEGASUS_DEV
-+#undef        PEGASUS_DEV_CLASS
-+      {NULL, 0, 0, 0},
-+      {NULL, 0, 0, 0}
-+};
-+
-+static struct usb_device_id pegasus_ids[] = {
-+#define       PEGASUS_DEV(pn, vid, pid, flags) \
-+      {.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = vid, .idProduct = pid},
-+/*
-+ * The Belkin F8T012xx1 bluetooth adaptor has the same vendor and product
-+ * IDs as the Belkin F5D5050, so we need to teach the pegasus driver to
-+ * ignore adaptors belonging to the "Wireless" class 0xE0. For this one
-+ * case anyway, seeing as the pegasus is for "Wired" adaptors.
-+ */
-+#define PEGASUS_DEV_CLASS(pn, vid, pid, dclass, flags) \
-+      {.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_CLASS), \
-+      .idVendor = vid, .idProduct = pid, .bDeviceClass = dclass},
-+#include "pegasus.h"
-+#undef        PEGASUS_DEV
-+#undef        PEGASUS_DEV_CLASS
-+      {},
-+      {}
-+};
-+
-+MODULE_AUTHOR(DRIVER_AUTHOR);
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_LICENSE("GPL");
-+module_param(loopback, bool, 0);
-+module_param(mii_mode, bool, 0);
-+module_param(devid, charp, 0);
-+MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
-+MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
-+MODULE_PARM_DESC(devid, "The format is: 'DEV_name:VendorID:DeviceID:Flags'");
-+
-+/* use ethtool to change the level for any given device */
-+static int msg_level = -1;
-+module_param(msg_level, int, 0);
-+MODULE_PARM_DESC(msg_level, "Override default message level");
-+
-+MODULE_DEVICE_TABLE(usb, pegasus_ids);
-+static const struct net_device_ops pegasus_netdev_ops;
-+
-+/*****/
-+
-+static void async_ctrl_callback(struct urb *urb)
-+{
-+      struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
-+      int status = urb->status;
-+
-+      if (status < 0)
-+              dev_dbg(&urb->dev->dev, "%s failed with %d", __func__, status);
-+      kfree(req);
-+      usb_free_urb(urb);
-+}
-+
-+static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
-+{
-+      int ret;
-+
-+      ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0),
-+                            PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0,
-+                            indx, data, size, 1000);
-+      if (ret < 0)
-+              netif_dbg(pegasus, drv, pegasus->net,
-+                        "%s returned %d\n", __func__, ret);
-+      return ret;
-+}
-+
-+static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
-+{
-+      int ret;
-+
-+      ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
-+                            PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0,
-+                            indx, data, size, 100);
-+      if (ret < 0)
-+              netif_dbg(pegasus, drv, pegasus->net,
-+                        "%s returned %d\n", __func__, ret);
-+      return ret;
-+}
-+
-+static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data)
-+{
-+      int ret;
-+
-+      ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
-+                            PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data,
-+                            indx, &data, 1, 1000);
-+      if (ret < 0)
-+              netif_dbg(pegasus, drv, pegasus->net,
-+                        "%s returned %d\n", __func__, ret);
-+      return ret;
-+}
-+
-+static int update_eth_regs_async(pegasus_t *pegasus)
-+{
-+      int ret = -ENOMEM;
-+      struct urb *async_urb;
-+      struct usb_ctrlrequest *req;
-+
-+      req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
-+      if (req == NULL)
-+              return ret;
-+
-+      async_urb = usb_alloc_urb(0, GFP_ATOMIC);
-+      if (async_urb == NULL) {
-+              kfree(req);
-+              return ret;
-+      }
-+      req->bRequestType = PEGASUS_REQT_WRITE;
-+      req->bRequest = PEGASUS_REQ_SET_REGS;
-+      req->wValue = cpu_to_le16(0);
-+      req->wIndex = cpu_to_le16(EthCtrl0);
-+      req->wLength = cpu_to_le16(3);
-+
-+      usb_fill_control_urb(async_urb, pegasus->usb,
-+                           usb_sndctrlpipe(pegasus->usb, 0), (void *)req,
-+                           pegasus->eth_regs, 3, async_ctrl_callback, req);
-+
-+      ret = usb_submit_urb(async_urb, GFP_ATOMIC);
-+      if (ret) {
-+              if (ret == -ENODEV)
-+                      netif_device_detach(pegasus->net);
-+              netif_err(pegasus, drv, pegasus->net,
-+                        "%s returned %d\n", __func__, ret);
-+      }
-+      return ret;
-+}
-+
-+static int __mii_op(pegasus_t *p, __u8 phy, __u8 indx, __u16 *regd, __u8 cmd)
-+{
-+      int i;
-+      __u8 data[4] = { phy, 0, 0, indx };
-+      __le16 regdi;
-+      int ret = -ETIMEDOUT;
-+
-+      if (cmd & PHY_WRITE) {
-+              __le16 *t = (__le16 *) & data[1];
-+              *t = cpu_to_le16(*regd);
-+      }
-+      set_register(p, PhyCtrl, 0);
-+      set_registers(p, PhyAddr, sizeof(data), data);
-+      set_register(p, PhyCtrl, (indx | cmd));
-+      for (i = 0; i < REG_TIMEOUT; i++) {
-+              ret = get_registers(p, PhyCtrl, 1, data);
-+              if (ret < 0)
-+                      goto fail;
-+              if (data[0] & PHY_DONE)
-+                      break;
-+      }
-+      if (i >= REG_TIMEOUT)
-+              goto fail;
-+      if (cmd & PHY_READ) {
-+              ret = get_registers(p, PhyData, 2, &regdi);
-+              *regd = le16_to_cpu(regdi);
-+              return ret;
-+      }
-+      return 0;
-+fail:
-+      netif_dbg(p, drv, p->net, "%s failed\n", __func__);
-+      return ret;
-+}
-+
-+/* Returns non-negative int on success, error on failure */
-+static int read_mii_word(pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 *regd)
-+{
-+      return __mii_op(pegasus, phy, indx, regd, PHY_READ);
-+}
-+
-+/* Returns zero on success, error on failure */
-+static int write_mii_word(pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 *regd)
-+{
-+      return __mii_op(pegasus, phy, indx, regd, PHY_WRITE);
-+}
-+
-+static int mdio_read(struct net_device *dev, int phy_id, int loc)
-+{
-+      pegasus_t *pegasus = netdev_priv(dev);
-+      u16 res;
-+
-+      read_mii_word(pegasus, phy_id, loc, &res);
-+      return (int)res;
-+}
-+
-+static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
-+{
-+      pegasus_t *pegasus = netdev_priv(dev);
-+      u16 data = val;
-+
-+      write_mii_word(pegasus, phy_id, loc, &data);
-+}
-+
-+static int read_eprom_word(pegasus_t *pegasus, __u8 index, __u16 *retdata)
-+{
-+      int i;
-+      __u8 tmp;
-+      __le16 retdatai;
-+      int ret;
-+
-+      set_register(pegasus, EpromCtrl, 0);
-+      set_register(pegasus, EpromOffset, index);
-+      set_register(pegasus, EpromCtrl, EPROM_READ);
-+
-+      for (i = 0; i < REG_TIMEOUT; i++) {
-+              ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
-+              if (tmp & EPROM_DONE)
-+                      break;
-+              if (ret == -ESHUTDOWN)
-+                      goto fail;
-+      }
-+      if (i >= REG_TIMEOUT)
-+              goto fail;
-+
-+      ret = get_registers(pegasus, EpromData, 2, &retdatai);
-+      *retdata = le16_to_cpu(retdatai);
-+      return ret;
-+
-+fail:
-+      netif_warn(pegasus, drv, pegasus->net, "%s failed\n", __func__);
-+      return -ETIMEDOUT;
-+}
-+
-+#ifdef        PEGASUS_WRITE_EEPROM
-+static inline void enable_eprom_write(pegasus_t *pegasus)
-+{
-+      __u8 tmp;
-+
-+      get_registers(pegasus, EthCtrl2, 1, &tmp);
-+      set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
-+}
-+
-+static inline void disable_eprom_write(pegasus_t *pegasus)
-+{
-+      __u8 tmp;
-+
-+      get_registers(pegasus, EthCtrl2, 1, &tmp);
-+      set_register(pegasus, EpromCtrl, 0);
-+      set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
-+}
-+
-+static int write_eprom_word(pegasus_t *pegasus, __u8 index, __u16 data)
-+{
-+      int i;
-+      __u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE };
-+      int ret;
-+      __le16 le_data = cpu_to_le16(data);
-+
-+      set_registers(pegasus, EpromOffset, 4, d);
-+      enable_eprom_write(pegasus);
-+      set_register(pegasus, EpromOffset, index);
-+      set_registers(pegasus, EpromData, 2, &le_data);
-+      set_register(pegasus, EpromCtrl, EPROM_WRITE);
-+
-+      for (i = 0; i < REG_TIMEOUT; i++) {
-+              ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
-+              if (ret == -ESHUTDOWN)
-+                      goto fail;
-+              if (tmp & EPROM_DONE)
-+                      break;
-+      }
-+      disable_eprom_write(pegasus);
-+      if (i >= REG_TIMEOUT)
-+              goto fail;
-+
-+      return ret;
-+
-+fail:
-+      netif_warn(pegasus, drv, pegasus->net, "%s failed\n", __func__);
-+      return -ETIMEDOUT;
-+}
-+#endif                                /* PEGASUS_WRITE_EEPROM */
-+
-+static inline void get_node_id(pegasus_t *pegasus, __u8 *id)
-+{
-+      int i;
-+      __u16 w16;
-+
-+      for (i = 0; i < 3; i++) {
-+              read_eprom_word(pegasus, i, &w16);
-+              ((__le16 *) id)[i] = cpu_to_le16(w16);
-+      }
-+}
-+
-+static void set_ethernet_addr(pegasus_t *pegasus)
-+{
-+      __u8 node_id[6];
-+
-+      if (pegasus->features & PEGASUS_II) {
-+              get_registers(pegasus, 0x10, sizeof(node_id), node_id);
-+      } else {
-+              get_node_id(pegasus, node_id);
-+              set_registers(pegasus, EthID, sizeof(node_id), node_id);
-+      }
-+      memcpy(pegasus->net->dev_addr, node_id, sizeof(node_id));
-+}
-+
-+static inline int reset_mac(pegasus_t *pegasus)
-+{
-+      __u8 data = 0x8;
-+      int i;
-+
-+      set_register(pegasus, EthCtrl1, data);
-+      for (i = 0; i < REG_TIMEOUT; i++) {
-+              get_registers(pegasus, EthCtrl1, 1, &data);
-+              if (~data & 0x08) {
-+                      if (loopback)
-+                              break;
-+                      if (mii_mode && (pegasus->features & HAS_HOME_PNA))
-+                              set_register(pegasus, Gpio1, 0x34);
-+                      else
-+                              set_register(pegasus, Gpio1, 0x26);
-+                      set_register(pegasus, Gpio0, pegasus->features);
-+                      set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
-+                      break;
-+              }
-+      }
-+      if (i == REG_TIMEOUT)
-+              return -ETIMEDOUT;
-+
-+      if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
-+          usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
-+              set_register(pegasus, Gpio0, 0x24);
-+              set_register(pegasus, Gpio0, 0x26);
-+      }
-+      if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) {
-+              __u16 auxmode;
-+              read_mii_word(pegasus, 3, 0x1b, &auxmode);
-+              auxmode |= 4;
-+              write_mii_word(pegasus, 3, 0x1b, &auxmode);
-+      }
-+
-+      return 0;
-+}
-+
-+static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
-+{
-+      __u16 linkpart;
-+      __u8 data[4];
-+      pegasus_t *pegasus = netdev_priv(dev);
-+      int ret;
-+
-+      read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart);
-+      data[0] = 0xc9;
-+      data[1] = 0;
-+      if (linkpart & (ADVERTISE_100FULL | ADVERTISE_10FULL))
-+              data[1] |= 0x20;        /* set full duplex */
-+      if (linkpart & (ADVERTISE_100FULL | ADVERTISE_100HALF))
-+              data[1] |= 0x10;        /* set 100 Mbps */
-+      if (mii_mode)
-+              data[1] = 0;
-+      data[2] = loopback ? 0x09 : 0x01;
-+
-+      memcpy(pegasus->eth_regs, data, sizeof(data));
-+      ret = set_registers(pegasus, EthCtrl0, 3, data);
-+
-+      if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
-+          usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS2 ||
-+          usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
-+              u16 auxmode;
-+              read_mii_word(pegasus, 0, 0x1b, &auxmode);
-+              auxmode |= 4;
-+              write_mii_word(pegasus, 0, 0x1b, &auxmode);
-+      }
-+
-+      return ret;
-+}
-+
-+static void read_bulk_callback(struct urb *urb)
-+{
-+      pegasus_t *pegasus = urb->context;
-+      struct net_device *net;
-+      int rx_status, count = urb->actual_length;
-+      int status = urb->status;
-+      u8 *buf = urb->transfer_buffer;
-+      __u16 pkt_len;
-+
-+      if (!pegasus)
-+              return;
-+
-+      net = pegasus->net;
-+      if (!netif_device_present(net) || !netif_running(net))
-+              return;
-+
-+      switch (status) {
-+      case 0:
-+              break;
-+      case -ETIME:
-+              netif_dbg(pegasus, rx_err, net, "reset MAC\n");
-+              pegasus->flags &= ~PEGASUS_RX_BUSY;
-+              break;
-+      case -EPIPE:            /* stall, or disconnect from TT */
-+              /* FIXME schedule work to clear the halt */
-+              netif_warn(pegasus, rx_err, net, "no rx stall recovery\n");
-+              return;
-+      case -ENOENT:
-+      case -ECONNRESET:
-+      case -ESHUTDOWN:
-+              netif_dbg(pegasus, ifdown, net, "rx unlink, %d\n", status);
-+              return;
-+      default:
-+              netif_dbg(pegasus, rx_err, net, "RX status %d\n", status);
-+              goto goon;
-+      }
-+
-+      if (!count || count < 4)
-+              goto goon;
-+
-+      rx_status = buf[count - 2];
-+      if (rx_status & 0x1e) {
-+              netif_dbg(pegasus, rx_err, net,
-+                        "RX packet error %x\n", rx_status);
-+              pegasus->stats.rx_errors++;
-+              if (rx_status & 0x06)   /* long or runt */
-+                      pegasus->stats.rx_length_errors++;
-+              if (rx_status & 0x08)
-+                      pegasus->stats.rx_crc_errors++;
-+              if (rx_status & 0x10)   /* extra bits   */
-+                      pegasus->stats.rx_frame_errors++;
-+              goto goon;
-+      }
-+      if (pegasus->chip == 0x8513) {
-+              pkt_len = le32_to_cpu(*(__le32 *)urb->transfer_buffer);
-+              pkt_len &= 0x0fff;
-+              pegasus->rx_skb->data += 2;
-+      } else {
-+              pkt_len = buf[count - 3] << 8;
-+              pkt_len += buf[count - 4];
-+              pkt_len &= 0xfff;
-+              pkt_len -= 8;
-+      }
-+
-+      /*
-+       * If the packet is unreasonably long, quietly drop it rather than
-+       * kernel panicing by calling skb_put.
-+       */
-+      if (pkt_len > PEGASUS_MTU)
-+              goto goon;
-+
-+      /*
-+       * at this point we are sure pegasus->rx_skb != NULL
-+       * so we go ahead and pass up the packet.
-+       */
-+      skb_put(pegasus->rx_skb, pkt_len);
-+      pegasus->rx_skb->protocol = eth_type_trans(pegasus->rx_skb, net);
-+      netif_rx(pegasus->rx_skb);
-+      pegasus->stats.rx_packets++;
-+      pegasus->stats.rx_bytes += pkt_len;
-+
-+      if (pegasus->flags & PEGASUS_UNPLUG)
-+              return;
-+
-+      pegasus->rx_skb = __netdev_alloc_skb_ip_align(pegasus->net, PEGASUS_MTU,
-+                                                    GFP_ATOMIC);
-+
-+      if (pegasus->rx_skb == NULL)
-+              goto tl_sched;
-+goon:
-+      usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
-+                        usb_rcvbulkpipe(pegasus->usb, 1),
-+                        pegasus->rx_skb->data, PEGASUS_MTU + 8,
-+                        read_bulk_callback, pegasus);
-+      rx_status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC);
-+      if (rx_status == -ENODEV)
-+              netif_device_detach(pegasus->net);
-+      else if (rx_status) {
-+              pegasus->flags |= PEGASUS_RX_URB_FAIL;
-+              goto tl_sched;
-+      } else {
-+              pegasus->flags &= ~PEGASUS_RX_URB_FAIL;
-+      }
-+
-+      return;
-+
-+tl_sched:
-+      tasklet_schedule(&pegasus->rx_tl);
-+}
-+
-+static void rx_fixup(unsigned long data)
-+{
-+      pegasus_t *pegasus;
-+      int status;
-+
-+      pegasus = (pegasus_t *) data;
-+      if (pegasus->flags & PEGASUS_UNPLUG)
-+              return;
-+
-+      if (pegasus->flags & PEGASUS_RX_URB_FAIL)
-+              if (pegasus->rx_skb)
-+                      goto try_again;
-+      if (pegasus->rx_skb == NULL)
-+              pegasus->rx_skb = __netdev_alloc_skb_ip_align(pegasus->net,
-+                                                            PEGASUS_MTU,
-+                                                            GFP_ATOMIC);
-+      if (pegasus->rx_skb == NULL) {
-+              netif_warn(pegasus, rx_err, pegasus->net, "low on memory\n");
-+              tasklet_schedule(&pegasus->rx_tl);
-+              return;
-+      }
-+      usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
-+                        usb_rcvbulkpipe(pegasus->usb, 1),
-+                        pegasus->rx_skb->data, PEGASUS_MTU + 8,
-+                        read_bulk_callback, pegasus);
-+try_again:
-+      status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC);
-+      if (status == -ENODEV)
-+              netif_device_detach(pegasus->net);
-+      else if (status) {
-+              pegasus->flags |= PEGASUS_RX_URB_FAIL;
-+              tasklet_schedule(&pegasus->rx_tl);
-+      } else {
-+              pegasus->flags &= ~PEGASUS_RX_URB_FAIL;
-+      }
-+}
-+
-+static void write_bulk_callback(struct urb *urb)
-+{
-+      pegasus_t *pegasus = urb->context;
-+      struct net_device *net;
-+      int status = urb->status;
-+
-+      if (!pegasus)
-+              return;
-+
-+      net = pegasus->net;
-+
-+      if (!netif_device_present(net) || !netif_running(net))
-+              return;
-+
-+      switch (status) {
-+      case -EPIPE:
-+              /* FIXME schedule_work() to clear the tx halt */
-+              netif_stop_queue(net);
-+              netif_warn(pegasus, tx_err, net, "no tx stall recovery\n");
-+              return;
-+      case -ENOENT:
-+      case -ECONNRESET:
-+      case -ESHUTDOWN:
-+              netif_dbg(pegasus, ifdown, net, "tx unlink, %d\n", status);
-+              return;
-+      default:
-+              netif_info(pegasus, tx_err, net, "TX status %d\n", status);
-+              /* FALL THROUGH */
-+      case 0:
-+              break;
-+      }
-+
-+      net->trans_start = jiffies; /* prevent tx timeout */
-+      netif_wake_queue(net);
-+}
-+
-+static void intr_callback(struct urb *urb)
-+{
-+      pegasus_t *pegasus = urb->context;
-+      struct net_device *net;
-+      int res, status = urb->status;
-+
-+      if (!pegasus)
-+              return;
-+      net = pegasus->net;
-+
-+      switch (status) {
-+      case 0:
-+              break;
-+      case -ECONNRESET:       /* unlink */
-+      case -ENOENT:
-+      case -ESHUTDOWN:
-+              return;
-+      default:
-+              /* some Pegasus-I products report LOTS of data
-+               * toggle errors... avoid log spamming
-+               */
-+              netif_dbg(pegasus, timer, net, "intr status %d\n", status);
-+      }
-+
-+      if (urb->actual_length >= 6) {
-+              u8 *d = urb->transfer_buffer;
-+
-+              /* byte 0 == tx_status1, reg 2B */
-+              if (d[0] & (TX_UNDERRUN|EXCESSIVE_COL
-+                                      |LATE_COL|JABBER_TIMEOUT)) {
-+                      pegasus->stats.tx_errors++;
-+                      if (d[0] & TX_UNDERRUN)
-+                              pegasus->stats.tx_fifo_errors++;
-+                      if (d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT))
-+                              pegasus->stats.tx_aborted_errors++;
-+                      if (d[0] & LATE_COL)
-+                              pegasus->stats.tx_window_errors++;
-+              }
-+
-+              /* d[5].LINK_STATUS lies on some adapters.
-+               * d[0].NO_CARRIER kicks in only with failed TX.
-+               * ... so monitoring with MII may be safest.
-+               */
-+
-+              /* bytes 3-4 == rx_lostpkt, reg 2E/2F */
-+              pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4];
-+      }
-+
-+      res = usb_submit_urb(urb, GFP_ATOMIC);
-+      if (res == -ENODEV)
-+              netif_device_detach(pegasus->net);
-+      if (res)
-+              netif_err(pegasus, timer, net,
-+                        "can't resubmit interrupt urb, %d\n", res);
-+}
-+
-+static void pegasus_tx_timeout(struct net_device *net)
-+{
-+      pegasus_t *pegasus = netdev_priv(net);
-+      netif_warn(pegasus, timer, net, "tx timeout\n");
-+      usb_unlink_urb(pegasus->tx_urb);
-+      pegasus->stats.tx_errors++;
-+}
-+
-+static netdev_tx_t pegasus_start_xmit(struct sk_buff *skb,
-+                                          struct net_device *net)
-+{
-+      pegasus_t *pegasus = netdev_priv(net);
-+      int count = ((skb->len + 2) & 0x3f) ? skb->len + 2 : skb->len + 3;
-+      int res;
-+      __u16 l16 = skb->len;
-+
-+      netif_stop_queue(net);
-+
-+      ((__le16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16);
-+      skb_copy_from_linear_data(skb, pegasus->tx_buff + 2, skb->len);
-+      usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb,
-+                        usb_sndbulkpipe(pegasus->usb, 2),
-+                        pegasus->tx_buff, count,
-+                        write_bulk_callback, pegasus);
-+      if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) {
-+              netif_warn(pegasus, tx_err, net, "fail tx, %d\n", res);
-+              switch (res) {
-+              case -EPIPE:            /* stall, or disconnect from TT */
-+                      /* cleanup should already have been scheduled */
-+                      break;
-+              case -ENODEV:           /* disconnect() upcoming */
-+              case -EPERM:
-+                      netif_device_detach(pegasus->net);
-+                      break;
-+              default:
-+                      pegasus->stats.tx_errors++;
-+                      netif_start_queue(net);
-+              }
-+      } else {
-+              pegasus->stats.tx_packets++;
-+              pegasus->stats.tx_bytes += skb->len;
-+      }
-+      dev_kfree_skb(skb);
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
-+{
-+      return &((pegasus_t *) netdev_priv(dev))->stats;
-+}
-+
-+static inline void disable_net_traffic(pegasus_t *pegasus)
-+{
-+      __le16 tmp = cpu_to_le16(0);
-+
-+      set_registers(pegasus, EthCtrl0, sizeof(tmp), &tmp);
-+}
-+
-+static inline void get_interrupt_interval(pegasus_t *pegasus)
-+{
-+      u16 data;
-+      u8 interval;
-+
-+      read_eprom_word(pegasus, 4, &data);
-+      interval = data >> 8;
-+      if (pegasus->usb->speed != USB_SPEED_HIGH) {
-+              if (interval < 0x80) {
-+                      netif_info(pegasus, timer, pegasus->net,
-+                                 "intr interval changed from %ums to %ums\n",
-+                                 interval, 0x80);
-+                      interval = 0x80;
-+                      data = (data & 0x00FF) | ((u16)interval << 8);
-+#ifdef PEGASUS_WRITE_EEPROM
-+                      write_eprom_word(pegasus, 4, data);
-+#endif
-+              }
-+      }
-+      pegasus->intr_interval = interval;
-+}
-+
-+static void set_carrier(struct net_device *net)
-+{
-+      pegasus_t *pegasus = netdev_priv(net);
-+      u16 tmp;
-+
-+      if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
-+              return;
-+
-+      if (tmp & BMSR_LSTATUS)
-+              netif_carrier_on(net);
-+      else
-+              netif_carrier_off(net);
-+}
-+
-+static void free_all_urbs(pegasus_t *pegasus)
-+{
-+      usb_free_urb(pegasus->intr_urb);
-+      usb_free_urb(pegasus->tx_urb);
-+      usb_free_urb(pegasus->rx_urb);
-+}
-+
-+static void unlink_all_urbs(pegasus_t *pegasus)
-+{
-+      usb_kill_urb(pegasus->intr_urb);
-+      usb_kill_urb(pegasus->tx_urb);
-+      usb_kill_urb(pegasus->rx_urb);
-+}
-+
-+static int alloc_urbs(pegasus_t *pegasus)
-+{
-+      int res = -ENOMEM;
-+
-+      pegasus->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!pegasus->rx_urb) {
-+              return res;
-+      }
-+      pegasus->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!pegasus->tx_urb) {
-+              usb_free_urb(pegasus->rx_urb);
-+              return res;
-+      }
-+      pegasus->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!pegasus->intr_urb) {
-+              usb_free_urb(pegasus->tx_urb);
-+              usb_free_urb(pegasus->rx_urb);
-+              return res;
-+      }
-+
-+      return 0;
-+}
-+
-+static int pegasus_open(struct net_device *net)
-+{
-+      pegasus_t *pegasus = netdev_priv(net);
-+      int res=-ENOMEM;
-+
-+      if (pegasus->rx_skb == NULL)
-+              pegasus->rx_skb = __netdev_alloc_skb_ip_align(pegasus->net,
-+                                                            PEGASUS_MTU,
-+                                                            GFP_KERNEL);
-+      if (!pegasus->rx_skb)
-+              goto exit;
-+
-+      res = set_registers(pegasus, EthID, 6, net->dev_addr);
-+
-+      usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
-+                        usb_rcvbulkpipe(pegasus->usb, 1),
-+                        pegasus->rx_skb->data, PEGASUS_MTU + 8,
-+                        read_bulk_callback, pegasus);
-+      if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) {
-+              if (res == -ENODEV)
-+                      netif_device_detach(pegasus->net);
-+              netif_dbg(pegasus, ifup, net, "failed rx_urb, %d\n", res);
-+              goto exit;
-+      }
-+
-+      usb_fill_int_urb(pegasus->intr_urb, pegasus->usb,
-+                       usb_rcvintpipe(pegasus->usb, 3),
-+                       pegasus->intr_buff, sizeof(pegasus->intr_buff),
-+                       intr_callback, pegasus, pegasus->intr_interval);
-+      if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) {
-+              if (res == -ENODEV)
-+                      netif_device_detach(pegasus->net);
-+              netif_dbg(pegasus, ifup, net, "failed intr_urb, %d\n", res);
-+              usb_kill_urb(pegasus->rx_urb);
-+              goto exit;
-+      }
-+      res = enable_net_traffic(net, pegasus->usb);
-+      if (res < 0) {
-+              netif_dbg(pegasus, ifup, net,
-+                        "can't enable_net_traffic() - %d\n", res);
-+              res = -EIO;
-+              usb_kill_urb(pegasus->rx_urb);
-+              usb_kill_urb(pegasus->intr_urb);
-+              goto exit;
-+      }
-+      set_carrier(net);
-+      netif_start_queue(net);
-+      netif_dbg(pegasus, ifup, net, "open\n");
-+      res = 0;
-+exit:
-+      return res;
-+}
-+
-+static int pegasus_close(struct net_device *net)
-+{
-+      pegasus_t *pegasus = netdev_priv(net);
-+
-+      netif_stop_queue(net);
-+      if (!(pegasus->flags & PEGASUS_UNPLUG))
-+              disable_net_traffic(pegasus);
-+      tasklet_kill(&pegasus->rx_tl);
-+      unlink_all_urbs(pegasus);
-+
-+      return 0;
-+}
-+
-+static void pegasus_get_drvinfo(struct net_device *dev,
-+                              struct ethtool_drvinfo *info)
-+{
-+      pegasus_t *pegasus = netdev_priv(dev);
-+
-+      strlcpy(info->driver, driver_name, sizeof(info->driver));
-+      strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
-+      usb_make_path(pegasus->usb, info->bus_info, sizeof(info->bus_info));
-+}
-+
-+/* also handles three patterns of some kind in hardware */
-+#define       WOL_SUPPORTED   (WAKE_MAGIC|WAKE_PHY)
-+
-+static void
-+pegasus_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-+{
-+      pegasus_t       *pegasus = netdev_priv(dev);
-+
-+      wol->supported = WAKE_MAGIC | WAKE_PHY;
-+      wol->wolopts = pegasus->wolopts;
-+}
-+
-+static int
-+pegasus_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-+{
-+      pegasus_t       *pegasus = netdev_priv(dev);
-+      u8              reg78 = 0x04;
-+      int             ret;
-+
-+      if (wol->wolopts & ~WOL_SUPPORTED)
-+              return -EINVAL;
-+
-+      if (wol->wolopts & WAKE_MAGIC)
-+              reg78 |= 0x80;
-+      if (wol->wolopts & WAKE_PHY)
-+              reg78 |= 0x40;
-+      /* FIXME this 0x10 bit still needs to get set in the chip... */
-+      if (wol->wolopts)
-+              pegasus->eth_regs[0] |= 0x10;
-+      else
-+              pegasus->eth_regs[0] &= ~0x10;
-+      pegasus->wolopts = wol->wolopts;
-+
-+      ret = set_register(pegasus, WakeupControl, reg78);
-+      if (!ret)
-+              ret = device_set_wakeup_enable(&pegasus->usb->dev,
-+                                              wol->wolopts);
-+      return ret;
-+}
-+
-+static inline void pegasus_reset_wol(struct net_device *dev)
-+{
-+      struct ethtool_wolinfo wol;
-+
-+      memset(&wol, 0, sizeof wol);
-+      (void) pegasus_set_wol(dev, &wol);
-+}
-+
-+static int
-+pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-+{
-+      pegasus_t *pegasus;
-+
-+      pegasus = netdev_priv(dev);
-+      mii_ethtool_gset(&pegasus->mii, ecmd);
-+      return 0;
-+}
-+
-+static int
-+pegasus_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-+{
-+      pegasus_t *pegasus = netdev_priv(dev);
-+      return mii_ethtool_sset(&pegasus->mii, ecmd);
-+}
-+
-+static int pegasus_nway_reset(struct net_device *dev)
-+{
-+      pegasus_t *pegasus = netdev_priv(dev);
-+      return mii_nway_restart(&pegasus->mii);
-+}
-+
-+static u32 pegasus_get_link(struct net_device *dev)
-+{
-+      pegasus_t *pegasus = netdev_priv(dev);
-+      return mii_link_ok(&pegasus->mii);
-+}
-+
-+static u32 pegasus_get_msglevel(struct net_device *dev)
-+{
-+      pegasus_t *pegasus = netdev_priv(dev);
-+      return pegasus->msg_enable;
-+}
-+
-+static void pegasus_set_msglevel(struct net_device *dev, u32 v)
-+{
-+      pegasus_t *pegasus = netdev_priv(dev);
-+      pegasus->msg_enable = v;
-+}
-+
-+static const struct ethtool_ops ops = {
-+      .get_drvinfo = pegasus_get_drvinfo,
-+      .get_settings = pegasus_get_settings,
-+      .set_settings = pegasus_set_settings,
-+      .nway_reset = pegasus_nway_reset,
-+      .get_link = pegasus_get_link,
-+      .get_msglevel = pegasus_get_msglevel,
-+      .set_msglevel = pegasus_set_msglevel,
-+      .get_wol = pegasus_get_wol,
-+      .set_wol = pegasus_set_wol,
-+};
-+
-+static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
-+{
-+      __u16 *data = (__u16 *) &rq->ifr_ifru;
-+      pegasus_t *pegasus = netdev_priv(net);
-+      int res;
-+
-+      switch (cmd) {
-+      case SIOCDEVPRIVATE:
-+              data[0] = pegasus->phy;
-+      case SIOCDEVPRIVATE + 1:
-+              read_mii_word(pegasus, data[0], data[1] & 0x1f, &data[3]);
-+              res = 0;
-+              break;
-+      case SIOCDEVPRIVATE + 2:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, &data[2]);
-+              res = 0;
-+              break;
-+      default:
-+              res = -EOPNOTSUPP;
-+      }
-+      return res;
-+}
-+
-+static void pegasus_set_multicast(struct net_device *net)
-+{
-+      pegasus_t *pegasus = netdev_priv(net);
-+
-+      if (net->flags & IFF_PROMISC) {
-+              pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS;
-+              netif_info(pegasus, link, net, "Promiscuous mode enabled\n");
-+      } else if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI)) {
-+              pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
-+              pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
-+              netif_dbg(pegasus, link, net, "set allmulti\n");
-+      } else {
-+              pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST;
-+              pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
-+      }
-+      update_eth_regs_async(pegasus);
-+}
-+
-+static __u8 mii_phy_probe(pegasus_t *pegasus)
-+{
-+      int i;
-+      __u16 tmp;
-+
-+      for (i = 0; i < 32; i++) {
-+              read_mii_word(pegasus, i, MII_BMSR, &tmp);
-+              if (tmp == 0 || tmp == 0xffff || (tmp & BMSR_MEDIA) == 0)
-+                      continue;
-+              else
-+                      return i;
-+      }
-+
-+      return 0xff;
-+}
-+
-+static inline void setup_pegasus_II(pegasus_t *pegasus)
-+{
-+      __u8 data = 0xa5;
-+
-+      set_register(pegasus, Reg1d, 0);
-+      set_register(pegasus, Reg7b, 1);
-+      mdelay(100);
-+      if ((pegasus->features & HAS_HOME_PNA) && mii_mode)
-+              set_register(pegasus, Reg7b, 0);
-+      else
-+              set_register(pegasus, Reg7b, 2);
-+
-+      set_register(pegasus, 0x83, data);
-+      get_registers(pegasus, 0x83, 1, &data);
-+
-+      if (data == 0xa5)
-+              pegasus->chip = 0x8513;
-+      else
-+              pegasus->chip = 0;
-+
-+      set_register(pegasus, 0x80, 0xc0);
-+      set_register(pegasus, 0x83, 0xff);
-+      set_register(pegasus, 0x84, 0x01);
-+
-+      if (pegasus->features & HAS_HOME_PNA && mii_mode)
-+              set_register(pegasus, Reg81, 6);
-+      else
-+              set_register(pegasus, Reg81, 2);
-+}
-+
-+
-+static int pegasus_count;
-+static struct workqueue_struct *pegasus_workqueue;
-+#define CARRIER_CHECK_DELAY (2 * HZ)
-+
-+static void check_carrier(struct work_struct *work)
-+{
-+      pegasus_t *pegasus = container_of(work, pegasus_t, carrier_check.work);
-+      set_carrier(pegasus->net);
-+      if (!(pegasus->flags & PEGASUS_UNPLUG)) {
-+              queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
-+                      CARRIER_CHECK_DELAY);
-+      }
-+}
-+
-+static int pegasus_blacklisted(struct usb_device *udev)
-+{
-+      struct usb_device_descriptor *udd = &udev->descriptor;
-+
-+      /* Special quirk to keep the driver from handling the Belkin Bluetooth
-+       * dongle which happens to have the same ID.
-+       */
-+      if ((udd->idVendor == cpu_to_le16(VENDOR_BELKIN)) &&
-+          (udd->idProduct == cpu_to_le16(0x0121)) &&
-+          (udd->bDeviceClass == USB_CLASS_WIRELESS_CONTROLLER) &&
-+          (udd->bDeviceProtocol == 1))
-+              return 1;
-+
-+      return 0;
-+}
-+
-+/* we rely on probe() and remove() being serialized so we
-+ * don't need extra locking on pegasus_count.
-+ */
-+static void pegasus_dec_workqueue(void)
-+{
-+      pegasus_count--;
-+      if (pegasus_count == 0) {
-+              destroy_workqueue(pegasus_workqueue);
-+              pegasus_workqueue = NULL;
-+      }
-+}
-+
-+static int pegasus_probe(struct usb_interface *intf,
-+                       const struct usb_device_id *id)
-+{
-+      struct usb_device *dev = interface_to_usbdev(intf);
-+      struct net_device *net;
-+      pegasus_t *pegasus;
-+      int dev_index = id - pegasus_ids;
-+      int res = -ENOMEM;
-+
-+      if (pegasus_blacklisted(dev))
-+              return -ENODEV;
-+
-+      if (pegasus_count == 0) {
-+              pegasus_workqueue = create_singlethread_workqueue("pegasus");
-+              if (!pegasus_workqueue)
-+                      return -ENOMEM;
-+      }
-+      pegasus_count++;
-+
-+      net = alloc_etherdev(sizeof(struct pegasus));
-+      if (!net)
-+              goto out;
-+
-+      pegasus = netdev_priv(net);
-+      pegasus->dev_index = dev_index;
-+
-+      res = alloc_urbs(pegasus);
-+      if (res < 0) {
-+              dev_err(&intf->dev, "can't allocate %s\n", "urbs");
-+              goto out1;
-+      }
-+
-+      tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus);
-+
-+      INIT_DELAYED_WORK(&pegasus->carrier_check, check_carrier);
-+
-+      pegasus->intf = intf;
-+      pegasus->usb = dev;
-+      pegasus->net = net;
-+
-+
-+      net->watchdog_timeo = PEGASUS_TX_TIMEOUT;
-+      net->netdev_ops = &pegasus_netdev_ops;
-+      net->ethtool_ops = &ops;
-+      pegasus->mii.dev = net;
-+      pegasus->mii.mdio_read = mdio_read;
-+      pegasus->mii.mdio_write = mdio_write;
-+      pegasus->mii.phy_id_mask = 0x1f;
-+      pegasus->mii.reg_num_mask = 0x1f;
-+      pegasus->msg_enable = netif_msg_init(msg_level, NETIF_MSG_DRV
-+                              | NETIF_MSG_PROBE | NETIF_MSG_LINK);
-+
-+      pegasus->features = usb_dev_id[dev_index].private;
-+      get_interrupt_interval(pegasus);
-+      if (reset_mac(pegasus)) {
-+              dev_err(&intf->dev, "can't reset MAC\n");
-+              res = -EIO;
-+              goto out2;
-+      }
-+      set_ethernet_addr(pegasus);
-+      if (pegasus->features & PEGASUS_II) {
-+              dev_info(&intf->dev, "setup Pegasus II specific registers\n");
-+              setup_pegasus_II(pegasus);
-+      }
-+      pegasus->phy = mii_phy_probe(pegasus);
-+      if (pegasus->phy == 0xff) {
-+              dev_warn(&intf->dev, "can't locate MII phy, using default\n");
-+              pegasus->phy = 1;
-+      }
-+      pegasus->mii.phy_id = pegasus->phy;
-+      usb_set_intfdata(intf, pegasus);
-+      SET_NETDEV_DEV(net, &intf->dev);
-+      pegasus_reset_wol(net);
-+      res = register_netdev(net);
-+      if (res)
-+              goto out3;
-+      queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
-+                         CARRIER_CHECK_DELAY);
-+      dev_info(&intf->dev, "%s, %s, %pM\n", net->name,
-+               usb_dev_id[dev_index].name, net->dev_addr);
-+      return 0;
-+
-+out3:
-+      usb_set_intfdata(intf, NULL);
-+out2:
-+      free_all_urbs(pegasus);
-+out1:
-+      free_netdev(net);
-+out:
-+      pegasus_dec_workqueue();
-+      return res;
-+}
-+
-+static void pegasus_disconnect(struct usb_interface *intf)
-+{
-+      struct pegasus *pegasus = usb_get_intfdata(intf);
-+
-+      usb_set_intfdata(intf, NULL);
-+      if (!pegasus) {
-+              dev_dbg(&intf->dev, "unregistering non-bound device?\n");
-+              return;
-+      }
-+
-+      pegasus->flags |= PEGASUS_UNPLUG;
-+      cancel_delayed_work(&pegasus->carrier_check);
-+      unregister_netdev(pegasus->net);
-+      unlink_all_urbs(pegasus);
-+      free_all_urbs(pegasus);
-+      if (pegasus->rx_skb != NULL) {
-+              dev_kfree_skb(pegasus->rx_skb);
-+              pegasus->rx_skb = NULL;
-+      }
-+      free_netdev(pegasus->net);
-+      pegasus_dec_workqueue();
-+}
-+
-+static int pegasus_suspend(struct usb_interface *intf, pm_message_t message)
-+{
-+      struct pegasus *pegasus = usb_get_intfdata(intf);
-+
-+      netif_device_detach(pegasus->net);
-+      cancel_delayed_work(&pegasus->carrier_check);
-+      if (netif_running(pegasus->net)) {
-+              usb_kill_urb(pegasus->rx_urb);
-+              usb_kill_urb(pegasus->intr_urb);
-+      }
-+      return 0;
-+}
-+
-+static int pegasus_resume(struct usb_interface *intf)
-+{
-+      struct pegasus *pegasus = usb_get_intfdata(intf);
-+
-+      netif_device_attach(pegasus->net);
-+      if (netif_running(pegasus->net)) {
-+              pegasus->rx_urb->status = 0;
-+              pegasus->rx_urb->actual_length = 0;
-+              read_bulk_callback(pegasus->rx_urb);
-+
-+              pegasus->intr_urb->status = 0;
-+              pegasus->intr_urb->actual_length = 0;
-+              intr_callback(pegasus->intr_urb);
-+      }
-+      queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
-+                              CARRIER_CHECK_DELAY);
-+      return 0;
-+}
-+
-+static const struct net_device_ops pegasus_netdev_ops = {
-+      .ndo_open =                     pegasus_open,
-+      .ndo_stop =                     pegasus_close,
-+      .ndo_do_ioctl =                 pegasus_ioctl,
-+      .ndo_start_xmit =               pegasus_start_xmit,
-+      .ndo_set_rx_mode =              pegasus_set_multicast,
-+      .ndo_get_stats =                pegasus_netdev_stats,
-+      .ndo_tx_timeout =               pegasus_tx_timeout,
-+      .ndo_change_mtu =               eth_change_mtu,
-+      .ndo_set_mac_address =          eth_mac_addr,
-+      .ndo_validate_addr =            eth_validate_addr,
-+};
-+
-+static struct usb_driver pegasus_driver = {
-+      .name = driver_name,
-+      .probe = pegasus_probe,
-+      .disconnect = pegasus_disconnect,
-+      .id_table = pegasus_ids,
-+      .suspend = pegasus_suspend,
-+      .resume = pegasus_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+static void __init parse_id(char *id)
-+{
-+      unsigned int vendor_id = 0, device_id = 0, flags = 0, i = 0;
-+      char *token, *name = NULL;
-+
-+      if ((token = strsep(&id, ":")) != NULL)
-+              name = token;
-+      /* name now points to a null terminated string*/
-+      if ((token = strsep(&id, ":")) != NULL)
-+              vendor_id = simple_strtoul(token, NULL, 16);
-+      if ((token = strsep(&id, ":")) != NULL)
-+              device_id = simple_strtoul(token, NULL, 16);
-+      flags = simple_strtoul(id, NULL, 16);
-+      pr_info("%s: new device %s, vendor ID 0x%04x, device ID 0x%04x, flags: 0x%x\n",
-+              driver_name, name, vendor_id, device_id, flags);
-+
-+      if (vendor_id > 0x10000 || vendor_id == 0)
-+              return;
-+      if (device_id > 0x10000 || device_id == 0)
-+              return;
-+
-+      for (i = 0; usb_dev_id[i].name; i++);
-+      usb_dev_id[i].name = name;
-+      usb_dev_id[i].vendor = vendor_id;
-+      usb_dev_id[i].device = device_id;
-+      usb_dev_id[i].private = flags;
-+      pegasus_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
-+      pegasus_ids[i].idVendor = vendor_id;
-+      pegasus_ids[i].idProduct = device_id;
-+}
-+
-+static int __init pegasus_init(void)
-+{
-+      pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION);
-+      if (devid)
-+              parse_id(devid);
-+      return usb_register(&pegasus_driver);
-+}
-+
-+static void __exit pegasus_exit(void)
-+{
-+      usb_deregister(&pegasus_driver);
-+}
-+
-+module_init(pegasus_init);
-+module_exit(pegasus_exit);
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/pegasus.h backports-4.2.6-1/drivers/net/usb/pegasus.h
---- backports-4.2.6-1.org/drivers/net/usb/pegasus.h    1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/pegasus.h        2016-06-28 14:35:17.998640551 +0200
-@@ -0,0 +1,308 @@
-+/*
-+ * Copyright (c) 1999-2013 Petko Manolov (petkan@nucleusys.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.
-+ */
-+
-+
-+#ifndef       PEGASUS_DEV
-+
-+#define       PEGASUS_II              0x80000000
-+#define       HAS_HOME_PNA            0x40000000
-+
-+#define       PEGASUS_MTU             1536
-+
-+#define       EPROM_WRITE             0x01
-+#define       EPROM_READ              0x02
-+#define       EPROM_DONE              0x04
-+#define       EPROM_WR_ENABLE         0x10
-+#define       EPROM_LOAD              0x20
-+
-+#define       PHY_DONE                0x80
-+#define       PHY_READ                0x40
-+#define       PHY_WRITE               0x20
-+#define       DEFAULT_GPIO_RESET      0x24
-+#define       DEFAULT_GPIO_SET        0x26
-+
-+#define       PEGASUS_PRESENT         0x00000001
-+#define       PEGASUS_TX_BUSY         0x00000004
-+#define       PEGASUS_RX_BUSY         0x00000008
-+#define       CTRL_URB_RUNNING        0x00000010
-+#define       CTRL_URB_SLEEP          0x00000020
-+#define       PEGASUS_UNPLUG          0x00000040
-+#define       PEGASUS_RX_URB_FAIL     0x00000080
-+
-+#define       RX_MULTICAST            2
-+#define       RX_PROMISCUOUS          4
-+
-+#define       REG_TIMEOUT             (HZ)
-+#define       PEGASUS_TX_TIMEOUT      (HZ*10)
-+
-+#define       TX_UNDERRUN             0x80
-+#define       EXCESSIVE_COL           0x40
-+#define       LATE_COL                0x20
-+#define       NO_CARRIER              0x10
-+#define       LOSS_CARRIER            0x08
-+#define       JABBER_TIMEOUT          0x04
-+
-+#define       LINK_STATUS             0x01
-+
-+#define       PEGASUS_REQT_READ       0xc0
-+#define       PEGASUS_REQT_WRITE      0x40
-+#define       PEGASUS_REQ_GET_REGS    0xf0
-+#define       PEGASUS_REQ_SET_REGS    0xf1
-+#define       PEGASUS_REQ_SET_REG     PEGASUS_REQ_SET_REGS
-+
-+enum pegasus_registers {
-+      EthCtrl0 = 0,
-+      EthCtrl1 = 1,
-+      EthCtrl2 = 2,
-+      EthID = 0x10,
-+      Reg1d = 0x1d,
-+      EpromOffset = 0x20,
-+      EpromData = 0x21,       /* 0x21 low, 0x22 high byte */
-+      EpromCtrl = 0x23,
-+      PhyAddr = 0x25,
-+      PhyData = 0x26,         /* 0x26 low, 0x27 high byte */
-+      PhyCtrl = 0x28,
-+      UsbStst = 0x2a,
-+      EthTxStat0 = 0x2b,
-+      EthTxStat1 = 0x2c,
-+      EthRxStat = 0x2d,
-+      WakeupControl = 0x78,
-+      Reg7b = 0x7b,
-+      Gpio0 = 0x7e,
-+      Gpio1 = 0x7f,
-+      Reg81 = 0x81,
-+};
-+
-+
-+typedef struct pegasus {
-+      struct usb_device       *usb;
-+      struct usb_interface    *intf;
-+      struct net_device       *net;
-+      struct net_device_stats stats;
-+      struct mii_if_info      mii;
-+      unsigned                flags;
-+      unsigned                features;
-+      u32                     msg_enable;
-+      u32                     wolopts;
-+      int                     dev_index;
-+      int                     intr_interval;
-+      struct tasklet_struct   rx_tl;
-+      struct delayed_work     carrier_check;
-+      struct urb              *rx_urb, *tx_urb, *intr_urb;
-+      struct sk_buff          *rx_skb;
-+      int                     chip;
-+      unsigned char           intr_buff[8];
-+      __u8                    tx_buff[PEGASUS_MTU];
-+      __u8                    eth_regs[4];
-+      __u8                    phy;
-+      __u8                    gpio_res;
-+} pegasus_t;
-+
-+
-+struct usb_eth_dev {
-+      char    *name;
-+      __u16   vendor;
-+      __u16   device;
-+      __u32   private; /* LSB is gpio reset value */
-+};
-+
-+#define       VENDOR_3COM             0x0506
-+#define       VENDOR_ABOCOM           0x07b8
-+#define       VENDOR_ACCTON           0x083a
-+#define       VENDOR_ADMTEK           0x07a6
-+#define       VENDOR_AEILAB           0x3334
-+#define       VENDOR_ALLIEDTEL        0x07c9
-+#define       VENDOR_ATEN             0x0557
-+#define       VENDOR_BELKIN           0x050d
-+#define       VENDOR_BILLIONTON       0x08dd
-+#define       VENDOR_COMPAQ           0x049f
-+#define       VENDOR_COREGA           0x07aa
-+#define       VENDOR_DLINK            0x2001
-+#define       VENDOR_ELCON            0x0db7
-+#define       VENDOR_ELECOM           0x056e
-+#define       VENDOR_ELSA             0x05cc
-+#define       VENDOR_GIGABYTE         0x1044
-+#define       VENDOR_HAWKING          0x0e66
-+#define       VENDOR_HP               0x03f0
-+#define       VENDOR_IODATA           0x04bb
-+#define       VENDOR_KINGSTON         0x0951
-+#define       VENDOR_LANEED           0x056e
-+#define       VENDOR_LINKSYS          0x066b
-+#define       VENDOR_LINKSYS2         0x077b
-+#define       VENDOR_MELCO            0x0411
-+#define       VENDOR_MICROSOFT        0x045e
-+#define       VENDOR_MOBILITY         0x1342
-+#define       VENDOR_NETGEAR          0x0846
-+#define       VENDOR_OCT              0x0b39
-+#define       VENDOR_SMARTBRIDGES     0x08d1
-+#define       VENDOR_SMC              0x0707
-+#define       VENDOR_SOHOWARE         0x15e8
-+#define       VENDOR_SIEMENS          0x067c
-+
-+
-+#else /* PEGASUS_DEV */
-+
-+PEGASUS_DEV("3Com USB Ethernet 3C460B", VENDOR_3COM, 0x4601,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("ATEN USB Ethernet UC-110T", VENDOR_ATEN, 0x2007,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("USB HPNA/Ethernet", VENDOR_ABOCOM, 0x110c,
-+              DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA)
-+PEGASUS_DEV("USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4104,
-+              DEFAULT_GPIO_RESET | HAS_HOME_PNA)
-+PEGASUS_DEV("USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4004,
-+              DEFAULT_GPIO_RESET | HAS_HOME_PNA)
-+PEGASUS_DEV("USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4007,
-+              DEFAULT_GPIO_RESET | HAS_HOME_PNA)
-+PEGASUS_DEV("USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4102,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4002,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400b,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400c,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0xabc1,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x200c,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("Philips USB 10/100 Ethernet", VENDOR_ACCTON, 0xb004,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
-+              VENDOR_ADMTEK, 0x8511,
-+              DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA)
-+PEGASUS_DEV("ADMtek ADM8513 \"Pegasus II\" USB Ethernet",
-+              VENDOR_ADMTEK, 0x8513,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("ADMtek ADM8515 \"Pegasus II\" USB-2.0 Ethernet",
-+              VENDOR_ADMTEK, 0x8515,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("ADMtek AN986 \"Pegasus\" USB Ethernet (evaluation board)",
-+              VENDOR_ADMTEK, 0x0986,
-+              DEFAULT_GPIO_RESET | HAS_HOME_PNA)
-+PEGASUS_DEV("AN986A USB MAC", VENDOR_ADMTEK, 1986,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("AEI USB Fast Ethernet Adapter", VENDOR_AEILAB, 0x1701,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+/*
-+ * Distinguish between this Belkin adaptor and the Belkin bluetooth adaptors
-+ * with the same product IDs by checking the device class too.
-+ */
-+PEGASUS_DEV_CLASS("Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121, 0x00,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("Belkin F5U122 10/100 USB Ethernet", VENDOR_BELKIN, 0x0122,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("Billionton USB-100", VENDOR_BILLIONTON, 0x0986,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987,
-+              DEFAULT_GPIO_RESET | HAS_HOME_PNA)
-+PEGASUS_DEV("iPAQ Networking 10/100 USB", VENDOR_COMPAQ, 0x8511,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("Billionton USBEL-100", VENDOR_BILLIONTON, 0x0988,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("Billionton USBE-100", VENDOR_BILLIONTON, 0x8511,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("Corega FEther USB-TX", VENDOR_COREGA, 0x0004,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("Corega FEther USB-TXS", VENDOR_COREGA, 0x000d,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("D-Link DSB-650TX", VENDOR_DLINK, 0x4001,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("D-Link DSB-650TX", VENDOR_DLINK, 0x4002,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("D-Link DSB-650TX", VENDOR_DLINK, 0x4102,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("D-Link DSB-650TX", VENDOR_DLINK, 0x400b,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("D-Link DSB-650TX", VENDOR_DLINK, 0x200c,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("D-Link DSB-650TX(PNA)", VENDOR_DLINK, 0x4003,
-+              DEFAULT_GPIO_RESET | HAS_HOME_PNA)
-+PEGASUS_DEV("D-Link DSB-650", VENDOR_DLINK, 0xabc1,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("GOLDPFEIL USB Adapter", VENDOR_ELCON, 0x0002,
-+              DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA)
-+PEGASUS_DEV("ELECOM USB Ethernet LD-USB20", VENDOR_ELECOM,  0x4010,
-+              DEFAULT_GPIO_RESET  | PEGASUS_II)
-+PEGASUS_DEV("EasiDock Ethernet", VENDOR_MOBILITY, 0x0304,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("GIGABYTE GN-BR402W Wireless Router", VENDOR_GIGABYTE, 0x8002,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("HP hn210c Ethernet USB", VENDOR_HP, 0x811c,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("IO DATA USB ET/TX", VENDOR_IODATA, 0x0904,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("IO DATA USB ETX-US2", VENDOR_IODATA, 0x093a,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("LANEED USB Ethernet LD-USBL/TX", VENDOR_LANEED, 0x4005,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x200c,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("Linksys USB10TX", VENDOR_LINKSYS, 0x2202,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("Linksys USB100TX", VENDOR_LINKSYS, 0x2203,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("Linksys USB100TX", VENDOR_LINKSYS, 0x2204,
-+              DEFAULT_GPIO_RESET | HAS_HOME_PNA)
-+PEGASUS_DEV("Linksys USB10T Ethernet Adapter", VENDOR_LINKSYS, 0x2206,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("Linksys USBVPN1", VENDOR_LINKSYS2, 0x08b4,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("Linksys USB USB100TX", VENDOR_LINKSYS, 0x400b,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("Linksys USB10TX", VENDOR_LINKSYS, 0x200c,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0001,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0005,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("Microsoft MN-110", VENDOR_MICROSOFT, 0x007a,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("NETGEAR FA101", VENDOR_NETGEAR, 0x1020,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("OCT Inc.", VENDOR_OCT, 0x0109,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("OCT USB TO Ethernet", VENDOR_OCT, 0x0901,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("SMC 2206 USB Ethernet", VENDOR_SMC, 0x0201,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
-+              DEFAULT_GPIO_RESET)
-+PEGASUS_DEV("SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+PEGASUS_DEV("SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
-+              DEFAULT_GPIO_RESET | PEGASUS_II)
-+
-+
-+#endif        /* PEGASUS_DEV */
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/plusb.c backports-4.2.6-1/drivers/net/usb/plusb.c
---- backports-4.2.6-1.org/drivers/net/usb/plusb.c      1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/plusb.c  2016-06-28 14:35:17.998640551 +0200
-@@ -0,0 +1,162 @@
-+/*
-+ * PL-2301/2302 USB host-to-host link cables
-+ * Copyright (C) 2000-2005 by David Brownell
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+// #define    DEBUG                   // error path messages, extra info
-+// #define    VERBOSE                 // more; success messages
-+
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/workqueue.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/usb/usbnet.h>
-+
-+
-+/*
-+ * Prolific PL-2301/PL-2302 driver ... http://www.prolific.com.tw/ 
-+ *
-+ * The protocol and handshaking used here should be bug-compatible
-+ * with the Linux 2.2 "plusb" driver, by Deti Fliegl.
-+ *
-+ * HEADS UP:  this handshaking isn't all that robust.  This driver
-+ * gets confused easily if you unplug one end of the cable then
-+ * try to connect it again; you'll need to restart both ends. The
-+ * "naplink" software (used by some PlayStation/2 deveopers) does
-+ * the handshaking much better!   Also, sometimes this hardware
-+ * seems to get wedged under load.  Prolific docs are weak, and
-+ * don't identify differences between PL2301 and PL2302, much less
-+ * anything to explain the different PL2302 versions observed.
-+ *
-+ * NOTE:  pl2501 has several modes, including pl2301 and pl2302
-+ * compatibility.   Some docs suggest the difference between 2301
-+ * and 2302 is only to make MS-Windows use a different driver...
-+ *
-+ * pl25a1 glue based on patch from Tony Gibbs.  Prolific "docs" on
-+ * this chip are as usual incomplete about what control messages
-+ * are supported.
-+ */
-+
-+/*
-+ * Bits 0-4 can be used for software handshaking; they're set from
-+ * one end, cleared from the other, "read" with the interrupt byte.
-+ */
-+#define       PL_S_EN         (1<<7)          /* (feature only) suspend enable */
-+/* reserved bit -- rx ready (6) ? */
-+#define       PL_TX_READY     (1<<5)          /* (interrupt only) transmit ready */
-+#define       PL_RESET_OUT    (1<<4)          /* reset output pipe */
-+#define       PL_RESET_IN     (1<<3)          /* reset input pipe */
-+#define       PL_TX_C         (1<<2)          /* transmission complete */
-+#define       PL_TX_REQ       (1<<1)          /* transmission received */
-+#define       PL_PEER_E       (1<<0)          /* peer exists */
-+
-+static inline int
-+pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
-+{
-+      return usbnet_read_cmd(dev, req,
-+                              USB_DIR_IN | USB_TYPE_VENDOR |
-+                              USB_RECIP_DEVICE,
-+                              val, index, NULL, 0);
-+}
-+
-+static inline int
-+pl_clear_QuickLink_features(struct usbnet *dev, int val)
-+{
-+      return pl_vendor_req(dev, 1, (u8) val, 0);
-+}
-+
-+static inline int
-+pl_set_QuickLink_features(struct usbnet *dev, int val)
-+{
-+      return pl_vendor_req(dev, 3, (u8) val, 0);
-+}
-+
-+static int pl_reset(struct usbnet *dev)
-+{
-+      int status;
-+
-+      /* some units seem to need this reset, others reject it utterly.
-+       * FIXME be more like "naplink" or windows drivers.
-+       */
-+      status = pl_set_QuickLink_features(dev,
-+              PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E);
-+      if (status != 0 && netif_msg_probe(dev))
-+              netif_dbg(dev, link, dev->net, "pl_reset --> %d\n", status);
-+      return 0;
-+}
-+
-+static const struct driver_info       prolific_info = {
-+      .description =  "Prolific PL-2301/PL-2302/PL-25A1",
-+      .flags =        FLAG_POINTTOPOINT | FLAG_NO_SETINT,
-+              /* some PL-2302 versions seem to fail usb_set_interface() */
-+      .reset =        pl_reset,
-+};
-+
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/*
-+ * Proilific's name won't normally be on the cables, and
-+ * may not be on the device.
-+ */
-+
-+static const struct usb_device_id     products [] = {
-+
-+/* full speed cables */
-+{
-+      USB_DEVICE(0x067b, 0x0000),     // PL-2301
-+      .driver_info =  (unsigned long) &prolific_info,
-+}, {
-+      USB_DEVICE(0x067b, 0x0001),     // PL-2302
-+      .driver_info =  (unsigned long) &prolific_info,
-+},
-+
-+/* high speed cables */
-+{
-+      USB_DEVICE(0x067b, 0x25a1),     /* PL-25A1, no eeprom */
-+      .driver_info =  (unsigned long) &prolific_info,
-+}, {
-+      USB_DEVICE(0x050d, 0x258a),     /* Belkin F5U258/F5U279 (PL-25A1) */
-+      .driver_info =  (unsigned long) &prolific_info,
-+}, {
-+      USB_DEVICE(0x3923, 0x7825),     /* National Instruments USB
-+                                       * Host-to-Host Cable
-+                                       */
-+      .driver_info =  (unsigned long) &prolific_info,
-+},
-+
-+      { },            // END
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver plusb_driver = {
-+      .name =         "plusb",
-+      .id_table =     products,
-+      .probe =        usbnet_probe,
-+      .disconnect =   usbnet_disconnect,
-+      .suspend =      usbnet_suspend,
-+      .resume =       usbnet_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(plusb_driver);
-+
-+MODULE_AUTHOR("David Brownell");
-+MODULE_DESCRIPTION("Prolific PL-2301/2302/25A1 USB Host to Host Link Driver");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/r8152.c backports-4.2.6-1/drivers/net/usb/r8152.c
---- backports-4.2.6-1.org/drivers/net/usb/r8152.c      1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/r8152.c  2016-06-28 14:45:32.005250978 +0200
-@@ -0,0 +1,2856 @@
-+/*
-+ *  Copyright (c) 2014 Realtek Semiconductor Corp. All rights reserved.
-+ *
-+ * 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.
-+ *
-+ */
-+
-+#include <linux/signal.h>
-+#include <linux/slab.h>
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/mii.h>
-+#include <linux/ethtool.h>
-+#include <linux/usb.h>
-+#include <linux/crc32.h>
-+#include <linux/if_vlan.h>
-+#include <linux/uaccess.h>
-+#include <linux/list.h>
-+#include <linux/ip.h>
-+#include <linux/ipv6.h>
-+
-+/* Version Information */
-+#define DRIVER_VERSION "v1.04.0 (2014/01/15)"
-+#define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
-+#define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
-+#define MODULENAME "r8152"
-+
-+#define R8152_PHY_ID          32
-+
-+#define PLA_IDR                       0xc000
-+#define PLA_RCR                       0xc010
-+#define PLA_RMS                       0xc016
-+#define PLA_RXFIFO_CTRL0      0xc0a0
-+#define PLA_RXFIFO_CTRL1      0xc0a4
-+#define PLA_RXFIFO_CTRL2      0xc0a8
-+#define PLA_FMC                       0xc0b4
-+#define PLA_CFG_WOL           0xc0b6
-+#define PLA_TEREDO_CFG                0xc0bc
-+#define PLA_MAR                       0xcd00
-+#define PLA_BACKUP            0xd000
-+#define PAL_BDC_CR            0xd1a0
-+#define PLA_TEREDO_TIMER      0xd2cc
-+#define PLA_REALWOW_TIMER     0xd2e8
-+#define PLA_LEDSEL            0xdd90
-+#define PLA_LED_FEATURE               0xdd92
-+#define PLA_PHYAR             0xde00
-+#define PLA_BOOT_CTRL         0xe004
-+#define PLA_GPHY_INTR_IMR     0xe022
-+#define PLA_EEE_CR            0xe040
-+#define PLA_EEEP_CR           0xe080
-+#define PLA_MAC_PWR_CTRL      0xe0c0
-+#define PLA_MAC_PWR_CTRL2     0xe0ca
-+#define PLA_MAC_PWR_CTRL3     0xe0cc
-+#define PLA_MAC_PWR_CTRL4     0xe0ce
-+#define PLA_WDT6_CTRL         0xe428
-+#define PLA_TCR0              0xe610
-+#define PLA_TCR1              0xe612
-+#define PLA_TXFIFO_CTRL               0xe618
-+#define PLA_RSTTELLY          0xe800
-+#define PLA_CR                        0xe813
-+#define PLA_CRWECR            0xe81c
-+#define PLA_CONFIG5           0xe822
-+#define PLA_PHY_PWR           0xe84c
-+#define PLA_OOB_CTRL          0xe84f
-+#define PLA_CPCR              0xe854
-+#define PLA_MISC_0            0xe858
-+#define PLA_MISC_1            0xe85a
-+#define PLA_OCP_GPHY_BASE     0xe86c
-+#define PLA_TELLYCNT          0xe890
-+#define PLA_SFF_STS_7         0xe8de
-+#define PLA_PHYSTATUS         0xe908
-+#define PLA_BP_BA             0xfc26
-+#define PLA_BP_0              0xfc28
-+#define PLA_BP_1              0xfc2a
-+#define PLA_BP_2              0xfc2c
-+#define PLA_BP_3              0xfc2e
-+#define PLA_BP_4              0xfc30
-+#define PLA_BP_5              0xfc32
-+#define PLA_BP_6              0xfc34
-+#define PLA_BP_7              0xfc36
-+#define PLA_BP_EN             0xfc38
-+
-+#define USB_U2P3_CTRL         0xb460
-+#define USB_DEV_STAT          0xb808
-+#define USB_USB_CTRL          0xd406
-+#define USB_PHY_CTRL          0xd408
-+#define USB_TX_AGG            0xd40a
-+#define USB_RX_BUF_TH         0xd40c
-+#define USB_USB_TIMER         0xd428
-+#define USB_RX_EARLY_AGG      0xd42c
-+#define USB_PM_CTRL_STATUS    0xd432
-+#define USB_TX_DMA            0xd434
-+#define USB_TOLERANCE         0xd490
-+#define USB_LPM_CTRL          0xd41a
-+#define USB_UPS_CTRL          0xd800
-+#define USB_MISC_0            0xd81a
-+#define USB_POWER_CUT         0xd80a
-+#define USB_AFE_CTRL2         0xd824
-+#define USB_WDT11_CTRL                0xe43c
-+#define USB_BP_BA             0xfc26
-+#define USB_BP_0              0xfc28
-+#define USB_BP_1              0xfc2a
-+#define USB_BP_2              0xfc2c
-+#define USB_BP_3              0xfc2e
-+#define USB_BP_4              0xfc30
-+#define USB_BP_5              0xfc32
-+#define USB_BP_6              0xfc34
-+#define USB_BP_7              0xfc36
-+#define USB_BP_EN             0xfc38
-+
-+/* OCP Registers */
-+#define OCP_ALDPS_CONFIG      0x2010
-+#define OCP_EEE_CONFIG1               0x2080
-+#define OCP_EEE_CONFIG2               0x2092
-+#define OCP_EEE_CONFIG3               0x2094
-+#define OCP_BASE_MII          0xa400
-+#define OCP_EEE_AR            0xa41a
-+#define OCP_EEE_DATA          0xa41c
-+#define OCP_PHY_STATUS                0xa420
-+#define OCP_POWER_CFG         0xa430
-+#define OCP_EEE_CFG           0xa432
-+#define OCP_SRAM_ADDR         0xa436
-+#define OCP_SRAM_DATA         0xa438
-+#define OCP_DOWN_SPEED                0xa442
-+#define OCP_EEE_CFG2          0xa5d0
-+#define OCP_ADC_CFG           0xbc06
-+
-+/* SRAM Register */
-+#define SRAM_LPF_CFG          0x8012
-+#define SRAM_10M_AMP1         0x8080
-+#define SRAM_10M_AMP2         0x8082
-+#define SRAM_IMPEDANCE                0x8084
-+
-+/* PLA_RCR */
-+#define RCR_AAP                       0x00000001
-+#define RCR_APM                       0x00000002
-+#define RCR_AM                        0x00000004
-+#define RCR_AB                        0x00000008
-+#define RCR_ACPT_ALL          (RCR_AAP | RCR_APM | RCR_AM | RCR_AB)
-+
-+/* PLA_RXFIFO_CTRL0 */
-+#define RXFIFO_THR1_NORMAL    0x00080002
-+#define RXFIFO_THR1_OOB               0x01800003
-+
-+/* PLA_RXFIFO_CTRL1 */
-+#define RXFIFO_THR2_FULL      0x00000060
-+#define RXFIFO_THR2_HIGH      0x00000038
-+#define RXFIFO_THR2_OOB               0x0000004a
-+#define RXFIFO_THR2_NORMAL    0x00a0
-+
-+/* PLA_RXFIFO_CTRL2 */
-+#define RXFIFO_THR3_FULL      0x00000078
-+#define RXFIFO_THR3_HIGH      0x00000048
-+#define RXFIFO_THR3_OOB               0x0000005a
-+#define RXFIFO_THR3_NORMAL    0x0110
-+
-+/* PLA_TXFIFO_CTRL */
-+#define TXFIFO_THR_NORMAL     0x00400008
-+#define TXFIFO_THR_NORMAL2    0x01000008
-+
-+/* PLA_FMC */
-+#define FMC_FCR_MCU_EN                0x0001
-+
-+/* PLA_EEEP_CR */
-+#define EEEP_CR_EEEP_TX               0x0002
-+
-+/* PLA_WDT6_CTRL */
-+#define WDT6_SET_MODE         0x0010
-+
-+/* PLA_TCR0 */
-+#define TCR0_TX_EMPTY         0x0800
-+#define TCR0_AUTO_FIFO                0x0080
-+
-+/* PLA_TCR1 */
-+#define VERSION_MASK          0x7cf0
-+
-+/* PLA_CR */
-+#define CR_RST                        0x10
-+#define CR_RE                 0x08
-+#define CR_TE                 0x04
-+
-+/* PLA_CRWECR */
-+#define CRWECR_NORAML         0x00
-+#define CRWECR_CONFIG         0xc0
-+
-+/* PLA_OOB_CTRL */
-+#define NOW_IS_OOB            0x80
-+#define TXFIFO_EMPTY          0x20
-+#define RXFIFO_EMPTY          0x10
-+#define LINK_LIST_READY               0x02
-+#define DIS_MCU_CLROOB                0x01
-+#define FIFO_EMPTY            (TXFIFO_EMPTY | RXFIFO_EMPTY)
-+
-+/* PLA_MISC_1 */
-+#define RXDY_GATED_EN         0x0008
-+
-+/* PLA_SFF_STS_7 */
-+#define RE_INIT_LL            0x8000
-+#define MCU_BORW_EN           0x4000
-+
-+/* PLA_CPCR */
-+#define CPCR_RX_VLAN          0x0040
-+
-+/* PLA_CFG_WOL */
-+#define MAGIC_EN              0x0001
-+
-+/* PLA_TEREDO_CFG */
-+#define TEREDO_SEL            0x8000
-+#define TEREDO_WAKE_MASK      0x7f00
-+#define TEREDO_RS_EVENT_MASK  0x00fe
-+#define OOB_TEREDO_EN         0x0001
-+
-+/* PAL_BDC_CR */
-+#define ALDPS_PROXY_MODE      0x0001
-+
-+/* PLA_CONFIG5 */
-+#define LAN_WAKE_EN           0x0002
-+
-+/* PLA_LED_FEATURE */
-+#define LED_MODE_MASK         0x0700
-+
-+/* PLA_PHY_PWR */
-+#define TX_10M_IDLE_EN                0x0080
-+#define PFM_PWM_SWITCH                0x0040
-+
-+/* PLA_MAC_PWR_CTRL */
-+#define D3_CLK_GATED_EN               0x00004000
-+#define MCU_CLK_RATIO         0x07010f07
-+#define MCU_CLK_RATIO_MASK    0x0f0f0f0f
-+#define ALDPS_SPDWN_RATIO     0x0f87
-+
-+/* PLA_MAC_PWR_CTRL2 */
-+#define EEE_SPDWN_RATIO               0x8007
-+
-+/* PLA_MAC_PWR_CTRL3 */
-+#define PKT_AVAIL_SPDWN_EN    0x0100
-+#define SUSPEND_SPDWN_EN      0x0004
-+#define U1U2_SPDWN_EN         0x0002
-+#define L1_SPDWN_EN           0x0001
-+
-+/* PLA_MAC_PWR_CTRL4 */
-+#define PWRSAVE_SPDWN_EN      0x1000
-+#define RXDV_SPDWN_EN         0x0800
-+#define TX10MIDLE_EN          0x0100
-+#define TP100_SPDWN_EN                0x0020
-+#define TP500_SPDWN_EN                0x0010
-+#define TP1000_SPDWN_EN               0x0008
-+#define EEE_SPDWN_EN          0x0001
-+
-+/* PLA_GPHY_INTR_IMR */
-+#define GPHY_STS_MSK          0x0001
-+#define SPEED_DOWN_MSK                0x0002
-+#define SPDWN_RXDV_MSK                0x0004
-+#define SPDWN_LINKCHG_MSK     0x0008
-+
-+/* PLA_PHYAR */
-+#define PHYAR_FLAG            0x80000000
-+
-+/* PLA_EEE_CR */
-+#define EEE_RX_EN             0x0001
-+#define EEE_TX_EN             0x0002
-+
-+/* PLA_BOOT_CTRL */
-+#define AUTOLOAD_DONE         0x0002
-+
-+/* USB_DEV_STAT */
-+#define STAT_SPEED_MASK               0x0006
-+#define STAT_SPEED_HIGH               0x0000
-+#define STAT_SPEED_FULL               0x0001
-+
-+/* USB_TX_AGG */
-+#define TX_AGG_MAX_THRESHOLD  0x03
-+
-+/* USB_RX_BUF_TH */
-+#define RX_THR_SUPPER         0x0c350180
-+#define RX_THR_HIGH           0x7a120180
-+#define RX_THR_SLOW           0xffff0180
-+
-+/* USB_TX_DMA */
-+#define TEST_MODE_DISABLE     0x00000001
-+#define TX_SIZE_ADJUST1               0x00000100
-+
-+/* USB_UPS_CTRL */
-+#define POWER_CUT             0x0100
-+
-+/* USB_PM_CTRL_STATUS */
-+#define RESUME_INDICATE               0x0001
-+
-+/* USB_USB_CTRL */
-+#define RX_AGG_DISABLE                0x0010
-+
-+/* USB_U2P3_CTRL */
-+#define U2P3_ENABLE           0x0001
-+
-+/* USB_POWER_CUT */
-+#define PWR_EN                        0x0001
-+#define PHASE2_EN             0x0008
-+
-+/* USB_MISC_0 */
-+#define PCUT_STATUS           0x0001
-+
-+/* USB_RX_EARLY_AGG */
-+#define EARLY_AGG_SUPPER      0x0e832981
-+#define EARLY_AGG_HIGH                0x0e837a12
-+#define EARLY_AGG_SLOW                0x0e83ffff
-+
-+/* USB_WDT11_CTRL */
-+#define TIMER11_EN            0x0001
-+
-+/* USB_LPM_CTRL */
-+#define LPM_TIMER_MASK                0x0c
-+#define LPM_TIMER_500MS               0x04    /* 500 ms */
-+#define LPM_TIMER_500US               0x0c    /* 500 us */
-+
-+/* USB_AFE_CTRL2 */
-+#define SEN_VAL_MASK          0xf800
-+#define SEN_VAL_NORMAL                0xa000
-+#define SEL_RXIDLE            0x0100
-+
-+/* OCP_ALDPS_CONFIG */
-+#define ENPWRSAVE             0x8000
-+#define ENPDNPS                       0x0200
-+#define LINKENA                       0x0100
-+#define DIS_SDSAVE            0x0010
-+
-+/* OCP_PHY_STATUS */
-+#define PHY_STAT_MASK         0x0007
-+#define PHY_STAT_LAN_ON               3
-+#define PHY_STAT_PWRDN                5
-+
-+/* OCP_POWER_CFG */
-+#define EEE_CLKDIV_EN         0x8000
-+#define EN_ALDPS              0x0004
-+#define EN_10M_PLLOFF         0x0001
-+
-+/* OCP_EEE_CONFIG1 */
-+#define RG_TXLPI_MSK_HFDUP    0x8000
-+#define RG_MATCLR_EN          0x4000
-+#define EEE_10_CAP            0x2000
-+#define EEE_NWAY_EN           0x1000
-+#define TX_QUIET_EN           0x0200
-+#define RX_QUIET_EN           0x0100
-+#define SDRISETIME            0x0010  /* bit 4 ~ 6 */
-+#define RG_RXLPI_MSK_HFDUP    0x0008
-+#define SDFALLTIME            0x0007  /* bit 0 ~ 2 */
-+
-+/* OCP_EEE_CONFIG2 */
-+#define RG_LPIHYS_NUM         0x7000  /* bit 12 ~ 15 */
-+#define RG_DACQUIET_EN                0x0400
-+#define RG_LDVQUIET_EN                0x0200
-+#define RG_CKRSEL             0x0020
-+#define RG_EEEPRG_EN          0x0010
-+
-+/* OCP_EEE_CONFIG3 */
-+#define FST_SNR_EYE_R         0x1500  /* bit 7 ~ 15 */
-+#define RG_LFS_SEL            0x0060  /* bit 6 ~ 5 */
-+#define MSK_PH                        0x0006  /* bit 0 ~ 3 */
-+
-+/* OCP_EEE_AR */
-+/* bit[15:14] function */
-+#define FUN_ADDR              0x0000
-+#define FUN_DATA              0x4000
-+/* bit[4:0] device addr */
-+#define DEVICE_ADDR           0x0007
-+
-+/* OCP_EEE_DATA */
-+#define EEE_ADDR              0x003C
-+#define EEE_DATA              0x0002
-+
-+/* OCP_EEE_CFG */
-+#define CTAP_SHORT_EN         0x0040
-+#define EEE10_EN              0x0010
-+
-+/* OCP_DOWN_SPEED */
-+#define EN_10M_BGOFF          0x0080
-+
-+/* OCP_EEE_CFG2 */
-+#define MY1000_EEE            0x0004
-+#define MY100_EEE             0x0002
-+
-+/* OCP_ADC_CFG */
-+#define CKADSEL_L             0x0100
-+#define ADC_EN                        0x0080
-+#define EN_EMI_L              0x0040
-+
-+/* SRAM_LPF_CFG */
-+#define LPF_AUTO_TUNE         0x8000
-+
-+/* SRAM_10M_AMP1 */
-+#define GDAC_IB_UPALL         0x0008
-+
-+/* SRAM_10M_AMP2 */
-+#define AMP_DN                        0x0200
-+
-+/* SRAM_IMPEDANCE */
-+#define RX_DRIVING_MASK               0x6000
-+
-+enum rtl_register_content {
-+      _1000bps        = 0x10,
-+      _100bps         = 0x08,
-+      _10bps          = 0x04,
-+      LINK_STATUS     = 0x02,
-+      FULL_DUP        = 0x01,
-+};
-+
-+#define RTL8152_MAX_TX                10
-+#define RTL8152_MAX_RX                10
-+#define INTBUFSIZE            2
-+#define CRC_SIZE              4
-+#define TX_ALIGN              4
-+#define RX_ALIGN              8
-+
-+#define INTR_LINK             0x0004
-+
-+#define RTL8152_REQT_READ     0xc0
-+#define RTL8152_REQT_WRITE    0x40
-+#define RTL8152_REQ_GET_REGS  0x05
-+#define RTL8152_REQ_SET_REGS  0x05
-+
-+#define BYTE_EN_DWORD         0xff
-+#define BYTE_EN_WORD          0x33
-+#define BYTE_EN_BYTE          0x11
-+#define BYTE_EN_SIX_BYTES     0x3f
-+#define BYTE_EN_START_MASK    0x0f
-+#define BYTE_EN_END_MASK      0xf0
-+
-+#define RTL8152_RMS           (VLAN_ETH_FRAME_LEN + VLAN_HLEN)
-+#define RTL8152_TX_TIMEOUT    (HZ)
-+
-+/* rtl8152 flags */
-+enum rtl8152_flags {
-+      RTL8152_UNPLUG = 0,
-+      RTL8152_SET_RX_MODE,
-+      WORK_ENABLE,
-+      RTL8152_LINK_CHG,
-+};
-+
-+/* Define these values to match your device */
-+#define VENDOR_ID_REALTEK             0x0bda
-+#define PRODUCT_ID_RTL8152            0x8152
-+#define PRODUCT_ID_RTL8153            0x8153
-+
-+#define VENDOR_ID_SAMSUNG             0x04e8
-+#define PRODUCT_ID_SAMSUNG            0xa101
-+
-+#define VENDOR_ID_LENOVO              0x17ef
-+#define PRODUCT_ID_LENOVO             0x7205
-+
-+#define VENDOR_ID_NVIDIA              0x0955
-+#define PRODUCT_ID_NVIDIA             0x09ff
-+
-+
-+#define MCU_TYPE_PLA                  0x0100
-+#define MCU_TYPE_USB                  0x0000
-+
-+struct rx_desc {
-+      __le32 opts1;
-+#define RX_LEN_MASK                   0x7fff
-+      __le32 opts2;
-+      __le32 opts3;
-+      __le32 opts4;
-+      __le32 opts5;
-+      __le32 opts6;
-+};
-+
-+struct tx_desc {
-+      __le32 opts1;
-+#define TX_FS                 (1 << 31) /* First segment of a packet */
-+#define TX_LS                 (1 << 30) /* Final segment of a packet */
-+#define TX_LEN_MASK           0x3ffff
-+
-+      __le32 opts2;
-+#define UDP_CS                        (1 << 31) /* Calculate UDP/IP checksum */
-+#define TCP_CS                        (1 << 30) /* Calculate TCP/IP checksum */
-+#define IPV4_CS                       (1 << 29) /* Calculate IPv4 checksum */
-+#define IPV6_CS                       (1 << 28) /* Calculate IPv6 checksum */
-+};
-+
-+struct r8152;
-+
-+struct rx_agg {
-+      struct list_head list;
-+      struct urb *urb;
-+      struct r8152 *context;
-+      void *buffer;
-+      void *head;
-+};
-+
-+struct tx_agg {
-+      struct list_head list;
-+      struct urb *urb;
-+      struct r8152 *context;
-+      void *buffer;
-+      void *head;
-+      u32 skb_num;
-+      u32 skb_len;
-+};
-+
-+struct r8152 {
-+      unsigned long flags;
-+      struct usb_device *udev;
-+      struct tasklet_struct tl;
-+      struct usb_interface *intf;
-+      struct net_device *netdev;
-+      struct urb *intr_urb;
-+      struct tx_agg tx_info[RTL8152_MAX_TX];
-+      struct rx_agg rx_info[RTL8152_MAX_RX];
-+      struct list_head rx_done, tx_free;
-+      struct sk_buff_head tx_queue;
-+      spinlock_t rx_lock, tx_lock;
-+      struct delayed_work schedule;
-+      struct mii_if_info mii;
-+
-+      struct rtl_ops {
-+              void (*init)(struct r8152 *);
-+              int (*enable)(struct r8152 *);
-+              void (*disable)(struct r8152 *);
-+              void (*down)(struct r8152 *);
-+              void (*unload)(struct r8152 *);
-+      } __no_const rtl_ops;
-+
-+      int intr_interval;
-+      u32 msg_enable;
-+      u32 tx_qlen;
-+      u16 ocp_base;
-+      u8 *intr_buff;
-+      u8 version;
-+      u8 speed;
-+};
-+
-+enum rtl_version {
-+      RTL_VER_UNKNOWN = 0,
-+      RTL_VER_01,
-+      RTL_VER_02,
-+      RTL_VER_03,
-+      RTL_VER_04,
-+      RTL_VER_05,
-+      RTL_VER_MAX
-+};
-+
-+/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
-+ * The RTL chips use a 64 element hash table based on the Ethernet CRC.
-+ */
-+static const int multicast_filter_limit = 32;
-+static unsigned int rx_buf_sz = 16384;
-+
-+static
-+int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
-+{
-+      int ret;
-+      void *tmp;
-+
-+      tmp = kmalloc(size, GFP_KERNEL);
-+      if (!tmp)
-+              return -ENOMEM;
-+
-+      ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
-+                             RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
-+                             value, index, tmp, size, 500);
-+
-+      memcpy(data, tmp, size);
-+      kfree(tmp);
-+
-+      return ret;
-+}
-+
-+static
-+int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
-+{
-+      int ret;
-+      void *tmp;
-+
-+      tmp = kmalloc(size, GFP_KERNEL);
-+      if (!tmp)
-+              return -ENOMEM;
-+
-+      memcpy(tmp, data, size);
-+
-+      ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0),
-+                             RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
-+                             value, index, tmp, size, 500);
-+
-+      kfree(tmp);
-+      return ret;
-+}
-+
-+static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
-+                              void *data, u16 type)
-+{
-+      u16 limit = 64;
-+      int ret = 0;
-+
-+      if (test_bit(RTL8152_UNPLUG, &tp->flags))
-+              return -ENODEV;
-+
-+      /* both size and indix must be 4 bytes align */
-+      if ((size & 3) || !size || (index & 3) || !data)
-+              return -EPERM;
-+
-+      if ((u32)index + (u32)size > 0xffff)
-+              return -EPERM;
-+
-+      while (size) {
-+              if (size > limit) {
-+                      ret = get_registers(tp, index, type, limit, data);
-+                      if (ret < 0)
-+                              break;
-+
-+                      index += limit;
-+                      data += limit;
-+                      size -= limit;
-+              } else {
-+                      ret = get_registers(tp, index, type, size, data);
-+                      if (ret < 0)
-+                              break;
-+
-+                      index += size;
-+                      data += size;
-+                      size = 0;
-+                      break;
-+              }
-+      }
-+
-+      return ret;
-+}
-+
-+static int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
-+                              u16 size, void *data, u16 type)
-+{
-+      int ret;
-+      u16 byteen_start, byteen_end, byen;
-+      u16 limit = 512;
-+
-+      if (test_bit(RTL8152_UNPLUG, &tp->flags))
-+              return -ENODEV;
-+
-+      /* both size and indix must be 4 bytes align */
-+      if ((size & 3) || !size || (index & 3) || !data)
-+              return -EPERM;
-+
-+      if ((u32)index + (u32)size > 0xffff)
-+              return -EPERM;
-+
-+      byteen_start = byteen & BYTE_EN_START_MASK;
-+      byteen_end = byteen & BYTE_EN_END_MASK;
-+
-+      byen = byteen_start | (byteen_start << 4);
-+      ret = set_registers(tp, index, type | byen, 4, data);
-+      if (ret < 0)
-+              goto error1;
-+
-+      index += 4;
-+      data += 4;
-+      size -= 4;
-+
-+      if (size) {
-+              size -= 4;
-+
-+              while (size) {
-+                      if (size > limit) {
-+                              ret = set_registers(tp, index,
-+                                      type | BYTE_EN_DWORD,
-+                                      limit, data);
-+                              if (ret < 0)
-+                                      goto error1;
-+
-+                              index += limit;
-+                              data += limit;
-+                              size -= limit;
-+                      } else {
-+                              ret = set_registers(tp, index,
-+                                      type | BYTE_EN_DWORD,
-+                                      size, data);
-+                              if (ret < 0)
-+                                      goto error1;
-+
-+                              index += size;
-+                              data += size;
-+                              size = 0;
-+                              break;
-+                      }
-+              }
-+
-+              byen = byteen_end | (byteen_end >> 4);
-+              ret = set_registers(tp, index, type | byen, 4, data);
-+              if (ret < 0)
-+                      goto error1;
-+      }
-+
-+error1:
-+      return ret;
-+}
-+
-+static inline
-+int pla_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
-+{
-+      return generic_ocp_read(tp, index, size, data, MCU_TYPE_PLA);
-+}
-+
-+static inline
-+int pla_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data)
-+{
-+      return generic_ocp_write(tp, index, byteen, size, data, MCU_TYPE_PLA);
-+}
-+
-+static inline
-+int usb_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
-+{
-+      return generic_ocp_read(tp, index, size, data, MCU_TYPE_USB);
-+}
-+
-+static inline
-+int usb_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data)
-+{
-+      return generic_ocp_write(tp, index, byteen, size, data, MCU_TYPE_USB);
-+}
-+
-+static u32 ocp_read_dword(struct r8152 *tp, u16 type, u16 index)
-+{
-+      __le32 data;
-+
-+      generic_ocp_read(tp, index, sizeof(data), &data, type);
-+
-+      return __le32_to_cpu(data);
-+}
-+
-+static void ocp_write_dword(struct r8152 *tp, u16 type, u16 index, u32 data)
-+{
-+      __le32 tmp = __cpu_to_le32(data);
-+
-+      generic_ocp_write(tp, index, BYTE_EN_DWORD, sizeof(tmp), &tmp, type);
-+}
-+
-+static u16 ocp_read_word(struct r8152 *tp, u16 type, u16 index)
-+{
-+      u32 data;
-+      __le32 tmp;
-+      u8 shift = index & 2;
-+
-+      index &= ~3;
-+
-+      generic_ocp_read(tp, index, sizeof(tmp), &tmp, type);
-+
-+      data = __le32_to_cpu(tmp);
-+      data >>= (shift * 8);
-+      data &= 0xffff;
-+
-+      return (u16)data;
-+}
-+
-+static void ocp_write_word(struct r8152 *tp, u16 type, u16 index, u32 data)
-+{
-+      u32 mask = 0xffff;
-+      __le32 tmp;
-+      u16 byen = BYTE_EN_WORD;
-+      u8 shift = index & 2;
-+
-+      data &= mask;
-+
-+      if (index & 2) {
-+              byen <<= shift;
-+              mask <<= (shift * 8);
-+              data <<= (shift * 8);
-+              index &= ~3;
-+      }
-+
-+      generic_ocp_read(tp, index, sizeof(tmp), &tmp, type);
-+
-+      data |= __le32_to_cpu(tmp) & ~mask;
-+      tmp = __cpu_to_le32(data);
-+
-+      generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
-+}
-+
-+static u8 ocp_read_byte(struct r8152 *tp, u16 type, u16 index)
-+{
-+      u32 data;
-+      __le32 tmp;
-+      u8 shift = index & 3;
-+
-+      index &= ~3;
-+
-+      generic_ocp_read(tp, index, sizeof(tmp), &tmp, type);
-+
-+      data = __le32_to_cpu(tmp);
-+      data >>= (shift * 8);
-+      data &= 0xff;
-+
-+      return (u8)data;
-+}
-+
-+static void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data)
-+{
-+      u32 mask = 0xff;
-+      __le32 tmp;
-+      u16 byen = BYTE_EN_BYTE;
-+      u8 shift = index & 3;
-+
-+      data &= mask;
-+
-+      if (index & 3) {
-+              byen <<= shift;
-+              mask <<= (shift * 8);
-+              data <<= (shift * 8);
-+              index &= ~3;
-+      }
-+
-+      generic_ocp_read(tp, index, sizeof(tmp), &tmp, type);
-+
-+      data |= __le32_to_cpu(tmp) & ~mask;
-+      tmp = __cpu_to_le32(data);
-+
-+      generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
-+}
-+
-+static u16 ocp_reg_read(struct r8152 *tp, u16 addr)
-+{
-+      u16 ocp_base, ocp_index;
-+
-+      ocp_base = addr & 0xf000;
-+      if (ocp_base != tp->ocp_base) {
-+              ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
-+              tp->ocp_base = ocp_base;
-+      }
-+
-+      ocp_index = (addr & 0x0fff) | 0xb000;
-+      return ocp_read_word(tp, MCU_TYPE_PLA, ocp_index);
-+}
-+
-+static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
-+{
-+      u16 ocp_base, ocp_index;
-+
-+      ocp_base = addr & 0xf000;
-+      if (ocp_base != tp->ocp_base) {
-+              ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
-+              tp->ocp_base = ocp_base;
-+      }
-+
-+      ocp_index = (addr & 0x0fff) | 0xb000;
-+      ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data);
-+}
-+
-+static inline void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
-+{
-+      ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
-+}
-+
-+static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
-+{
-+      return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);
-+}
-+
-+static void sram_write(struct r8152 *tp, u16 addr, u16 data)
-+{
-+      ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
-+      ocp_reg_write(tp, OCP_SRAM_DATA, data);
-+}
-+
-+static u16 sram_read(struct r8152 *tp, u16 addr)
-+{
-+      ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
-+      return ocp_reg_read(tp, OCP_SRAM_DATA);
-+}
-+
-+static int read_mii_word(struct net_device *netdev, int phy_id, int reg)
-+{
-+      struct r8152 *tp = netdev_priv(netdev);
-+
-+      if (phy_id != R8152_PHY_ID)
-+              return -EINVAL;
-+
-+      return r8152_mdio_read(tp, reg);
-+}
-+
-+static
-+void write_mii_word(struct net_device *netdev, int phy_id, int reg, int val)
-+{
-+      struct r8152 *tp = netdev_priv(netdev);
-+
-+      if (phy_id != R8152_PHY_ID)
-+              return;
-+
-+      r8152_mdio_write(tp, reg, val);
-+}
-+
-+static
-+int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags);
-+
-+static inline void set_ethernet_addr(struct r8152 *tp)
-+{
-+      struct net_device *dev = tp->netdev;
-+      u8 node_id[8] = {0};
-+
-+      if (pla_ocp_read(tp, PLA_IDR, sizeof(node_id), node_id) < 0)
-+              netif_notice(tp, probe, dev, "inet addr fail\n");
-+      else {
-+              memcpy(dev->dev_addr, node_id, dev->addr_len);
-+              memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-+      }
-+}
-+
-+static int rtl8152_set_mac_address(struct net_device *netdev, void *p)
-+{
-+      struct r8152 *tp = netdev_priv(netdev);
-+      struct sockaddr *addr = p;
-+
-+      if (!is_valid_ether_addr(addr->sa_data))
-+              return -EADDRNOTAVAIL;
-+
-+      memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-+
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
-+      pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, addr->sa_data);
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
-+
-+      return 0;
-+}
-+
-+static struct net_device_stats *rtl8152_get_stats(struct net_device *dev)
-+{
-+      return &dev->stats;
-+}
-+
-+static void read_bulk_callback(struct urb *urb)
-+{
-+      struct net_device *netdev;
-+      unsigned long flags;
-+      int status = urb->status;
-+      struct rx_agg *agg;
-+      struct r8152 *tp;
-+      int result;
-+
-+      agg = urb->context;
-+      if (!agg)
-+              return;
-+
-+      tp = agg->context;
-+      if (!tp)
-+              return;
-+
-+      if (test_bit(RTL8152_UNPLUG, &tp->flags))
-+              return;
-+
-+      if (!test_bit(WORK_ENABLE, &tp->flags))
-+              return;
-+
-+      netdev = tp->netdev;
-+
-+      /* When link down, the driver would cancel all bulks. */
-+      /* This avoid the re-submitting bulk */
-+      if (!netif_carrier_ok(netdev))
-+              return;
-+
-+      switch (status) {
-+      case 0:
-+              if (urb->actual_length < ETH_ZLEN)
-+                      break;
-+
-+              spin_lock_irqsave(&tp->rx_lock, flags);
-+              list_add_tail(&agg->list, &tp->rx_done);
-+              spin_unlock_irqrestore(&tp->rx_lock, flags);
-+              tasklet_schedule(&tp->tl);
-+              return;
-+      case -ESHUTDOWN:
-+              set_bit(RTL8152_UNPLUG, &tp->flags);
-+              netif_device_detach(tp->netdev);
-+              return;
-+      case -ENOENT:
-+              return; /* the urb is in unlink state */
-+      case -ETIME:
-+              if (net_ratelimit())
-+                      netdev_warn(netdev, "maybe reset is needed?\n");
-+              break;
-+      default:
-+              if (net_ratelimit())
-+                      netdev_warn(netdev, "Rx status %d\n", status);
-+              break;
-+      }
-+
-+      result = r8152_submit_rx(tp, agg, GFP_ATOMIC);
-+      if (result == -ENODEV) {
-+              netif_device_detach(tp->netdev);
-+      } else if (result) {
-+              spin_lock_irqsave(&tp->rx_lock, flags);
-+              list_add_tail(&agg->list, &tp->rx_done);
-+              spin_unlock_irqrestore(&tp->rx_lock, flags);
-+              tasklet_schedule(&tp->tl);
-+      }
-+}
-+
-+static void write_bulk_callback(struct urb *urb)
-+{
-+      struct net_device_stats *stats;
-+      unsigned long flags;
-+      struct tx_agg *agg;
-+      struct r8152 *tp;
-+      int status = urb->status;
-+
-+      agg = urb->context;
-+      if (!agg)
-+              return;
-+
-+      tp = agg->context;
-+      if (!tp)
-+              return;
-+
-+      stats = rtl8152_get_stats(tp->netdev);
-+      if (status) {
-+              if (net_ratelimit())
-+                      netdev_warn(tp->netdev, "Tx status %d\n", status);
-+              stats->tx_errors += agg->skb_num;
-+      } else {
-+              stats->tx_packets += agg->skb_num;
-+              stats->tx_bytes += agg->skb_len;
-+      }
-+
-+      spin_lock_irqsave(&tp->tx_lock, flags);
-+      list_add_tail(&agg->list, &tp->tx_free);
-+      spin_unlock_irqrestore(&tp->tx_lock, flags);
-+
-+      if (!netif_carrier_ok(tp->netdev))
-+              return;
-+
-+      if (!test_bit(WORK_ENABLE, &tp->flags))
-+              return;
-+
-+      if (test_bit(RTL8152_UNPLUG, &tp->flags))
-+              return;
-+
-+      if (!skb_queue_empty(&tp->tx_queue))
-+              tasklet_schedule(&tp->tl);
-+}
-+
-+static void intr_callback(struct urb *urb)
-+{
-+      struct r8152 *tp;
-+      __le16 *d;
-+      int status = urb->status;
-+      int res;
-+
-+      tp = urb->context;
-+      if (!tp)
-+              return;
-+
-+      if (!test_bit(WORK_ENABLE, &tp->flags))
-+              return;
-+
-+      if (test_bit(RTL8152_UNPLUG, &tp->flags))
-+              return;
-+
-+      switch (status) {
-+      case 0:                 /* success */
-+              break;
-+      case -ECONNRESET:       /* unlink */
-+      case -ESHUTDOWN:
-+              netif_device_detach(tp->netdev);
-+      case -ENOENT:
-+              return;
-+      case -EOVERFLOW:
-+              netif_info(tp, intr, tp->netdev, "intr status -EOVERFLOW\n");
-+              goto resubmit;
-+      /* -EPIPE:  should clear the halt */
-+      default:
-+              netif_info(tp, intr, tp->netdev, "intr status %d\n", status);
-+              goto resubmit;
-+      }
-+
-+      d = urb->transfer_buffer;
-+      if (INTR_LINK & __le16_to_cpu(d[0])) {
-+              if (!(tp->speed & LINK_STATUS)) {
-+                      set_bit(RTL8152_LINK_CHG, &tp->flags);
-+                      schedule_delayed_work(&tp->schedule, 0);
-+              }
-+      } else {
-+              if (tp->speed & LINK_STATUS) {
-+                      set_bit(RTL8152_LINK_CHG, &tp->flags);
-+                      schedule_delayed_work(&tp->schedule, 0);
-+              }
-+      }
-+
-+resubmit:
-+      res = usb_submit_urb(urb, GFP_ATOMIC);
-+      if (res == -ENODEV)
-+              netif_device_detach(tp->netdev);
-+      else if (res)
-+              netif_err(tp, intr, tp->netdev,
-+                        "can't resubmit intr, status %d\n", res);
-+}
-+
-+static inline void *rx_agg_align(void *data)
-+{
-+      return (void *)ALIGN((uintptr_t)data, RX_ALIGN);
-+}
-+
-+static inline void *tx_agg_align(void *data)
-+{
-+      return (void *)ALIGN((uintptr_t)data, TX_ALIGN);
-+}
-+
-+static void free_all_mem(struct r8152 *tp)
-+{
-+      int i;
-+
-+      for (i = 0; i < RTL8152_MAX_RX; i++) {
-+              usb_free_urb(tp->rx_info[i].urb);
-+              tp->rx_info[i].urb = NULL;
-+
-+              kfree(tp->rx_info[i].buffer);
-+              tp->rx_info[i].buffer = NULL;
-+              tp->rx_info[i].head = NULL;
-+      }
-+
-+      for (i = 0; i < RTL8152_MAX_TX; i++) {
-+              usb_free_urb(tp->tx_info[i].urb);
-+              tp->tx_info[i].urb = NULL;
-+
-+              kfree(tp->tx_info[i].buffer);
-+              tp->tx_info[i].buffer = NULL;
-+              tp->tx_info[i].head = NULL;
-+      }
-+
-+      usb_free_urb(tp->intr_urb);
-+      tp->intr_urb = NULL;
-+
-+      kfree(tp->intr_buff);
-+      tp->intr_buff = NULL;
-+}
-+
-+static int alloc_all_mem(struct r8152 *tp)
-+{
-+      struct net_device *netdev = tp->netdev;
-+      struct usb_interface *intf = tp->intf;
-+      struct usb_host_interface *alt = intf->cur_altsetting;
-+      struct usb_host_endpoint *ep_intr = alt->endpoint + 2;
-+      struct urb *urb;
-+      int node, i;
-+      u8 *buf;
-+
-+      node = netdev->dev.parent ? dev_to_node(netdev->dev.parent) : -1;
-+
-+      spin_lock_init(&tp->rx_lock);
-+      spin_lock_init(&tp->tx_lock);
-+      INIT_LIST_HEAD(&tp->rx_done);
-+      INIT_LIST_HEAD(&tp->tx_free);
-+      skb_queue_head_init(&tp->tx_queue);
-+
-+      for (i = 0; i < RTL8152_MAX_RX; i++) {
-+              buf = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
-+              if (!buf)
-+                      goto err1;
-+
-+              if (buf != rx_agg_align(buf)) {
-+                      kfree(buf);
-+                      buf = kmalloc_node(rx_buf_sz + RX_ALIGN, GFP_KERNEL,
-+                                         node);
-+                      if (!buf)
-+                              goto err1;
-+              }
-+
-+              urb = usb_alloc_urb(0, GFP_KERNEL);
-+              if (!urb) {
-+                      kfree(buf);
-+                      goto err1;
-+              }
-+
-+              INIT_LIST_HEAD(&tp->rx_info[i].list);
-+              tp->rx_info[i].context = tp;
-+              tp->rx_info[i].urb = urb;
-+              tp->rx_info[i].buffer = buf;
-+              tp->rx_info[i].head = rx_agg_align(buf);
-+      }
-+
-+      for (i = 0; i < RTL8152_MAX_TX; i++) {
-+              buf = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
-+              if (!buf)
-+                      goto err1;
-+
-+              if (buf != tx_agg_align(buf)) {
-+                      kfree(buf);
-+                      buf = kmalloc_node(rx_buf_sz + TX_ALIGN, GFP_KERNEL,
-+                                         node);
-+                      if (!buf)
-+                              goto err1;
-+              }
-+
-+              urb = usb_alloc_urb(0, GFP_KERNEL);
-+              if (!urb) {
-+                      kfree(buf);
-+                      goto err1;
-+              }
-+
-+              INIT_LIST_HEAD(&tp->tx_info[i].list);
-+              tp->tx_info[i].context = tp;
-+              tp->tx_info[i].urb = urb;
-+              tp->tx_info[i].buffer = buf;
-+              tp->tx_info[i].head = tx_agg_align(buf);
-+
-+              list_add_tail(&tp->tx_info[i].list, &tp->tx_free);
-+      }
-+
-+      tp->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!tp->intr_urb)
-+              goto err1;
-+
-+      tp->intr_buff = kmalloc(INTBUFSIZE, GFP_KERNEL);
-+      if (!tp->intr_buff)
-+              goto err1;
-+
-+      tp->intr_interval = (int)ep_intr->desc.bInterval;
-+      usb_fill_int_urb(tp->intr_urb, tp->udev, usb_rcvintpipe(tp->udev, 3),
-+                   tp->intr_buff, INTBUFSIZE, intr_callback,
-+                   tp, tp->intr_interval);
-+
-+      return 0;
-+
-+err1:
-+      free_all_mem(tp);
-+      return -ENOMEM;
-+}
-+
-+static struct tx_agg *r8152_get_tx_agg(struct r8152 *tp)
-+{
-+      struct tx_agg *agg = NULL;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&tp->tx_lock, flags);
-+      if (!list_empty(&tp->tx_free)) {
-+              struct list_head *cursor;
-+
-+              cursor = tp->tx_free.next;
-+              list_del_init(cursor);
-+              agg = list_entry(cursor, struct tx_agg, list);
-+      }
-+      spin_unlock_irqrestore(&tp->tx_lock, flags);
-+
-+      return agg;
-+}
-+
-+static void
-+r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, struct sk_buff *skb)
-+{
-+      memset(desc, 0, sizeof(*desc));
-+
-+      desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | TX_LS);
-+
-+      if (skb->ip_summed == CHECKSUM_PARTIAL) {
-+              __be16 protocol;
-+              u8 ip_protocol;
-+              u32 opts2 = 0;
-+
-+              if (skb->protocol == htons(ETH_P_8021Q))
-+                      protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
-+              else
-+                      protocol = skb->protocol;
-+
-+              switch (protocol) {
-+              case htons(ETH_P_IP):
-+                      opts2 |= IPV4_CS;
-+                      ip_protocol = ip_hdr(skb)->protocol;
-+                      break;
-+
-+              case htons(ETH_P_IPV6):
-+                      opts2 |= IPV6_CS;
-+                      ip_protocol = ipv6_hdr(skb)->nexthdr;
-+                      break;
-+
-+              default:
-+                      ip_protocol = IPPROTO_RAW;
-+                      break;
-+              }
-+
-+              if (ip_protocol == IPPROTO_TCP) {
-+                      opts2 |= TCP_CS;
-+                      opts2 |= (skb_transport_offset(skb) & 0x7fff) << 17;
-+              } else if (ip_protocol == IPPROTO_UDP) {
-+                      opts2 |= UDP_CS;
-+              } else {
-+                      WARN_ON_ONCE(1);
-+              }
-+
-+              desc->opts2 = cpu_to_le32(opts2);
-+      }
-+}
-+
-+static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
-+{
-+      int remain;
-+      u8 *tx_data;
-+
-+      tx_data = agg->head;
-+      agg->skb_num = agg->skb_len = 0;
-+      remain = rx_buf_sz;
-+
-+      while (remain >= ETH_ZLEN + sizeof(struct tx_desc)) {
-+              struct tx_desc *tx_desc;
-+              struct sk_buff *skb;
-+              unsigned int len;
-+
-+              skb = skb_dequeue(&tp->tx_queue);
-+              if (!skb)
-+                      break;
-+
-+              remain -= sizeof(*tx_desc);
-+              len = skb->len;
-+              if (remain < len) {
-+                      skb_queue_head(&tp->tx_queue, skb);
-+                      break;
-+              }
-+
-+              tx_data = tx_agg_align(tx_data);
-+              tx_desc = (struct tx_desc *)tx_data;
-+              tx_data += sizeof(*tx_desc);
-+
-+              r8152_tx_csum(tp, tx_desc, skb);
-+              memcpy(tx_data, skb->data, len);
-+              agg->skb_num++;
-+              agg->skb_len += len;
-+              dev_kfree_skb_any(skb);
-+
-+              tx_data += len;
-+              remain = rx_buf_sz - (int)(tx_agg_align(tx_data) - agg->head);
-+      }
-+
-+      netif_tx_lock(tp->netdev);
-+
-+      if (netif_queue_stopped(tp->netdev) &&
-+          skb_queue_len(&tp->tx_queue) < tp->tx_qlen)
-+              netif_wake_queue(tp->netdev);
-+
-+      netif_tx_unlock(tp->netdev);
-+
-+      usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2),
-+                        agg->head, (int)(tx_data - (u8 *)agg->head),
-+                        (usb_complete_t)write_bulk_callback, agg);
-+
-+      return usb_submit_urb(agg->urb, GFP_ATOMIC);
-+}
-+
-+static void rx_bottom(struct r8152 *tp)
-+{
-+      unsigned long flags;
-+      struct list_head *cursor, *next;
-+
-+      spin_lock_irqsave(&tp->rx_lock, flags);
-+      list_for_each_safe(cursor, next, &tp->rx_done) {
-+              struct rx_desc *rx_desc;
-+              struct rx_agg *agg;
-+              int len_used = 0;
-+              struct urb *urb;
-+              u8 *rx_data;
-+              int ret;
-+
-+              list_del_init(cursor);
-+              spin_unlock_irqrestore(&tp->rx_lock, flags);
-+
-+              agg = list_entry(cursor, struct rx_agg, list);
-+              urb = agg->urb;
-+              if (urb->actual_length < ETH_ZLEN)
-+                      goto submit;
-+
-+              rx_desc = agg->head;
-+              rx_data = agg->head;
-+              len_used += sizeof(struct rx_desc);
-+
-+              while (urb->actual_length > len_used) {
-+                      struct net_device *netdev = tp->netdev;
-+                      struct net_device_stats *stats;
-+                      unsigned int pkt_len;
-+                      struct sk_buff *skb;
-+
-+                      pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
-+                      if (pkt_len < ETH_ZLEN)
-+                              break;
-+
-+                      len_used += pkt_len;
-+                      if (urb->actual_length < len_used)
-+                              break;
-+
-+                      stats = rtl8152_get_stats(netdev);
-+
-+                      pkt_len -= CRC_SIZE;
-+                      rx_data += sizeof(struct rx_desc);
-+
-+                      skb = netdev_alloc_skb_ip_align(netdev, pkt_len);
-+                      if (!skb) {
-+                              stats->rx_dropped++;
-+                              break;
-+                      }
-+                      memcpy(skb->data, rx_data, pkt_len);
-+                      skb_put(skb, pkt_len);
-+                      skb->protocol = eth_type_trans(skb, netdev);
-+                      netif_rx(skb);
-+                      stats->rx_packets++;
-+                      stats->rx_bytes += pkt_len;
-+
-+                      rx_data = rx_agg_align(rx_data + pkt_len + CRC_SIZE);
-+                      rx_desc = (struct rx_desc *)rx_data;
-+                      len_used = (int)(rx_data - (u8 *)agg->head);
-+                      len_used += sizeof(struct rx_desc);
-+              }
-+
-+submit:
-+              ret = r8152_submit_rx(tp, agg, GFP_ATOMIC);
-+              spin_lock_irqsave(&tp->rx_lock, flags);
-+              if (ret && ret != -ENODEV) {
-+                      list_add_tail(&agg->list, next);
-+                      tasklet_schedule(&tp->tl);
-+              }
-+      }
-+      spin_unlock_irqrestore(&tp->rx_lock, flags);
-+}
-+
-+static void tx_bottom(struct r8152 *tp)
-+{
-+      int res;
-+
-+      do {
-+              struct tx_agg *agg;
-+
-+              if (skb_queue_empty(&tp->tx_queue))
-+                      break;
-+
-+              agg = r8152_get_tx_agg(tp);
-+              if (!agg)
-+                      break;
-+
-+              res = r8152_tx_agg_fill(tp, agg);
-+              if (res) {
-+                      struct net_device_stats *stats;
-+                      struct net_device *netdev;
-+                      unsigned long flags;
-+
-+                      netdev = tp->netdev;
-+                      stats = rtl8152_get_stats(netdev);
-+
-+                      if (res == -ENODEV) {
-+                              netif_device_detach(netdev);
-+                      } else {
-+                              netif_warn(tp, tx_err, netdev,
-+                                         "failed tx_urb %d\n", res);
-+                              stats->tx_dropped += agg->skb_num;
-+                              spin_lock_irqsave(&tp->tx_lock, flags);
-+                              list_add_tail(&agg->list, &tp->tx_free);
-+                              spin_unlock_irqrestore(&tp->tx_lock, flags);
-+                      }
-+              }
-+      } while (res == 0);
-+}
-+
-+static void bottom_half(unsigned long data)
-+{
-+      struct r8152 *tp;
-+
-+      tp = (struct r8152 *)data;
-+
-+      if (test_bit(RTL8152_UNPLUG, &tp->flags))
-+              return;
-+
-+      if (!test_bit(WORK_ENABLE, &tp->flags))
-+              return;
-+
-+      /* When link down, the driver would cancel all bulks. */
-+      /* This avoid the re-submitting bulk */
-+      if (!netif_carrier_ok(tp->netdev))
-+              return;
-+
-+      rx_bottom(tp);
-+      tx_bottom(tp);
-+}
-+
-+static
-+int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags)
-+{
-+      usb_fill_bulk_urb(agg->urb, tp->udev, usb_rcvbulkpipe(tp->udev, 1),
-+                    agg->head, rx_buf_sz,
-+                    (usb_complete_t)read_bulk_callback, agg);
-+
-+      return usb_submit_urb(agg->urb, mem_flags);
-+}
-+
-+static void rtl8152_tx_timeout(struct net_device *netdev)
-+{
-+      struct r8152 *tp = netdev_priv(netdev);
-+      int i;
-+
-+      netif_warn(tp, tx_err, netdev, "Tx timeout\n");
-+      for (i = 0; i < RTL8152_MAX_TX; i++)
-+              usb_unlink_urb(tp->tx_info[i].urb);
-+}
-+
-+static void rtl8152_set_rx_mode(struct net_device *netdev)
-+{
-+      struct r8152 *tp = netdev_priv(netdev);
-+
-+      if (tp->speed & LINK_STATUS) {
-+              set_bit(RTL8152_SET_RX_MODE, &tp->flags);
-+              schedule_delayed_work(&tp->schedule, 0);
-+      }
-+}
-+
-+static void _rtl8152_set_rx_mode(struct net_device *netdev)
-+{
-+      struct r8152 *tp = netdev_priv(netdev);
-+      u32 mc_filter[2];       /* Multicast hash filter */
-+      __le32 tmp[2];
-+      u32 ocp_data;
-+
-+      clear_bit(RTL8152_SET_RX_MODE, &tp->flags);
-+      netif_stop_queue(netdev);
-+      ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
-+      ocp_data &= ~RCR_ACPT_ALL;
-+      ocp_data |= RCR_AB | RCR_APM;
-+
-+      if (netdev->flags & IFF_PROMISC) {
-+              /* Unconditionally log net taps. */
-+              netif_notice(tp, link, netdev, "Promiscuous mode enabled\n");
-+              ocp_data |= RCR_AM | RCR_AAP;
-+              mc_filter[1] = mc_filter[0] = 0xffffffff;
-+      } else if ((netdev_mc_count(netdev) > multicast_filter_limit) ||
-+                 (netdev->flags & IFF_ALLMULTI)) {
-+              /* Too many to filter perfectly -- accept all multicasts. */
-+              ocp_data |= RCR_AM;
-+              mc_filter[1] = mc_filter[0] = 0xffffffff;
-+      } else {
-+              struct netdev_hw_addr *ha;
-+
-+              mc_filter[1] = mc_filter[0] = 0;
-+              netdev_for_each_mc_addr(ha, netdev) {
-+                      int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
-+                      mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
-+                      ocp_data |= RCR_AM;
-+              }
-+      }
-+
-+      tmp[0] = __cpu_to_le32(swab32(mc_filter[1]));
-+      tmp[1] = __cpu_to_le32(swab32(mc_filter[0]));
-+
-+      pla_ocp_write(tp, PLA_MAR, BYTE_EN_DWORD, sizeof(tmp), tmp);
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
-+      netif_wake_queue(netdev);
-+}
-+
-+static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
-+                                          struct net_device *netdev)
-+{
-+      struct r8152 *tp = netdev_priv(netdev);
-+
-+      skb_tx_timestamp(skb);
-+
-+      skb_queue_tail(&tp->tx_queue, skb);
-+
-+      if (list_empty(&tp->tx_free) &&
-+          skb_queue_len(&tp->tx_queue) > tp->tx_qlen)
-+              netif_stop_queue(netdev);
-+
-+      if (!list_empty(&tp->tx_free))
-+              tasklet_schedule(&tp->tl);
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+static void r8152b_reset_packet_filter(struct r8152 *tp)
-+{
-+      u32     ocp_data;
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_FMC);
-+      ocp_data &= ~FMC_FCR_MCU_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_FMC, ocp_data);
-+      ocp_data |= FMC_FCR_MCU_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_FMC, ocp_data);
-+}
-+
-+static void rtl8152_nic_reset(struct r8152 *tp)
-+{
-+      int     i;
-+
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, CR_RST);
-+
-+      for (i = 0; i < 1000; i++) {
-+              if (!(ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR) & CR_RST))
-+                      break;
-+              udelay(100);
-+      }
-+}
-+
-+static void set_tx_qlen(struct r8152 *tp)
-+{
-+      struct net_device *netdev = tp->netdev;
-+
-+      tp->tx_qlen = rx_buf_sz / (netdev->mtu + VLAN_ETH_HLEN + VLAN_HLEN +
-+                                 sizeof(struct tx_desc));
-+}
-+
-+static inline u8 rtl8152_get_speed(struct r8152 *tp)
-+{
-+      return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS);
-+}
-+
-+static void rtl_set_eee_plus(struct r8152 *tp)
-+{
-+      u32 ocp_data;
-+      u8 speed;
-+
-+      speed = rtl8152_get_speed(tp);
-+      if (speed & _10bps) {
-+              ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
-+              ocp_data |= EEEP_CR_EEEP_TX;
-+              ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
-+      } else {
-+              ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
-+              ocp_data &= ~EEEP_CR_EEEP_TX;
-+              ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
-+      }
-+}
-+
-+static int rtl_enable(struct r8152 *tp)
-+{
-+      u32 ocp_data;
-+      int i, ret;
-+
-+      r8152b_reset_packet_filter(tp);
-+
-+      ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR);
-+      ocp_data |= CR_RE | CR_TE;
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
-+      ocp_data &= ~RXDY_GATED_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
-+
-+      INIT_LIST_HEAD(&tp->rx_done);
-+      ret = 0;
-+      for (i = 0; i < RTL8152_MAX_RX; i++) {
-+              INIT_LIST_HEAD(&tp->rx_info[i].list);
-+              ret |= r8152_submit_rx(tp, &tp->rx_info[i], GFP_KERNEL);
-+      }
-+
-+      return ret;
-+}
-+
-+static int rtl8152_enable(struct r8152 *tp)
-+{
-+      set_tx_qlen(tp);
-+      rtl_set_eee_plus(tp);
-+
-+      return rtl_enable(tp);
-+}
-+
-+static void r8153_set_rx_agg(struct r8152 *tp)
-+{
-+      u8 speed;
-+
-+      speed = rtl8152_get_speed(tp);
-+      if (speed & _1000bps) {
-+              if (tp->udev->speed == USB_SPEED_SUPER) {
-+                      ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH,
-+                                      RX_THR_SUPPER);
-+                      ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_EARLY_AGG,
-+                                      EARLY_AGG_SUPPER);
-+              } else {
-+                      ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH,
-+                                      RX_THR_HIGH);
-+                      ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_EARLY_AGG,
-+                                      EARLY_AGG_HIGH);
-+              }
-+      } else {
-+              ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_SLOW);
-+              ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_EARLY_AGG,
-+                              EARLY_AGG_SLOW);
-+      }
-+}
-+
-+static int rtl8153_enable(struct r8152 *tp)
-+{
-+      set_tx_qlen(tp);
-+      rtl_set_eee_plus(tp);
-+      r8153_set_rx_agg(tp);
-+
-+      return rtl_enable(tp);
-+}
-+
-+static void rtl8152_disable(struct r8152 *tp)
-+{
-+      struct net_device_stats *stats = rtl8152_get_stats(tp->netdev);
-+      struct sk_buff *skb;
-+      u32 ocp_data;
-+      int i;
-+
-+      ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
-+      ocp_data &= ~RCR_ACPT_ALL;
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
-+
-+      while ((skb = skb_dequeue(&tp->tx_queue))) {
-+              dev_kfree_skb(skb);
-+              stats->tx_dropped++;
-+      }
-+
-+      for (i = 0; i < RTL8152_MAX_TX; i++)
-+              usb_kill_urb(tp->tx_info[i].urb);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
-+      ocp_data |= RXDY_GATED_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
-+
-+      for (i = 0; i < 1000; i++) {
-+              ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+              if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
-+                      break;
-+              mdelay(1);
-+      }
-+
-+      for (i = 0; i < 1000; i++) {
-+              if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
-+                      break;
-+              mdelay(1);
-+      }
-+
-+      for (i = 0; i < RTL8152_MAX_RX; i++)
-+              usb_kill_urb(tp->rx_info[i].urb);
-+
-+      rtl8152_nic_reset(tp);
-+}
-+
-+static void r8152b_exit_oob(struct r8152 *tp)
-+{
-+      u32     ocp_data;
-+      int     i;
-+
-+      ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
-+      ocp_data &= ~RCR_ACPT_ALL;
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
-+      ocp_data |= RXDY_GATED_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
-+
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, 0x00);
-+
-+      ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+      ocp_data &= ~NOW_IS_OOB;
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
-+      ocp_data &= ~MCU_BORW_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
-+
-+      for (i = 0; i < 1000; i++) {
-+              ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+              if (ocp_data & LINK_LIST_READY)
-+                      break;
-+              mdelay(1);
-+      }
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
-+      ocp_data |= RE_INIT_LL;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
-+
-+      for (i = 0; i < 1000; i++) {
-+              ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+              if (ocp_data & LINK_LIST_READY)
-+                      break;
-+              mdelay(1);
-+      }
-+
-+      rtl8152_nic_reset(tp);
-+
-+      /* rx share fifo credit full threshold */
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_DEV_STAT);
-+      ocp_data &= STAT_SPEED_MASK;
-+      if (ocp_data == STAT_SPEED_FULL) {
-+              /* rx share fifo credit near full threshold */
-+              ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
-+                              RXFIFO_THR2_FULL);
-+              ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
-+                              RXFIFO_THR3_FULL);
-+      } else {
-+              /* rx share fifo credit near full threshold */
-+              ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
-+                              RXFIFO_THR2_HIGH);
-+              ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
-+                              RXFIFO_THR3_HIGH);
-+      }
-+
-+      /* TX share fifo free credit full threshold */
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL);
-+
-+      ocp_write_byte(tp, MCU_TYPE_USB, USB_TX_AGG, TX_AGG_MAX_THRESHOLD);
-+      ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_HIGH);
-+      ocp_write_dword(tp, MCU_TYPE_USB, USB_TX_DMA,
-+                      TEST_MODE_DISABLE | TX_SIZE_ADJUST1);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
-+      ocp_data &= ~CPCR_RX_VLAN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
-+
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);
-+      ocp_data |= TCR0_AUTO_FIFO;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data);
-+}
-+
-+static void r8152b_enter_oob(struct r8152 *tp)
-+{
-+      u32 ocp_data;
-+      int i;
-+
-+      ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+      ocp_data &= ~NOW_IS_OOB;
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
-+
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_OOB);
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB);
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB);
-+
-+      rtl8152_disable(tp);
-+
-+      for (i = 0; i < 1000; i++) {
-+              ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+              if (ocp_data & LINK_LIST_READY)
-+                      break;
-+              mdelay(1);
-+      }
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
-+      ocp_data |= RE_INIT_LL;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
-+
-+      for (i = 0; i < 1000; i++) {
-+              ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+              if (ocp_data & LINK_LIST_READY)
-+                      break;
-+              mdelay(1);
-+      }
-+
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
-+      ocp_data |= MAGIC_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
-+      ocp_data |= CPCR_RX_VLAN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
-+      ocp_data |= ALDPS_PROXY_MODE;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
-+
-+      ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+      ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
-+
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG5, LAN_WAKE_EN);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
-+      ocp_data &= ~RXDY_GATED_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
-+
-+      ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
-+      ocp_data |= RCR_APM | RCR_AM | RCR_AB;
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
-+}
-+
-+static void r8152b_disable_aldps(struct r8152 *tp)
-+{
-+      ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE);
-+      msleep(20);
-+}
-+
-+static inline void r8152b_enable_aldps(struct r8152 *tp)
-+{
-+      ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS |
-+                                          LINKENA | DIS_SDSAVE);
-+}
-+
-+static void r8153_hw_phy_cfg(struct r8152 *tp)
-+{
-+      u32 ocp_data;
-+      u16 data;
-+
-+      ocp_reg_write(tp, OCP_ADC_CFG, CKADSEL_L | ADC_EN | EN_EMI_L);
-+      r8152_mdio_write(tp, MII_BMCR, BMCR_ANENABLE);
-+
-+      if (tp->version == RTL_VER_03) {
-+              data = ocp_reg_read(tp, OCP_EEE_CFG);
-+              data &= ~CTAP_SHORT_EN;
-+              ocp_reg_write(tp, OCP_EEE_CFG, data);
-+      }
-+
-+      data = ocp_reg_read(tp, OCP_POWER_CFG);
-+      data |= EEE_CLKDIV_EN;
-+      ocp_reg_write(tp, OCP_POWER_CFG, data);
-+
-+      data = ocp_reg_read(tp, OCP_DOWN_SPEED);
-+      data |= EN_10M_BGOFF;
-+      ocp_reg_write(tp, OCP_DOWN_SPEED, data);
-+      data = ocp_reg_read(tp, OCP_POWER_CFG);
-+      data |= EN_10M_PLLOFF;
-+      ocp_reg_write(tp, OCP_POWER_CFG, data);
-+      data = sram_read(tp, SRAM_IMPEDANCE);
-+      data &= ~RX_DRIVING_MASK;
-+      sram_write(tp, SRAM_IMPEDANCE, data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
-+      ocp_data |= PFM_PWM_SWITCH;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
-+
-+      data = sram_read(tp, SRAM_LPF_CFG);
-+      data |= LPF_AUTO_TUNE;
-+      sram_write(tp, SRAM_LPF_CFG, data);
-+
-+      data = sram_read(tp, SRAM_10M_AMP1);
-+      data |= GDAC_IB_UPALL;
-+      sram_write(tp, SRAM_10M_AMP1, data);
-+      data = sram_read(tp, SRAM_10M_AMP2);
-+      data |= AMP_DN;
-+      sram_write(tp, SRAM_10M_AMP2, data);
-+}
-+
-+static void r8153_u1u2en(struct r8152 *tp, int enable)
-+{
-+      u8 u1u2[8];
-+
-+      if (enable)
-+              memset(u1u2, 0xff, sizeof(u1u2));
-+      else
-+              memset(u1u2, 0x00, sizeof(u1u2));
-+
-+      usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2);
-+}
-+
-+static void r8153_u2p3en(struct r8152 *tp, int enable)
-+{
-+      u32 ocp_data;
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL);
-+      if (enable)
-+              ocp_data |= U2P3_ENABLE;
-+      else
-+              ocp_data &= ~U2P3_ENABLE;
-+      ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data);
-+}
-+
-+static void r8153_power_cut_en(struct r8152 *tp, int enable)
-+{
-+      u32 ocp_data;
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_POWER_CUT);
-+      if (enable)
-+              ocp_data |= PWR_EN | PHASE2_EN;
-+      else
-+              ocp_data &= ~(PWR_EN | PHASE2_EN);
-+      ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
-+      ocp_data &= ~PCUT_STATUS;
-+      ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
-+}
-+
-+static void r8153_teredo_off(struct r8152 *tp)
-+{
-+      u32 ocp_data;
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
-+      ocp_data &= ~(TEREDO_SEL | TEREDO_RS_EVENT_MASK | OOB_TEREDO_EN);
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
-+
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_WDT6_CTRL, WDT6_SET_MODE);
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_REALWOW_TIMER, 0);
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TEREDO_TIMER, 0);
-+}
-+
-+static void r8153_first_init(struct r8152 *tp)
-+{
-+      u32 ocp_data;
-+      int i;
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
-+      ocp_data |= RXDY_GATED_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
-+
-+      r8153_teredo_off(tp);
-+
-+      ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
-+      ocp_data &= ~RCR_ACPT_ALL;
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
-+
-+      r8153_hw_phy_cfg(tp);
-+
-+      rtl8152_nic_reset(tp);
-+
-+      ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+      ocp_data &= ~NOW_IS_OOB;
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
-+      ocp_data &= ~MCU_BORW_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
-+
-+      for (i = 0; i < 1000; i++) {
-+              ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+              if (ocp_data & LINK_LIST_READY)
-+                      break;
-+              mdelay(1);
-+      }
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
-+      ocp_data |= RE_INIT_LL;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
-+
-+      for (i = 0; i < 1000; i++) {
-+              ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+              if (ocp_data & LINK_LIST_READY)
-+                      break;
-+              mdelay(1);
-+      }
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
-+      ocp_data &= ~CPCR_RX_VLAN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
-+
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);
-+      ocp_data |= TCR0_AUTO_FIFO;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data);
-+
-+      rtl8152_nic_reset(tp);
-+
-+      /* rx share fifo credit full threshold */
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL);
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_NORMAL);
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_NORMAL);
-+      /* TX share fifo free credit full threshold */
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL2);
-+
-+      /* rx aggregation */
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
-+      ocp_data &= ~RX_AGG_DISABLE;
-+      ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
-+}
-+
-+static void r8153_enter_oob(struct r8152 *tp)
-+{
-+      u32 ocp_data;
-+      int i;
-+
-+      ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+      ocp_data &= ~NOW_IS_OOB;
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
-+
-+      rtl8152_disable(tp);
-+
-+      for (i = 0; i < 1000; i++) {
-+              ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+              if (ocp_data & LINK_LIST_READY)
-+                      break;
-+              mdelay(1);
-+      }
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
-+      ocp_data |= RE_INIT_LL;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
-+
-+      for (i = 0; i < 1000; i++) {
-+              ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+              if (ocp_data & LINK_LIST_READY)
-+                      break;
-+              mdelay(1);
-+      }
-+
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL);
-+      ocp_data |= MAGIC_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
-+      ocp_data &= ~TEREDO_WAKE_MASK;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
-+      ocp_data |= CPCR_RX_VLAN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
-+      ocp_data |= ALDPS_PROXY_MODE;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
-+
-+      ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-+      ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
-+
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG5, LAN_WAKE_EN);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
-+      ocp_data &= ~RXDY_GATED_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
-+
-+      ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
-+      ocp_data |= RCR_APM | RCR_AM | RCR_AB;
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
-+}
-+
-+static void r8153_disable_aldps(struct r8152 *tp)
-+{
-+      u16 data;
-+
-+      data = ocp_reg_read(tp, OCP_POWER_CFG);
-+      data &= ~EN_ALDPS;
-+      ocp_reg_write(tp, OCP_POWER_CFG, data);
-+      msleep(20);
-+}
-+
-+static void r8153_enable_aldps(struct r8152 *tp)
-+{
-+      u16 data;
-+
-+      data = ocp_reg_read(tp, OCP_POWER_CFG);
-+      data |= EN_ALDPS;
-+      ocp_reg_write(tp, OCP_POWER_CFG, data);
-+}
-+
-+static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
-+{
-+      u16 bmcr, anar, gbcr;
-+      int ret = 0;
-+
-+      cancel_delayed_work_sync(&tp->schedule);
-+      anar = r8152_mdio_read(tp, MII_ADVERTISE);
-+      anar &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
-+                ADVERTISE_100HALF | ADVERTISE_100FULL);
-+      if (tp->mii.supports_gmii) {
-+              gbcr = r8152_mdio_read(tp, MII_CTRL1000);
-+              gbcr &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
-+      } else {
-+              gbcr = 0;
-+      }
-+
-+      if (autoneg == AUTONEG_DISABLE) {
-+              if (speed == SPEED_10) {
-+                      bmcr = 0;
-+                      anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
-+              } else if (speed == SPEED_100) {
-+                      bmcr = BMCR_SPEED100;
-+                      anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
-+              } else if (speed == SPEED_1000 && tp->mii.supports_gmii) {
-+                      bmcr = BMCR_SPEED1000;
-+                      gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
-+              } else {
-+                      ret = -EINVAL;
-+                      goto out;
-+              }
-+
-+              if (duplex == DUPLEX_FULL)
-+                      bmcr |= BMCR_FULLDPLX;
-+      } else {
-+              if (speed == SPEED_10) {
-+                      if (duplex == DUPLEX_FULL)
-+                              anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
-+                      else
-+                              anar |= ADVERTISE_10HALF;
-+              } else if (speed == SPEED_100) {
-+                      if (duplex == DUPLEX_FULL) {
-+                              anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
-+                              anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
-+                      } else {
-+                              anar |= ADVERTISE_10HALF;
-+                              anar |= ADVERTISE_100HALF;
-+                      }
-+              } else if (speed == SPEED_1000 && tp->mii.supports_gmii) {
-+                      if (duplex == DUPLEX_FULL) {
-+                              anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
-+                              anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
-+                              gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
-+                      } else {
-+                              anar |= ADVERTISE_10HALF;
-+                              anar |= ADVERTISE_100HALF;
-+                              gbcr |= ADVERTISE_1000HALF;
-+                      }
-+              } else {
-+                      ret = -EINVAL;
-+                      goto out;
-+              }
-+
-+              bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
-+      }
-+
-+      if (tp->mii.supports_gmii)
-+              r8152_mdio_write(tp, MII_CTRL1000, gbcr);
-+
-+      r8152_mdio_write(tp, MII_ADVERTISE, anar);
-+      r8152_mdio_write(tp, MII_BMCR, bmcr);
-+
-+out:
-+
-+      return ret;
-+}
-+
-+static void rtl8152_down(struct r8152 *tp)
-+{
-+      u32     ocp_data;
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL);
-+      ocp_data &= ~POWER_CUT;
-+      ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
-+
-+      r8152b_disable_aldps(tp);
-+      r8152b_enter_oob(tp);
-+      r8152b_enable_aldps(tp);
-+}
-+
-+static void rtl8153_down(struct r8152 *tp)
-+{
-+      r8153_u1u2en(tp, 0);
-+      r8153_power_cut_en(tp, 0);
-+      r8153_disable_aldps(tp);
-+      r8153_enter_oob(tp);
-+      r8153_enable_aldps(tp);
-+}
-+
-+static void set_carrier(struct r8152 *tp)
-+{
-+      struct net_device *netdev = tp->netdev;
-+      u8 speed;
-+
-+      clear_bit(RTL8152_LINK_CHG, &tp->flags);
-+      speed = rtl8152_get_speed(tp);
-+
-+      if (speed & LINK_STATUS) {
-+              if (!(tp->speed & LINK_STATUS)) {
-+                      tp->rtl_ops.enable(tp);
-+                      set_bit(RTL8152_SET_RX_MODE, &tp->flags);
-+                      netif_carrier_on(netdev);
-+              }
-+      } else {
-+              if (tp->speed & LINK_STATUS) {
-+                      netif_carrier_off(netdev);
-+                      tasklet_disable(&tp->tl);
-+                      tp->rtl_ops.disable(tp);
-+                      tasklet_enable(&tp->tl);
-+              }
-+      }
-+      tp->speed = speed;
-+}
-+
-+static void rtl_work_func_t(struct work_struct *work)
-+{
-+      struct r8152 *tp = container_of(work, struct r8152, schedule.work);
-+
-+      if (!test_bit(WORK_ENABLE, &tp->flags))
-+              goto out1;
-+
-+      if (test_bit(RTL8152_UNPLUG, &tp->flags))
-+              goto out1;
-+
-+      if (test_bit(RTL8152_LINK_CHG, &tp->flags))
-+              set_carrier(tp);
-+
-+      if (test_bit(RTL8152_SET_RX_MODE, &tp->flags))
-+              _rtl8152_set_rx_mode(tp->netdev);
-+
-+out1:
-+      return;
-+}
-+
-+static int rtl8152_open(struct net_device *netdev)
-+{
-+      struct r8152 *tp = netdev_priv(netdev);
-+      int res = 0;
-+
-+      rtl8152_set_speed(tp, AUTONEG_ENABLE,
-+                        tp->mii.supports_gmii ? SPEED_1000 : SPEED_100,
-+                        DUPLEX_FULL);
-+      tp->speed = 0;
-+      netif_carrier_off(netdev);
-+      netif_start_queue(netdev);
-+      set_bit(WORK_ENABLE, &tp->flags);
-+      res = usb_submit_urb(tp->intr_urb, GFP_KERNEL);
-+      if (res) {
-+              if (res == -ENODEV)
-+                      netif_device_detach(tp->netdev);
-+              netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n",
-+                         res);
-+      }
-+
-+
-+      return res;
-+}
-+
-+static int rtl8152_close(struct net_device *netdev)
-+{
-+      struct r8152 *tp = netdev_priv(netdev);
-+      int res = 0;
-+
-+      clear_bit(WORK_ENABLE, &tp->flags);
-+      usb_kill_urb(tp->intr_urb);
-+      cancel_delayed_work_sync(&tp->schedule);
-+      netif_stop_queue(netdev);
-+      tasklet_disable(&tp->tl);
-+      tp->rtl_ops.disable(tp);
-+      tasklet_enable(&tp->tl);
-+
-+      return res;
-+}
-+
-+static void rtl_clear_bp(struct r8152 *tp)
-+{
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_0, 0);
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_2, 0);
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_4, 0);
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_6, 0);
-+      ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_0, 0);
-+      ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_2, 0);
-+      ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_4, 0);
-+      ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_6, 0);
-+      mdelay(3);
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_BA, 0);
-+      ocp_write_word(tp, MCU_TYPE_USB, USB_BP_BA, 0);
-+}
-+
-+static void r8153_clear_bp(struct r8152 *tp)
-+{
-+      ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0);
-+      ocp_write_byte(tp, MCU_TYPE_USB, USB_BP_EN, 0);
-+      rtl_clear_bp(tp);
-+}
-+
-+static void r8152b_enable_eee(struct r8152 *tp)
-+{
-+      u32 ocp_data;
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR);
-+      ocp_data |= EEE_RX_EN | EEE_TX_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data);
-+      ocp_reg_write(tp, OCP_EEE_CONFIG1, RG_TXLPI_MSK_HFDUP | RG_MATCLR_EN |
-+                                         EEE_10_CAP | EEE_NWAY_EN |
-+                                         TX_QUIET_EN | RX_QUIET_EN |
-+                                         SDRISETIME | RG_RXLPI_MSK_HFDUP |
-+                                         SDFALLTIME);
-+      ocp_reg_write(tp, OCP_EEE_CONFIG2, RG_LPIHYS_NUM | RG_DACQUIET_EN |
-+                                         RG_LDVQUIET_EN | RG_CKRSEL |
-+                                         RG_EEEPRG_EN);
-+      ocp_reg_write(tp, OCP_EEE_CONFIG3, FST_SNR_EYE_R | RG_LFS_SEL | MSK_PH);
-+      ocp_reg_write(tp, OCP_EEE_AR, FUN_ADDR | DEVICE_ADDR);
-+      ocp_reg_write(tp, OCP_EEE_DATA, EEE_ADDR);
-+      ocp_reg_write(tp, OCP_EEE_AR, FUN_DATA | DEVICE_ADDR);
-+      ocp_reg_write(tp, OCP_EEE_DATA, EEE_DATA);
-+      ocp_reg_write(tp, OCP_EEE_AR, 0x0000);
-+}
-+
-+static void r8153_enable_eee(struct r8152 *tp)
-+{
-+      u32 ocp_data;
-+      u16 data;
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEE_CR);
-+      ocp_data |= EEE_RX_EN | EEE_TX_EN;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data);
-+      data = ocp_reg_read(tp, OCP_EEE_CFG);
-+      data |= EEE10_EN;
-+      ocp_reg_write(tp, OCP_EEE_CFG, data);
-+      data = ocp_reg_read(tp, OCP_EEE_CFG2);
-+      data |= MY1000_EEE | MY100_EEE;
-+      ocp_reg_write(tp, OCP_EEE_CFG2, data);
-+}
-+
-+static void r8152b_enable_fc(struct r8152 *tp)
-+{
-+      u16 anar;
-+
-+      anar = r8152_mdio_read(tp, MII_ADVERTISE);
-+      anar |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
-+      r8152_mdio_write(tp, MII_ADVERTISE, anar);
-+}
-+
-+static void r8152b_hw_phy_cfg(struct r8152 *tp)
-+{
-+      r8152_mdio_write(tp, MII_BMCR, BMCR_ANENABLE);
-+      r8152b_disable_aldps(tp);
-+}
-+
-+static void r8152b_init(struct r8152 *tp)
-+{
-+      u32 ocp_data;
-+      int i;
-+
-+      rtl_clear_bp(tp);
-+
-+      if (tp->version == RTL_VER_01) {
-+              ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
-+              ocp_data &= ~LED_MODE_MASK;
-+              ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
-+      }
-+
-+      r8152b_hw_phy_cfg(tp);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL);
-+      ocp_data &= ~POWER_CUT;
-+      ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
-+      ocp_data &= ~RESUME_INDICATE;
-+      ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
-+
-+      r8152b_exit_oob(tp);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
-+      ocp_data |= TX_10M_IDLE_EN | PFM_PWM_SWITCH;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
-+      ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL);
-+      ocp_data &= ~MCU_CLK_RATIO_MASK;
-+      ocp_data |= MCU_CLK_RATIO | D3_CLK_GATED_EN;
-+      ocp_write_dword(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ocp_data);
-+      ocp_data = GPHY_STS_MSK | SPEED_DOWN_MSK |
-+                 SPDWN_RXDV_MSK | SPDWN_LINKCHG_MSK;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_GPHY_INTR_IMR, ocp_data);
-+
-+      r8152b_enable_eee(tp);
-+      r8152b_enable_aldps(tp);
-+      r8152b_enable_fc(tp);
-+
-+      r8152_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE |
-+                                     BMCR_ANRESTART);
-+      for (i = 0; i < 100; i++) {
-+              udelay(100);
-+              if (!(r8152_mdio_read(tp, MII_BMCR) & BMCR_RESET))
-+                      break;
-+      }
-+
-+      /* enable rx aggregation */
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
-+      ocp_data &= ~RX_AGG_DISABLE;
-+      ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
-+}
-+
-+static void r8153_init(struct r8152 *tp)
-+{
-+      u32 ocp_data;
-+      int i;
-+
-+      r8153_u1u2en(tp, 0);
-+
-+      for (i = 0; i < 500; i++) {
-+              if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
-+                  AUTOLOAD_DONE)
-+                      break;
-+              msleep(20);
-+      }
-+
-+      for (i = 0; i < 500; i++) {
-+              ocp_data = ocp_reg_read(tp, OCP_PHY_STATUS) & PHY_STAT_MASK;
-+              if (ocp_data == PHY_STAT_LAN_ON || ocp_data == PHY_STAT_PWRDN)
-+                      break;
-+              msleep(20);
-+      }
-+
-+      r8153_u2p3en(tp, 0);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL);
-+      ocp_data &= ~TIMER11_EN;
-+      ocp_write_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL, ocp_data);
-+
-+      r8153_clear_bp(tp);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
-+      ocp_data &= ~LED_MODE_MASK;
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
-+
-+      ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_LPM_CTRL);
-+      ocp_data &= ~LPM_TIMER_MASK;
-+      if (tp->udev->speed == USB_SPEED_SUPER)
-+              ocp_data |= LPM_TIMER_500US;
-+      else
-+              ocp_data |= LPM_TIMER_500MS;
-+      ocp_write_byte(tp, MCU_TYPE_USB, USB_LPM_CTRL, ocp_data);
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2);
-+      ocp_data &= ~SEN_VAL_MASK;
-+      ocp_data |= SEN_VAL_NORMAL | SEL_RXIDLE;
-+      ocp_write_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2, ocp_data);
-+
-+      r8153_power_cut_en(tp, 0);
-+      r8153_u1u2en(tp, 1);
-+
-+      r8153_first_init(tp);
-+
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ALDPS_SPDWN_RATIO);
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, EEE_SPDWN_RATIO);
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,
-+                     PKT_AVAIL_SPDWN_EN | SUSPEND_SPDWN_EN |
-+                     U1U2_SPDWN_EN | L1_SPDWN_EN);
-+      ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
-+                     PWRSAVE_SPDWN_EN | RXDV_SPDWN_EN | TX10MIDLE_EN |
-+                     TP100_SPDWN_EN | TP500_SPDWN_EN | TP1000_SPDWN_EN |
-+                     EEE_SPDWN_EN);
-+
-+      r8153_enable_eee(tp);
-+      r8153_enable_aldps(tp);
-+      r8152b_enable_fc(tp);
-+
-+      r8152_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE |
-+                                     BMCR_ANRESTART);
-+}
-+
-+static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
-+{
-+      struct r8152 *tp = usb_get_intfdata(intf);
-+
-+      netif_device_detach(tp->netdev);
-+
-+      if (netif_running(tp->netdev)) {
-+              clear_bit(WORK_ENABLE, &tp->flags);
-+              usb_kill_urb(tp->intr_urb);
-+              cancel_delayed_work_sync(&tp->schedule);
-+              tasklet_disable(&tp->tl);
-+      }
-+
-+      tp->rtl_ops.down(tp);
-+
-+      return 0;
-+}
-+
-+static int rtl8152_resume(struct usb_interface *intf)
-+{
-+      struct r8152 *tp = usb_get_intfdata(intf);
-+
-+      tp->rtl_ops.init(tp);
-+      netif_device_attach(tp->netdev);
-+      if (netif_running(tp->netdev)) {
-+              rtl8152_set_speed(tp, AUTONEG_ENABLE,
-+                              tp->mii.supports_gmii ? SPEED_1000 : SPEED_100,
-+                              DUPLEX_FULL);
-+              tp->speed = 0;
-+              netif_carrier_off(tp->netdev);
-+              set_bit(WORK_ENABLE, &tp->flags);
-+              usb_submit_urb(tp->intr_urb, GFP_KERNEL);
-+              tasklet_enable(&tp->tl);
-+      }
-+
-+      return 0;
-+}
-+
-+static void rtl8152_get_drvinfo(struct net_device *netdev,
-+                              struct ethtool_drvinfo *info)
-+{
-+      struct r8152 *tp = netdev_priv(netdev);
-+
-+      strncpy(info->driver, MODULENAME, ETHTOOL_BUSINFO_LEN);
-+      strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
-+      usb_make_path(tp->udev, info->bus_info, sizeof(info->bus_info));
-+}
-+
-+static
-+int rtl8152_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
-+{
-+      struct r8152 *tp = netdev_priv(netdev);
-+
-+      if (!tp->mii.mdio_read)
-+              return -EOPNOTSUPP;
-+
-+      return mii_ethtool_gset(&tp->mii, cmd);
-+}
-+
-+static int rtl8152_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-+{
-+      struct r8152 *tp = netdev_priv(dev);
-+
-+      return rtl8152_set_speed(tp, cmd->autoneg, cmd->speed, cmd->duplex);
-+}
-+
-+static struct ethtool_ops ops = {
-+      .get_drvinfo = rtl8152_get_drvinfo,
-+      .get_settings = rtl8152_get_settings,
-+      .set_settings = rtl8152_set_settings,
-+      .get_link = ethtool_op_get_link,
-+};
-+
-+static int rtl8152_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
-+{
-+      struct r8152 *tp = netdev_priv(netdev);
-+      struct mii_ioctl_data *data = if_mii(rq);
-+      int res = 0;
-+
-+      switch (cmd) {
-+      case SIOCGMIIPHY:
-+              data->phy_id = R8152_PHY_ID; /* Internal PHY */
-+              break;
-+
-+      case SIOCGMIIREG:
-+              data->val_out = r8152_mdio_read(tp, data->reg_num);
-+              break;
-+
-+      case SIOCSMIIREG:
-+              if (!capable(CAP_NET_ADMIN)) {
-+                      res = -EPERM;
-+                      break;
-+              }
-+              r8152_mdio_write(tp, data->reg_num, data->val_in);
-+              break;
-+
-+      default:
-+              res = -EOPNOTSUPP;
-+      }
-+
-+      return res;
-+}
-+
-+static const struct net_device_ops rtl8152_netdev_ops = {
-+      .ndo_open               = rtl8152_open,
-+      .ndo_stop               = rtl8152_close,
-+      .ndo_do_ioctl           = rtl8152_ioctl,
-+      .ndo_start_xmit         = rtl8152_start_xmit,
-+      .ndo_tx_timeout         = rtl8152_tx_timeout,
-+      .ndo_set_rx_mode        = rtl8152_set_rx_mode,
-+      .ndo_set_mac_address    = rtl8152_set_mac_address,
-+
-+      .ndo_change_mtu         = eth_change_mtu,
-+      .ndo_validate_addr      = eth_validate_addr,
-+};
-+
-+static void r8152b_get_version(struct r8152 *tp)
-+{
-+      u32     ocp_data;
-+      u16     version;
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR1);
-+      version = (u16)(ocp_data & VERSION_MASK);
-+
-+      switch (version) {
-+      case 0x4c00:
-+              tp->version = RTL_VER_01;
-+              break;
-+      case 0x4c10:
-+              tp->version = RTL_VER_02;
-+              break;
-+      case 0x5c00:
-+              tp->version = RTL_VER_03;
-+              tp->mii.supports_gmii = 1;
-+              break;
-+      case 0x5c10:
-+              tp->version = RTL_VER_04;
-+              tp->mii.supports_gmii = 1;
-+              break;
-+      case 0x5c20:
-+              tp->version = RTL_VER_05;
-+              tp->mii.supports_gmii = 1;
-+              break;
-+      default:
-+              netif_info(tp, probe, tp->netdev,
-+                         "Unknown version 0x%04x\n", version);
-+              break;
-+      }
-+}
-+
-+static void rtl8152_unload(struct r8152 *tp)
-+{
-+      u32     ocp_data;
-+
-+      if (tp->version != RTL_VER_01) {
-+              ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL);
-+              ocp_data |= POWER_CUT;
-+              ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
-+      }
-+
-+      ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
-+      ocp_data &= ~RESUME_INDICATE;
-+      ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
-+}
-+
-+static void rtl8153_unload(struct r8152 *tp)
-+{
-+      r8153_power_cut_en(tp, 1);
-+}
-+
-+static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id)
-+{
-+      struct rtl_ops *ops = &tp->rtl_ops;
-+      int ret = -ENODEV;
-+
-+      switch (id->idVendor) {
-+      case VENDOR_ID_REALTEK:
-+              switch (id->idProduct) {
-+              case PRODUCT_ID_RTL8152:
-+                      ops->init               = r8152b_init;
-+                      ops->enable             = rtl8152_enable;
-+                      ops->disable            = rtl8152_disable;
-+                      ops->down               = rtl8152_down;
-+                      ops->unload             = rtl8152_unload;
-+                      ret = 0;
-+                      break;
-+              case PRODUCT_ID_RTL8153:
-+                      ops->init               = r8153_init;
-+                      ops->enable             = rtl8153_enable;
-+                      ops->disable            = rtl8152_disable;
-+                      ops->down               = rtl8153_down;
-+                      ops->unload             = rtl8153_unload;
-+                      ret = 0;
-+                      break;
-+              default:
-+                      break;
-+              }
-+              break;
-+
-+      case VENDOR_ID_SAMSUNG:
-+              switch (id->idProduct) {
-+              case PRODUCT_ID_SAMSUNG:
-+                      ops->init               = r8153_init;
-+                      ops->enable             = rtl8153_enable;
-+                      ops->disable            = rtl8152_disable;
-+                      ops->down               = rtl8153_down;
-+                      ops->unload             = rtl8153_unload;
-+                      ret = 0;
-+                      break;
-+              default:
-+                      break;
-+              }
-+              break;
-+
-+      default:
-+              break;
-+      }
-+
-+      if (ret)
-+              netif_err(tp, probe, tp->netdev, "Unknown Device\n");
-+
-+      return ret;
-+}
-+
-+static int rtl8152_probe(struct usb_interface *intf,
-+                       const struct usb_device_id *id)
-+{
-+      struct usb_device *udev = interface_to_usbdev(intf);
-+      struct r8152 *tp;
-+      struct net_device *netdev;
-+      int ret;
-+
-+      if (udev->actconfig->desc.bConfigurationValue != 1) {
-+              usb_driver_set_configuration(udev, 1);
-+              return -ENODEV;
-+      }
-+
-+      usb_reset_device(udev);
-+      netdev = alloc_etherdev(sizeof(struct r8152));
-+      if (!netdev) {
-+              dev_err(&intf->dev, "Out of memory\n");
-+              return -ENOMEM;
-+      }
-+
-+      SET_NETDEV_DEV(netdev, &intf->dev);
-+      tp = netdev_priv(netdev);
-+      tp->msg_enable = 0x7FFF;
-+
-+      tp->udev = udev;
-+      tp->netdev = netdev;
-+      tp->intf = intf;
-+
-+      ret = rtl_ops_init(tp, id);
-+      if (ret)
-+              goto out;
-+
-+      tasklet_init(&tp->tl, bottom_half, (unsigned long)tp);
-+      INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t);
-+
-+      netdev->netdev_ops = &rtl8152_netdev_ops;
-+      netdev->watchdog_timeo = RTL8152_TX_TIMEOUT;
-+
-+      netdev->features |= NETIF_F_IP_CSUM;
-+      netdev->hw_features = NETIF_F_IP_CSUM;
-+      SET_ETHTOOL_OPS(netdev, &ops);
-+
-+      tp->mii.dev = netdev;
-+      tp->mii.mdio_read = read_mii_word;
-+      tp->mii.mdio_write = write_mii_word;
-+      tp->mii.phy_id_mask = 0x3f;
-+      tp->mii.reg_num_mask = 0x1f;
-+      tp->mii.phy_id = R8152_PHY_ID;
-+      tp->mii.supports_gmii = 0;
-+
-+      r8152b_get_version(tp);
-+      tp->rtl_ops.init(tp);
-+      set_ethernet_addr(tp);
-+
-+      ret = alloc_all_mem(tp);
-+      if (ret)
-+              goto out;
-+
-+      usb_set_intfdata(intf, tp);
-+
-+      ret = register_netdev(netdev);
-+      if (ret != 0) {
-+              netif_err(tp, probe, netdev, "couldn't register the device\n");
-+              goto out1;
-+      }
-+
-+      netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION);
-+
-+      return 0;
-+
-+out1:
-+      usb_set_intfdata(intf, NULL);
-+out:
-+      free_netdev(netdev);
-+      return ret;
-+}
-+
-+static void rtl8152_disconnect(struct usb_interface *intf)
-+{
-+      struct r8152 *tp = usb_get_intfdata(intf);
-+
-+      usb_set_intfdata(intf, NULL);
-+      if (tp) {
-+              set_bit(RTL8152_UNPLUG, &tp->flags);
-+              tasklet_kill(&tp->tl);
-+              unregister_netdev(tp->netdev);
-+              tp->rtl_ops.unload(tp);
-+              free_all_mem(tp);
-+              free_netdev(tp->netdev);
-+      }
-+}
-+
-+/* table of devices that work with this driver */
-+static struct usb_device_id rtl8152_table[] = {
-+      {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8152)},
-+      {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8153)},
-+      {USB_DEVICE(VENDOR_ID_SAMSUNG, PRODUCT_ID_SAMSUNG)},
-+      {USB_DEVICE(VENDOR_ID_LENOVO, PRODUCT_ID_LENOVO)},
-+      {USB_DEVICE(VENDOR_ID_NVIDIA, PRODUCT_ID_NVIDIA)},
-+      {}
-+};
-+
-+MODULE_DEVICE_TABLE(usb, rtl8152_table);
-+
-+static struct usb_driver rtl8152_driver = {
-+      .name =         MODULENAME,
-+      .id_table =     rtl8152_table,
-+      .probe =        rtl8152_probe,
-+      .disconnect =   rtl8152_disconnect,
-+      .suspend =      rtl8152_suspend,
-+      .resume =       rtl8152_resume,
-+      .reset_resume = rtl8152_resume,
-+};
-+
-+module_usb_driver(rtl8152_driver);
-+
-+MODULE_AUTHOR(DRIVER_AUTHOR);
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/rtl8150.c backports-4.2.6-1/drivers/net/usb/rtl8150.c
---- backports-4.2.6-1.org/drivers/net/usb/rtl8150.c    1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/rtl8150.c        2016-06-28 14:35:18.001973885 +0200
-@@ -0,0 +1,949 @@
-+/*
-+ *  Copyright (c) 2002 Petko Manolov (petkan@users.sourceforge.net)
-+ *
-+ * 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.
-+ */
-+
-+#include <linux/signal.h>
-+#include <linux/slab.h>
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/mii.h>
-+#include <linux/ethtool.h>
-+#include <linux/usb.h>
-+#include <asm/uaccess.h>
-+
-+/* Version Information */
-+#define DRIVER_VERSION "v0.6.2 (2004/08/27)"
-+#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
-+#define DRIVER_DESC "rtl8150 based usb-ethernet driver"
-+
-+#define       IDR                     0x0120
-+#define       MAR                     0x0126
-+#define       CR                      0x012e
-+#define       TCR                     0x012f
-+#define       RCR                     0x0130
-+#define       TSR                     0x0132
-+#define       RSR                     0x0133
-+#define       CON0                    0x0135
-+#define       CON1                    0x0136
-+#define       MSR                     0x0137
-+#define       PHYADD                  0x0138
-+#define       PHYDAT                  0x0139
-+#define       PHYCNT                  0x013b
-+#define       GPPC                    0x013d
-+#define       BMCR                    0x0140
-+#define       BMSR                    0x0142
-+#define       ANAR                    0x0144
-+#define       ANLP                    0x0146
-+#define       AER                     0x0148
-+#define CSCR                  0x014C  /* This one has the link status */
-+#define CSCR_LINK_STATUS      (1 << 3)
-+
-+#define       IDR_EEPROM              0x1202
-+
-+#define       PHY_READ                0
-+#define       PHY_WRITE               0x20
-+#define       PHY_GO                  0x40
-+
-+#define       MII_TIMEOUT             10
-+#define       INTBUFSIZE              8
-+
-+#define       RTL8150_REQT_READ       0xc0
-+#define       RTL8150_REQT_WRITE      0x40
-+#define       RTL8150_REQ_GET_REGS    0x05
-+#define       RTL8150_REQ_SET_REGS    0x05
-+
-+
-+/* Transmit status register errors */
-+#define TSR_ECOL              (1<<5)
-+#define TSR_LCOL              (1<<4)
-+#define TSR_LOSS_CRS          (1<<3)
-+#define TSR_JBR                       (1<<2)
-+#define TSR_ERRORS            (TSR_ECOL | TSR_LCOL | TSR_LOSS_CRS | TSR_JBR)
-+/* Receive status register errors */
-+#define RSR_CRC                       (1<<2)
-+#define RSR_FAE                       (1<<1)
-+#define RSR_ERRORS            (RSR_CRC | RSR_FAE)
-+
-+/* Media status register definitions */
-+#define MSR_DUPLEX            (1<<4)
-+#define MSR_SPEED             (1<<3)
-+#define MSR_LINK              (1<<2)
-+
-+/* Interrupt pipe data */
-+#define INT_TSR                       0x00
-+#define INT_RSR                       0x01
-+#define INT_MSR                       0x02
-+#define INT_WAKSR             0x03
-+#define INT_TXOK_CNT          0x04
-+#define INT_RXLOST_CNT                0x05
-+#define INT_CRERR_CNT         0x06
-+#define INT_COL_CNT           0x07
-+
-+
-+#define       RTL8150_MTU             1540
-+#define       RTL8150_TX_TIMEOUT      (HZ)
-+#define       RX_SKB_POOL_SIZE        4
-+
-+/* rtl8150 flags */
-+#define       RTL8150_HW_CRC          0
-+#define       RX_REG_SET              1
-+#define       RTL8150_UNPLUG          2
-+#define       RX_URB_FAIL             3
-+
-+/* Define these values to match your device */
-+#define       VENDOR_ID_REALTEK               0x0bda
-+#define       VENDOR_ID_MELCO                 0x0411
-+#define       VENDOR_ID_MICRONET              0x3980
-+#define       VENDOR_ID_LONGSHINE             0x07b8
-+#define       VENDOR_ID_OQO                   0x1557
-+#define       VENDOR_ID_ZYXEL                 0x0586
-+
-+#define PRODUCT_ID_RTL8150            0x8150
-+#define       PRODUCT_ID_LUAKTX               0x0012
-+#define       PRODUCT_ID_LCS8138TX            0x401a
-+#define PRODUCT_ID_SP128AR            0x0003
-+#define       PRODUCT_ID_PRESTIGE             0x401a
-+
-+#undef        EEPROM_WRITE
-+
-+/* table of devices that work with this driver */
-+static struct usb_device_id rtl8150_table[] = {
-+      {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8150)},
-+      {USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)},
-+      {USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)},
-+      {USB_DEVICE(VENDOR_ID_LONGSHINE, PRODUCT_ID_LCS8138TX)},
-+      {USB_DEVICE(VENDOR_ID_OQO, PRODUCT_ID_RTL8150)},
-+      {USB_DEVICE(VENDOR_ID_ZYXEL, PRODUCT_ID_PRESTIGE)},
-+      {}
-+};
-+
-+MODULE_DEVICE_TABLE(usb, rtl8150_table);
-+
-+struct rtl8150 {
-+      unsigned long flags;
-+      struct usb_device *udev;
-+      struct tasklet_struct tl;
-+      struct net_device *netdev;
-+      struct urb *rx_urb, *tx_urb, *intr_urb;
-+      struct sk_buff *tx_skb, *rx_skb;
-+      struct sk_buff *rx_skb_pool[RX_SKB_POOL_SIZE];
-+      spinlock_t rx_pool_lock;
-+      struct usb_ctrlrequest dr;
-+      int intr_interval;
-+      u8 *intr_buff;
-+      u8 phy;
-+};
-+
-+typedef struct rtl8150 rtl8150_t;
-+
-+struct async_req {
-+      struct usb_ctrlrequest dr;
-+      u16 rx_creg;
-+};
-+
-+static const char driver_name [] = "rtl8150";
-+
-+/*
-+**
-+**    device related part of the code
-+**
-+*/
-+static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
-+{
-+      return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-+                             RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
-+                             indx, 0, data, size, 500);
-+}
-+
-+static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
-+{
-+      return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-+                             RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
-+                             indx, 0, data, size, 500);
-+}
-+
-+static void async_set_reg_cb(struct urb *urb)
-+{
-+      struct async_req *req = (struct async_req *)urb->context;
-+      int status = urb->status;
-+
-+      if (status < 0)
-+              dev_dbg(&urb->dev->dev, "%s failed with %d", __func__, status);
-+      kfree(req);
-+      usb_free_urb(urb);
-+}
-+
-+static int async_set_registers(rtl8150_t *dev, u16 indx, u16 size, u16 reg)
-+{
-+      int res = -ENOMEM;
-+      struct urb *async_urb;
-+      struct async_req *req;
-+
-+      req = kmalloc(sizeof(struct async_req), GFP_ATOMIC);
-+      if (req == NULL)
-+              return res;
-+      async_urb = usb_alloc_urb(0, GFP_ATOMIC);
-+      if (async_urb == NULL) {
-+              kfree(req);
-+              return res;
-+      }
-+      req->rx_creg = cpu_to_le16(reg);
-+      req->dr.bRequestType = RTL8150_REQT_WRITE;
-+      req->dr.bRequest = RTL8150_REQ_SET_REGS;
-+      req->dr.wIndex = 0;
-+      req->dr.wValue = cpu_to_le16(indx);
-+      req->dr.wLength = cpu_to_le16(size);
-+      usb_fill_control_urb(async_urb, dev->udev,
-+                           usb_sndctrlpipe(dev->udev, 0), (void *)&req->dr,
-+                           &req->rx_creg, size, async_set_reg_cb, req);
-+      res = usb_submit_urb(async_urb, GFP_ATOMIC);
-+      if (res) {
-+              if (res == -ENODEV)
-+                      netif_device_detach(dev->netdev);
-+              dev_err(&dev->udev->dev, "%s failed with %d\n", __func__, res);
-+      }
-+      return res;
-+}
-+
-+static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg)
-+{
-+      int i;
-+      u8 data[3], tmp;
-+
-+      data[0] = phy;
-+      data[1] = data[2] = 0;
-+      tmp = indx | PHY_READ | PHY_GO;
-+      i = 0;
-+
-+      set_registers(dev, PHYADD, sizeof(data), data);
-+      set_registers(dev, PHYCNT, 1, &tmp);
-+      do {
-+              get_registers(dev, PHYCNT, 1, data);
-+      } while ((data[0] & PHY_GO) && (i++ < MII_TIMEOUT));
-+
-+      if (i <= MII_TIMEOUT) {
-+              get_registers(dev, PHYDAT, 2, data);
-+              *reg = data[0] | (data[1] << 8);
-+              return 0;
-+      } else
-+              return 1;
-+}
-+
-+static int write_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 reg)
-+{
-+      int i;
-+      u8 data[3], tmp;
-+
-+      data[0] = phy;
-+      data[1] = reg & 0xff;
-+      data[2] = (reg >> 8) & 0xff;
-+      tmp = indx | PHY_WRITE | PHY_GO;
-+      i = 0;
-+
-+      set_registers(dev, PHYADD, sizeof(data), data);
-+      set_registers(dev, PHYCNT, 1, &tmp);
-+      do {
-+              get_registers(dev, PHYCNT, 1, data);
-+      } while ((data[0] & PHY_GO) && (i++ < MII_TIMEOUT));
-+
-+      if (i <= MII_TIMEOUT)
-+              return 0;
-+      else
-+              return 1;
-+}
-+
-+static inline void set_ethernet_addr(rtl8150_t * dev)
-+{
-+      u8 node_id[6];
-+
-+      get_registers(dev, IDR, sizeof(node_id), node_id);
-+      memcpy(dev->netdev->dev_addr, node_id, sizeof(node_id));
-+}
-+
-+static int rtl8150_set_mac_address(struct net_device *netdev, void *p)
-+{
-+      struct sockaddr *addr = p;
-+      rtl8150_t *dev = netdev_priv(netdev);
-+
-+      if (netif_running(netdev))
-+              return -EBUSY;
-+
-+      memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-+      netdev_dbg(netdev, "Setting MAC address to %pM\n", netdev->dev_addr);
-+      /* Set the IDR registers. */
-+      set_registers(dev, IDR, netdev->addr_len, netdev->dev_addr);
-+#ifdef EEPROM_WRITE
-+      {
-+      int i;
-+      u8 cr;
-+      /* Get the CR contents. */
-+      get_registers(dev, CR, 1, &cr);
-+      /* Set the WEPROM bit (eeprom write enable). */
-+      cr |= 0x20;
-+      set_registers(dev, CR, 1, &cr);
-+      /* Write the MAC address into eeprom. Eeprom writes must be word-sized,
-+         so we need to split them up. */
-+      for (i = 0; i * 2 < netdev->addr_len; i++) {
-+              set_registers(dev, IDR_EEPROM + (i * 2), 2,
-+              netdev->dev_addr + (i * 2));
-+      }
-+      /* Clear the WEPROM bit (preventing accidental eeprom writes). */
-+      cr &= 0xdf;
-+      set_registers(dev, CR, 1, &cr);
-+      }
-+#endif
-+      return 0;
-+}
-+
-+static int rtl8150_reset(rtl8150_t * dev)
-+{
-+      u8 data = 0x10;
-+      int i = HZ;
-+
-+      set_registers(dev, CR, 1, &data);
-+      do {
-+              get_registers(dev, CR, 1, &data);
-+      } while ((data & 0x10) && --i);
-+
-+      return (i > 0) ? 1 : 0;
-+}
-+
-+static int alloc_all_urbs(rtl8150_t * dev)
-+{
-+      dev->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!dev->rx_urb)
-+              return 0;
-+      dev->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!dev->tx_urb) {
-+              usb_free_urb(dev->rx_urb);
-+              return 0;
-+      }
-+      dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
-+      if (!dev->intr_urb) {
-+              usb_free_urb(dev->rx_urb);
-+              usb_free_urb(dev->tx_urb);
-+              return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+static void free_all_urbs(rtl8150_t * dev)
-+{
-+      usb_free_urb(dev->rx_urb);
-+      usb_free_urb(dev->tx_urb);
-+      usb_free_urb(dev->intr_urb);
-+}
-+
-+static void unlink_all_urbs(rtl8150_t * dev)
-+{
-+      usb_kill_urb(dev->rx_urb);
-+      usb_kill_urb(dev->tx_urb);
-+      usb_kill_urb(dev->intr_urb);
-+}
-+
-+static inline struct sk_buff *pull_skb(rtl8150_t *dev)
-+{
-+      struct sk_buff *skb;
-+      int i;
-+
-+      for (i = 0; i < RX_SKB_POOL_SIZE; i++) {
-+              if (dev->rx_skb_pool[i]) {
-+                      skb = dev->rx_skb_pool[i];
-+                      dev->rx_skb_pool[i] = NULL;
-+                      return skb;
-+              }
-+      }
-+      return NULL;
-+}
-+
-+static void read_bulk_callback(struct urb *urb)
-+{
-+      rtl8150_t *dev;
-+      unsigned pkt_len, res;
-+      struct sk_buff *skb;
-+      struct net_device *netdev;
-+      u16 rx_stat;
-+      int status = urb->status;
-+      int result;
-+
-+      dev = urb->context;
-+      if (!dev)
-+              return;
-+      if (test_bit(RTL8150_UNPLUG, &dev->flags))
-+              return;
-+      netdev = dev->netdev;
-+      if (!netif_device_present(netdev))
-+              return;
-+
-+      switch (status) {
-+      case 0:
-+              break;
-+      case -ENOENT:
-+              return; /* the urb is in unlink state */
-+      case -ETIME:
-+              if (printk_ratelimit())
-+                      dev_warn(&urb->dev->dev, "may be reset is needed?..\n");
-+              goto goon;
-+      default:
-+              if (printk_ratelimit())
-+                      dev_warn(&urb->dev->dev, "Rx status %d\n", status);
-+              goto goon;
-+      }
-+
-+      if (!dev->rx_skb)
-+              goto resched;
-+      /* protect against short packets (tell me why we got some?!?) */
-+      if (urb->actual_length < 4)
-+              goto goon;
-+
-+      res = urb->actual_length;
-+      rx_stat = le16_to_cpu(*(__le16 *)(urb->transfer_buffer + res - 4));
-+      pkt_len = res - 4;
-+
-+      skb_put(dev->rx_skb, pkt_len);
-+      dev->rx_skb->protocol = eth_type_trans(dev->rx_skb, netdev);
-+      netif_rx(dev->rx_skb);
-+      netdev->stats.rx_packets++;
-+      netdev->stats.rx_bytes += pkt_len;
-+
-+      spin_lock(&dev->rx_pool_lock);
-+      skb = pull_skb(dev);
-+      spin_unlock(&dev->rx_pool_lock);
-+      if (!skb)
-+              goto resched;
-+
-+      dev->rx_skb = skb;
-+goon:
-+      usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
-+                    dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
-+      result = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
-+      if (result == -ENODEV)
-+              netif_device_detach(dev->netdev);
-+      else if (result) {
-+              set_bit(RX_URB_FAIL, &dev->flags);
-+              goto resched;
-+      } else {
-+              clear_bit(RX_URB_FAIL, &dev->flags);
-+      }
-+
-+      return;
-+resched:
-+      tasklet_schedule(&dev->tl);
-+}
-+
-+static void write_bulk_callback(struct urb *urb)
-+{
-+      rtl8150_t *dev;
-+      int status = urb->status;
-+
-+      dev = urb->context;
-+      if (!dev)
-+              return;
-+      dev_kfree_skb_irq(dev->tx_skb);
-+      if (!netif_device_present(dev->netdev))
-+              return;
-+      if (status)
-+              dev_info(&urb->dev->dev, "%s: Tx status %d\n",
-+                       dev->netdev->name, status);
-+      dev->netdev->trans_start = jiffies;
-+      netif_wake_queue(dev->netdev);
-+}
-+
-+static void intr_callback(struct urb *urb)
-+{
-+      rtl8150_t *dev;
-+      __u8 *d;
-+      int status = urb->status;
-+      int res;
-+
-+      dev = urb->context;
-+      if (!dev)
-+              return;
-+      switch (status) {
-+      case 0:                 /* success */
-+              break;
-+      case -ECONNRESET:       /* unlink */
-+      case -ENOENT:
-+      case -ESHUTDOWN:
-+              return;
-+      /* -EPIPE:  should clear the halt */
-+      default:
-+              dev_info(&urb->dev->dev, "%s: intr status %d\n",
-+                       dev->netdev->name, status);
-+              goto resubmit;
-+      }
-+
-+      d = urb->transfer_buffer;
-+      if (d[0] & TSR_ERRORS) {
-+              dev->netdev->stats.tx_errors++;
-+              if (d[INT_TSR] & (TSR_ECOL | TSR_JBR))
-+                      dev->netdev->stats.tx_aborted_errors++;
-+              if (d[INT_TSR] & TSR_LCOL)
-+                      dev->netdev->stats.tx_window_errors++;
-+              if (d[INT_TSR] & TSR_LOSS_CRS)
-+                      dev->netdev->stats.tx_carrier_errors++;
-+      }
-+      /* Report link status changes to the network stack */
-+      if ((d[INT_MSR] & MSR_LINK) == 0) {
-+              if (netif_carrier_ok(dev->netdev)) {
-+                      netif_carrier_off(dev->netdev);
-+                      netdev_dbg(dev->netdev, "%s: LINK LOST\n", __func__);
-+              }
-+      } else {
-+              if (!netif_carrier_ok(dev->netdev)) {
-+                      netif_carrier_on(dev->netdev);
-+                      netdev_dbg(dev->netdev, "%s: LINK CAME BACK\n", __func__);
-+              }
-+      }
-+
-+resubmit:
-+      res = usb_submit_urb (urb, GFP_ATOMIC);
-+      if (res == -ENODEV)
-+              netif_device_detach(dev->netdev);
-+      else if (res)
-+              dev_err(&dev->udev->dev,
-+                      "can't resubmit intr, %s-%s/input0, status %d\n",
-+                      dev->udev->bus->bus_name, dev->udev->devpath, res);
-+}
-+
-+static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message)
-+{
-+      rtl8150_t *dev = usb_get_intfdata(intf);
-+
-+      netif_device_detach(dev->netdev);
-+
-+      if (netif_running(dev->netdev)) {
-+              usb_kill_urb(dev->rx_urb);
-+              usb_kill_urb(dev->intr_urb);
-+      }
-+      return 0;
-+}
-+
-+static int rtl8150_resume(struct usb_interface *intf)
-+{
-+      rtl8150_t *dev = usb_get_intfdata(intf);
-+
-+      netif_device_attach(dev->netdev);
-+      if (netif_running(dev->netdev)) {
-+              dev->rx_urb->status = 0;
-+              dev->rx_urb->actual_length = 0;
-+              read_bulk_callback(dev->rx_urb);
-+
-+              dev->intr_urb->status = 0;
-+              dev->intr_urb->actual_length = 0;
-+              intr_callback(dev->intr_urb);
-+      }
-+      return 0;
-+}
-+
-+/*
-+**
-+**    network related part of the code
-+**
-+*/
-+
-+static void fill_skb_pool(rtl8150_t *dev)
-+{
-+      struct sk_buff *skb;
-+      int i;
-+
-+      for (i = 0; i < RX_SKB_POOL_SIZE; i++) {
-+              if (dev->rx_skb_pool[i])
-+                      continue;
-+              skb = dev_alloc_skb(RTL8150_MTU + 2);
-+              if (!skb) {
-+                      return;
-+              }
-+              skb_reserve(skb, 2);
-+              dev->rx_skb_pool[i] = skb;
-+      }
-+}
-+
-+static void free_skb_pool(rtl8150_t *dev)
-+{
-+      int i;
-+
-+      for (i = 0; i < RX_SKB_POOL_SIZE; i++)
-+              if (dev->rx_skb_pool[i])
-+                      dev_kfree_skb(dev->rx_skb_pool[i]);
-+}
-+
-+static void rx_fixup(unsigned long data)
-+{
-+      struct rtl8150 *dev = (struct rtl8150 *)data;
-+      struct sk_buff *skb;
-+      int status;
-+
-+      spin_lock_irq(&dev->rx_pool_lock);
-+      fill_skb_pool(dev);
-+      spin_unlock_irq(&dev->rx_pool_lock);
-+      if (test_bit(RX_URB_FAIL, &dev->flags))
-+              if (dev->rx_skb)
-+                      goto try_again;
-+      spin_lock_irq(&dev->rx_pool_lock);
-+      skb = pull_skb(dev);
-+      spin_unlock_irq(&dev->rx_pool_lock);
-+      if (skb == NULL)
-+              goto tlsched;
-+      dev->rx_skb = skb;
-+      usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
-+                    dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
-+try_again:
-+      status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
-+      if (status == -ENODEV) {
-+              netif_device_detach(dev->netdev);
-+      } else if (status) {
-+              set_bit(RX_URB_FAIL, &dev->flags);
-+              goto tlsched;
-+      } else {
-+              clear_bit(RX_URB_FAIL, &dev->flags);
-+      }
-+
-+      return;
-+tlsched:
-+      tasklet_schedule(&dev->tl);
-+}
-+
-+static int enable_net_traffic(rtl8150_t * dev)
-+{
-+      u8 cr, tcr, rcr, msr;
-+
-+      if (!rtl8150_reset(dev)) {
-+              dev_warn(&dev->udev->dev, "device reset failed\n");
-+      }
-+      /* RCR bit7=1 attach Rx info at the end;  =0 HW CRC (which is broken) */
-+      rcr = 0x9e;
-+      tcr = 0xd8;
-+      cr = 0x0c;
-+      if (!(rcr & 0x80))
-+              set_bit(RTL8150_HW_CRC, &dev->flags);
-+      set_registers(dev, RCR, 1, &rcr);
-+      set_registers(dev, TCR, 1, &tcr);
-+      set_registers(dev, CR, 1, &cr);
-+      get_registers(dev, MSR, 1, &msr);
-+
-+      return 0;
-+}
-+
-+static void disable_net_traffic(rtl8150_t * dev)
-+{
-+      u8 cr;
-+
-+      get_registers(dev, CR, 1, &cr);
-+      cr &= 0xf3;
-+      set_registers(dev, CR, 1, &cr);
-+}
-+
-+static void rtl8150_tx_timeout(struct net_device *netdev)
-+{
-+      rtl8150_t *dev = netdev_priv(netdev);
-+      dev_warn(&netdev->dev, "Tx timeout.\n");
-+      usb_unlink_urb(dev->tx_urb);
-+      netdev->stats.tx_errors++;
-+}
-+
-+static void rtl8150_set_multicast(struct net_device *netdev)
-+{
-+      rtl8150_t *dev = netdev_priv(netdev);
-+      u16 rx_creg = 0x9e;
-+
-+      netif_stop_queue(netdev);
-+      if (netdev->flags & IFF_PROMISC) {
-+              rx_creg |= 0x0001;
-+              dev_info(&netdev->dev, "%s: promiscuous mode\n", netdev->name);
-+      } else if (!netdev_mc_empty(netdev) ||
-+                 (netdev->flags & IFF_ALLMULTI)) {
-+              rx_creg &= 0xfffe;
-+              rx_creg |= 0x0002;
-+              dev_info(&netdev->dev, "%s: allmulti set\n", netdev->name);
-+      } else {
-+              /* ~RX_MULTICAST, ~RX_PROMISCUOUS */
-+              rx_creg &= 0x00fc;
-+      }
-+      async_set_registers(dev, RCR, sizeof(rx_creg), rx_creg);
-+      netif_wake_queue(netdev);
-+}
-+
-+static netdev_tx_t rtl8150_start_xmit(struct sk_buff *skb,
-+                                          struct net_device *netdev)
-+{
-+      rtl8150_t *dev = netdev_priv(netdev);
-+      int count, res;
-+
-+      netif_stop_queue(netdev);
-+      count = (skb->len < 60) ? 60 : skb->len;
-+      count = (count & 0x3f) ? count : count + 1;
-+      dev->tx_skb = skb;
-+      usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2),
-+                    skb->data, count, write_bulk_callback, dev);
-+      if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) {
-+              /* Can we get/handle EPIPE here? */
-+              if (res == -ENODEV)
-+                      netif_device_detach(dev->netdev);
-+              else {
-+                      dev_warn(&netdev->dev, "failed tx_urb %d\n", res);
-+                      netdev->stats.tx_errors++;
-+                      netif_start_queue(netdev);
-+              }
-+      } else {
-+              netdev->stats.tx_packets++;
-+              netdev->stats.tx_bytes += skb->len;
-+              netdev->trans_start = jiffies;
-+      }
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+
-+static void set_carrier(struct net_device *netdev)
-+{
-+      rtl8150_t *dev = netdev_priv(netdev);
-+      short tmp;
-+
-+      get_registers(dev, CSCR, 2, &tmp);
-+      if (tmp & CSCR_LINK_STATUS)
-+              netif_carrier_on(netdev);
-+      else
-+              netif_carrier_off(netdev);
-+}
-+
-+static int rtl8150_open(struct net_device *netdev)
-+{
-+      rtl8150_t *dev = netdev_priv(netdev);
-+      int res;
-+
-+      if (dev->rx_skb == NULL)
-+              dev->rx_skb = pull_skb(dev);
-+      if (!dev->rx_skb)
-+              return -ENOMEM;
-+
-+      set_registers(dev, IDR, 6, netdev->dev_addr);
-+
-+      usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
-+                    dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
-+      if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) {
-+              if (res == -ENODEV)
-+                      netif_device_detach(dev->netdev);
-+              dev_warn(&netdev->dev, "rx_urb submit failed: %d\n", res);
-+              return res;
-+      }
-+      usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3),
-+                   dev->intr_buff, INTBUFSIZE, intr_callback,
-+                   dev, dev->intr_interval);
-+      if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) {
-+              if (res == -ENODEV)
-+                      netif_device_detach(dev->netdev);
-+              dev_warn(&netdev->dev, "intr_urb submit failed: %d\n", res);
-+              usb_kill_urb(dev->rx_urb);
-+              return res;
-+      }
-+      enable_net_traffic(dev);
-+      set_carrier(netdev);
-+      netif_start_queue(netdev);
-+
-+      return res;
-+}
-+
-+static int rtl8150_close(struct net_device *netdev)
-+{
-+      rtl8150_t *dev = netdev_priv(netdev);
-+
-+      netif_stop_queue(netdev);
-+      if (!test_bit(RTL8150_UNPLUG, &dev->flags))
-+              disable_net_traffic(dev);
-+      unlink_all_urbs(dev);
-+
-+      return 0;
-+}
-+
-+static void rtl8150_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
-+{
-+      rtl8150_t *dev = netdev_priv(netdev);
-+
-+      strlcpy(info->driver, driver_name, sizeof(info->driver));
-+      strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
-+      usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info));
-+}
-+
-+static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
-+{
-+      rtl8150_t *dev = netdev_priv(netdev);
-+      short lpa, bmcr;
-+
-+      ecmd->supported = (SUPPORTED_10baseT_Half |
-+                        SUPPORTED_10baseT_Full |
-+                        SUPPORTED_100baseT_Half |
-+                        SUPPORTED_100baseT_Full |
-+                        SUPPORTED_Autoneg |
-+                        SUPPORTED_TP | SUPPORTED_MII);
-+      ecmd->port = PORT_TP;
-+      ecmd->transceiver = XCVR_INTERNAL;
-+      ecmd->phy_address = dev->phy;
-+      get_registers(dev, BMCR, 2, &bmcr);
-+      get_registers(dev, ANLP, 2, &lpa);
-+      if (bmcr & BMCR_ANENABLE) {
-+              u32 speed = ((lpa & (LPA_100HALF | LPA_100FULL)) ?
-+                           SPEED_100 : SPEED_10);
-+              ethtool_cmd_speed_set(ecmd, speed);
-+              ecmd->autoneg = AUTONEG_ENABLE;
-+              if (speed == SPEED_100)
-+                      ecmd->duplex = (lpa & LPA_100FULL) ?
-+                          DUPLEX_FULL : DUPLEX_HALF;
-+              else
-+                      ecmd->duplex = (lpa & LPA_10FULL) ?
-+                          DUPLEX_FULL : DUPLEX_HALF;
-+      } else {
-+              ecmd->autoneg = AUTONEG_DISABLE;
-+              ethtool_cmd_speed_set(ecmd, ((bmcr & BMCR_SPEED100) ?
-+                                           SPEED_100 : SPEED_10));
-+              ecmd->duplex = (bmcr & BMCR_FULLDPLX) ?
-+                  DUPLEX_FULL : DUPLEX_HALF;
-+      }
-+      return 0;
-+}
-+
-+static const struct ethtool_ops ops = {
-+      .get_drvinfo = rtl8150_get_drvinfo,
-+      .get_settings = rtl8150_get_settings,
-+      .get_link = ethtool_op_get_link
-+};
-+
-+static int rtl8150_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
-+{
-+      rtl8150_t *dev = netdev_priv(netdev);
-+      u16 *data = (u16 *) & rq->ifr_ifru;
-+      int res = 0;
-+
-+      switch (cmd) {
-+      case SIOCDEVPRIVATE:
-+              data[0] = dev->phy;
-+      case SIOCDEVPRIVATE + 1:
-+              read_mii_word(dev, dev->phy, (data[1] & 0x1f), &data[3]);
-+              break;
-+      case SIOCDEVPRIVATE + 2:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+              write_mii_word(dev, dev->phy, (data[1] & 0x1f), data[2]);
-+              break;
-+      default:
-+              res = -EOPNOTSUPP;
-+      }
-+
-+      return res;
-+}
-+
-+static const struct net_device_ops rtl8150_netdev_ops = {
-+      .ndo_open               = rtl8150_open,
-+      .ndo_stop               = rtl8150_close,
-+      .ndo_do_ioctl           = rtl8150_ioctl,
-+      .ndo_start_xmit         = rtl8150_start_xmit,
-+      .ndo_tx_timeout         = rtl8150_tx_timeout,
-+      .ndo_set_rx_mode        = rtl8150_set_multicast,
-+      .ndo_set_mac_address    = rtl8150_set_mac_address,
-+
-+      .ndo_change_mtu         = eth_change_mtu,
-+      .ndo_validate_addr      = eth_validate_addr,
-+};
-+
-+static int rtl8150_probe(struct usb_interface *intf,
-+                       const struct usb_device_id *id)
-+{
-+      struct usb_device *udev = interface_to_usbdev(intf);
-+      rtl8150_t *dev;
-+      struct net_device *netdev;
-+
-+      netdev = alloc_etherdev(sizeof(rtl8150_t));
-+      if (!netdev)
-+              return -ENOMEM;
-+
-+      dev = netdev_priv(netdev);
-+
-+      dev->intr_buff = kmalloc(INTBUFSIZE, GFP_KERNEL);
-+      if (!dev->intr_buff) {
-+              free_netdev(netdev);
-+              return -ENOMEM;
-+      }
-+
-+      tasklet_init(&dev->tl, rx_fixup, (unsigned long)dev);
-+      spin_lock_init(&dev->rx_pool_lock);
-+
-+      dev->udev = udev;
-+      dev->netdev = netdev;
-+      netdev->netdev_ops = &rtl8150_netdev_ops;
-+      netdev->watchdog_timeo = RTL8150_TX_TIMEOUT;
-+      netdev->ethtool_ops = &ops;
-+      dev->intr_interval = 100;       /* 100ms */
-+
-+      if (!alloc_all_urbs(dev)) {
-+              dev_err(&intf->dev, "out of memory\n");
-+              goto out;
-+      }
-+      if (!rtl8150_reset(dev)) {
-+              dev_err(&intf->dev, "couldn't reset the device\n");
-+              goto out1;
-+      }
-+      fill_skb_pool(dev);
-+      set_ethernet_addr(dev);
-+
-+      usb_set_intfdata(intf, dev);
-+      SET_NETDEV_DEV(netdev, &intf->dev);
-+      if (register_netdev(netdev) != 0) {
-+              dev_err(&intf->dev, "couldn't register the device\n");
-+              goto out2;
-+      }
-+
-+      dev_info(&intf->dev, "%s: rtl8150 is detected\n", netdev->name);
-+
-+      return 0;
-+
-+out2:
-+      usb_set_intfdata(intf, NULL);
-+      free_skb_pool(dev);
-+out1:
-+      free_all_urbs(dev);
-+out:
-+      kfree(dev->intr_buff);
-+      free_netdev(netdev);
-+      return -EIO;
-+}
-+
-+static void rtl8150_disconnect(struct usb_interface *intf)
-+{
-+      rtl8150_t *dev = usb_get_intfdata(intf);
-+
-+      usb_set_intfdata(intf, NULL);
-+      if (dev) {
-+              set_bit(RTL8150_UNPLUG, &dev->flags);
-+              tasklet_kill(&dev->tl);
-+              unregister_netdev(dev->netdev);
-+              unlink_all_urbs(dev);
-+              free_all_urbs(dev);
-+              free_skb_pool(dev);
-+              if (dev->rx_skb)
-+                      dev_kfree_skb(dev->rx_skb);
-+              kfree(dev->intr_buff);
-+              free_netdev(dev->netdev);
-+      }
-+}
-+
-+static struct usb_driver rtl8150_driver = {
-+      .name           = driver_name,
-+      .probe          = rtl8150_probe,
-+      .disconnect     = rtl8150_disconnect,
-+      .id_table       = rtl8150_table,
-+      .suspend        = rtl8150_suspend,
-+      .resume         = rtl8150_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(rtl8150_driver);
-+
-+MODULE_AUTHOR(DRIVER_AUTHOR);
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/smsc75xx.c backports-4.2.6-1/drivers/net/usb/smsc75xx.c
---- backports-4.2.6-1.org/drivers/net/usb/smsc75xx.c   1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/smsc75xx.c       2016-06-28 14:35:18.008640551 +0200
-@@ -0,0 +1,2286 @@
-+ /***************************************************************************
-+ *
-+ * Copyright (C) 2007-2010 SMSC
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ *
-+ *****************************************************************************/
-+
-+#include <linux/module.h>
-+#include <linux/kmod.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/bitrev.h>
-+#include <linux/crc16.h>
-+#include <linux/crc32.h>
-+#include <linux/usb/usbnet.h>
-+#include <linux/slab.h>
-+#include "smsc75xx.h"
-+
-+#define SMSC_CHIPNAME                 "smsc75xx"
-+#define SMSC_DRIVER_VERSION           "1.0.0"
-+#define HS_USB_PKT_SIZE                       (512)
-+#define FS_USB_PKT_SIZE                       (64)
-+#define DEFAULT_HS_BURST_CAP_SIZE     (16 * 1024 + 5 * HS_USB_PKT_SIZE)
-+#define DEFAULT_FS_BURST_CAP_SIZE     (6 * 1024 + 33 * FS_USB_PKT_SIZE)
-+#define DEFAULT_BULK_IN_DELAY         (0x00002000)
-+#define MAX_SINGLE_PACKET_SIZE                (9000)
-+#define LAN75XX_EEPROM_MAGIC          (0x7500)
-+#define EEPROM_MAC_OFFSET             (0x01)
-+#define DEFAULT_TX_CSUM_ENABLE                (true)
-+#define DEFAULT_RX_CSUM_ENABLE                (true)
-+#define SMSC75XX_INTERNAL_PHY_ID      (1)
-+#define SMSC75XX_TX_OVERHEAD          (8)
-+#define MAX_RX_FIFO_SIZE              (20 * 1024)
-+#define MAX_TX_FIFO_SIZE              (12 * 1024)
-+#define USB_VENDOR_ID_SMSC            (0x0424)
-+#define USB_PRODUCT_ID_LAN7500                (0x7500)
-+#define USB_PRODUCT_ID_LAN7505                (0x7505)
-+#define RXW_PADDING                   2
-+#define SUPPORTED_WAKE                        (WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
-+                                       WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
-+
-+#define SUSPEND_SUSPEND0              (0x01)
-+#define SUSPEND_SUSPEND1              (0x02)
-+#define SUSPEND_SUSPEND2              (0x04)
-+#define SUSPEND_SUSPEND3              (0x08)
-+#define SUSPEND_ALLMODES              (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
-+                                       SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
-+
-+struct smsc75xx_priv {
-+      struct usbnet *dev;
-+      u32 rfe_ctl;
-+      u32 wolopts;
-+      u32 multicast_hash_table[DP_SEL_VHF_HASH_LEN];
-+      struct mutex dataport_mutex;
-+      spinlock_t rfe_ctl_lock;
-+      struct work_struct set_multicast;
-+      u8 suspend_flags;
-+};
-+
-+struct usb_context {
-+      struct usb_ctrlrequest req;
-+      struct usbnet *dev;
-+};
-+
-+static bool turbo_mode = true;
-+module_param(turbo_mode, bool, 0644);
-+MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
-+
-+static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index,
-+                                          u32 *data, int in_pm)
-+{
-+      u32 buf;
-+      int ret;
-+      int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
-+
-+      BUG_ON(!dev);
-+
-+      if (!in_pm)
-+              fn = usbnet_read_cmd;
-+      else
-+              fn = usbnet_read_cmd_nopm;
-+
-+      ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
-+               | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+               0, index, &buf, 4);
-+      if (unlikely(ret < 0))
-+              netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
-+                          index, ret);
-+
-+      le32_to_cpus(&buf);
-+      *data = buf;
-+
-+      return ret;
-+}
-+
-+static int __must_check __smsc75xx_write_reg(struct usbnet *dev, u32 index,
-+                                           u32 data, int in_pm)
-+{
-+      u32 buf;
-+      int ret;
-+      int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
-+
-+      BUG_ON(!dev);
-+
-+      if (!in_pm)
-+              fn = usbnet_write_cmd;
-+      else
-+              fn = usbnet_write_cmd_nopm;
-+
-+      buf = data;
-+      cpu_to_le32s(&buf);
-+
-+      ret = fn(dev, USB_VENDOR_REQUEST_WRITE_REGISTER, USB_DIR_OUT
-+               | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+               0, index, &buf, 4);
-+      if (unlikely(ret < 0))
-+              netdev_warn(dev->net, "Failed to write reg index 0x%08x: %d\n",
-+                          index, ret);
-+
-+      return ret;
-+}
-+
-+static int __must_check smsc75xx_read_reg_nopm(struct usbnet *dev, u32 index,
-+                                             u32 *data)
-+{
-+      return __smsc75xx_read_reg(dev, index, data, 1);
-+}
-+
-+static int __must_check smsc75xx_write_reg_nopm(struct usbnet *dev, u32 index,
-+                                              u32 data)
-+{
-+      return __smsc75xx_write_reg(dev, index, data, 1);
-+}
-+
-+static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index,
-+                                        u32 *data)
-+{
-+      return __smsc75xx_read_reg(dev, index, data, 0);
-+}
-+
-+static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
-+                                         u32 data)
-+{
-+      return __smsc75xx_write_reg(dev, index, data, 0);
-+}
-+
-+/* Loop until the read is completed with timeout
-+ * called with phy_mutex held */
-+static __must_check int __smsc75xx_phy_wait_not_busy(struct usbnet *dev,
-+                                                   int in_pm)
-+{
-+      unsigned long start_time = jiffies;
-+      u32 val;
-+      int ret;
-+
-+      do {
-+              ret = __smsc75xx_read_reg(dev, MII_ACCESS, &val, in_pm);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading MII_ACCESS\n");
-+                      return ret;
-+              }
-+
-+              if (!(val & MII_ACCESS_BUSY))
-+                      return 0;
-+      } while (!time_after(jiffies, start_time + HZ));
-+
-+      return -EIO;
-+}
-+
-+static int __smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx,
-+                              int in_pm)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      u32 val, addr;
-+      int ret;
-+
-+      mutex_lock(&dev->phy_mutex);
-+
-+      /* confirm MII not busy */
-+      ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "MII is busy in smsc75xx_mdio_read\n");
-+              goto done;
-+      }
-+
-+      /* set the address, index & direction (read from PHY) */
-+      phy_id &= dev->mii.phy_id_mask;
-+      idx &= dev->mii.reg_num_mask;
-+      addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
-+              | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
-+              | MII_ACCESS_READ | MII_ACCESS_BUSY;
-+      ret = __smsc75xx_write_reg(dev, MII_ACCESS, addr, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing MII_ACCESS\n");
-+              goto done;
-+      }
-+
-+      ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Timed out reading MII reg %02X\n", idx);
-+              goto done;
-+      }
-+
-+      ret = __smsc75xx_read_reg(dev, MII_DATA, &val, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading MII_DATA\n");
-+              goto done;
-+      }
-+
-+      ret = (u16)(val & 0xFFFF);
-+
-+done:
-+      mutex_unlock(&dev->phy_mutex);
-+      return ret;
-+}
-+
-+static void __smsc75xx_mdio_write(struct net_device *netdev, int phy_id,
-+                                int idx, int regval, int in_pm)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      u32 val, addr;
-+      int ret;
-+
-+      mutex_lock(&dev->phy_mutex);
-+
-+      /* confirm MII not busy */
-+      ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "MII is busy in smsc75xx_mdio_write\n");
-+              goto done;
-+      }
-+
-+      val = regval;
-+      ret = __smsc75xx_write_reg(dev, MII_DATA, val, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing MII_DATA\n");
-+              goto done;
-+      }
-+
-+      /* set the address, index & direction (write to PHY) */
-+      phy_id &= dev->mii.phy_id_mask;
-+      idx &= dev->mii.reg_num_mask;
-+      addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
-+              | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
-+              | MII_ACCESS_WRITE | MII_ACCESS_BUSY;
-+      ret = __smsc75xx_write_reg(dev, MII_ACCESS, addr, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing MII_ACCESS\n");
-+              goto done;
-+      }
-+
-+      ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Timed out writing MII reg %02X\n", idx);
-+              goto done;
-+      }
-+
-+done:
-+      mutex_unlock(&dev->phy_mutex);
-+}
-+
-+static int smsc75xx_mdio_read_nopm(struct net_device *netdev, int phy_id,
-+                                 int idx)
-+{
-+      return __smsc75xx_mdio_read(netdev, phy_id, idx, 1);
-+}
-+
-+static void smsc75xx_mdio_write_nopm(struct net_device *netdev, int phy_id,
-+                                   int idx, int regval)
-+{
-+      __smsc75xx_mdio_write(netdev, phy_id, idx, regval, 1);
-+}
-+
-+static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
-+{
-+      return __smsc75xx_mdio_read(netdev, phy_id, idx, 0);
-+}
-+
-+static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
-+                              int regval)
-+{
-+      __smsc75xx_mdio_write(netdev, phy_id, idx, regval, 0);
-+}
-+
-+static int smsc75xx_wait_eeprom(struct usbnet *dev)
-+{
-+      unsigned long start_time = jiffies;
-+      u32 val;
-+      int ret;
-+
-+      do {
-+              ret = smsc75xx_read_reg(dev, E2P_CMD, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading E2P_CMD\n");
-+                      return ret;
-+              }
-+
-+              if (!(val & E2P_CMD_BUSY) || (val & E2P_CMD_TIMEOUT))
-+                      break;
-+              udelay(40);
-+      } while (!time_after(jiffies, start_time + HZ));
-+
-+      if (val & (E2P_CMD_TIMEOUT | E2P_CMD_BUSY)) {
-+              netdev_warn(dev->net, "EEPROM read operation timeout\n");
-+              return -EIO;
-+      }
-+
-+      return 0;
-+}
-+
-+static int smsc75xx_eeprom_confirm_not_busy(struct usbnet *dev)
-+{
-+      unsigned long start_time = jiffies;
-+      u32 val;
-+      int ret;
-+
-+      do {
-+              ret = smsc75xx_read_reg(dev, E2P_CMD, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading E2P_CMD\n");
-+                      return ret;
-+              }
-+
-+              if (!(val & E2P_CMD_BUSY))
-+                      return 0;
-+
-+              udelay(40);
-+      } while (!time_after(jiffies, start_time + HZ));
-+
-+      netdev_warn(dev->net, "EEPROM is busy\n");
-+      return -EIO;
-+}
-+
-+static int smsc75xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
-+                              u8 *data)
-+{
-+      u32 val;
-+      int i, ret;
-+
-+      BUG_ON(!dev);
-+      BUG_ON(!data);
-+
-+      ret = smsc75xx_eeprom_confirm_not_busy(dev);
-+      if (ret)
-+              return ret;
-+
-+      for (i = 0; i < length; i++) {
-+              val = E2P_CMD_BUSY | E2P_CMD_READ | (offset & E2P_CMD_ADDR);
-+              ret = smsc75xx_write_reg(dev, E2P_CMD, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing E2P_CMD\n");
-+                      return ret;
-+              }
-+
-+              ret = smsc75xx_wait_eeprom(dev);
-+              if (ret < 0)
-+                      return ret;
-+
-+              ret = smsc75xx_read_reg(dev, E2P_DATA, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading E2P_DATA\n");
-+                      return ret;
-+              }
-+
-+              data[i] = val & 0xFF;
-+              offset++;
-+      }
-+
-+      return 0;
-+}
-+
-+static int smsc75xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
-+                               u8 *data)
-+{
-+      u32 val;
-+      int i, ret;
-+
-+      BUG_ON(!dev);
-+      BUG_ON(!data);
-+
-+      ret = smsc75xx_eeprom_confirm_not_busy(dev);
-+      if (ret)
-+              return ret;
-+
-+      /* Issue write/erase enable command */
-+      val = E2P_CMD_BUSY | E2P_CMD_EWEN;
-+      ret = smsc75xx_write_reg(dev, E2P_CMD, val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing E2P_CMD\n");
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_wait_eeprom(dev);
-+      if (ret < 0)
-+              return ret;
-+
-+      for (i = 0; i < length; i++) {
-+
-+              /* Fill data register */
-+              val = data[i];
-+              ret = smsc75xx_write_reg(dev, E2P_DATA, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing E2P_DATA\n");
-+                      return ret;
-+              }
-+
-+              /* Send "write" command */
-+              val = E2P_CMD_BUSY | E2P_CMD_WRITE | (offset & E2P_CMD_ADDR);
-+              ret = smsc75xx_write_reg(dev, E2P_CMD, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing E2P_CMD\n");
-+                      return ret;
-+              }
-+
-+              ret = smsc75xx_wait_eeprom(dev);
-+              if (ret < 0)
-+                      return ret;
-+
-+              offset++;
-+      }
-+
-+      return 0;
-+}
-+
-+static int smsc75xx_dataport_wait_not_busy(struct usbnet *dev)
-+{
-+      int i, ret;
-+
-+      for (i = 0; i < 100; i++) {
-+              u32 dp_sel;
-+              ret = smsc75xx_read_reg(dev, DP_SEL, &dp_sel);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading DP_SEL\n");
-+                      return ret;
-+              }
-+
-+              if (dp_sel & DP_SEL_DPRDY)
-+                      return 0;
-+
-+              udelay(40);
-+      }
-+
-+      netdev_warn(dev->net, "smsc75xx_dataport_wait_not_busy timed out\n");
-+
-+      return -EIO;
-+}
-+
-+static int smsc75xx_dataport_write(struct usbnet *dev, u32 ram_select, u32 addr,
-+                                 u32 length, u32 *buf)
-+{
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      u32 dp_sel;
-+      int i, ret;
-+
-+      mutex_lock(&pdata->dataport_mutex);
-+
-+      ret = smsc75xx_dataport_wait_not_busy(dev);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "smsc75xx_dataport_write busy on entry\n");
-+              goto done;
-+      }
-+
-+      ret = smsc75xx_read_reg(dev, DP_SEL, &dp_sel);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading DP_SEL\n");
-+              goto done;
-+      }
-+
-+      dp_sel &= ~DP_SEL_RSEL;
-+      dp_sel |= ram_select;
-+      ret = smsc75xx_write_reg(dev, DP_SEL, dp_sel);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing DP_SEL\n");
-+              goto done;
-+      }
-+
-+      for (i = 0; i < length; i++) {
-+              ret = smsc75xx_write_reg(dev, DP_ADDR, addr + i);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing DP_ADDR\n");
-+                      goto done;
-+              }
-+
-+              ret = smsc75xx_write_reg(dev, DP_DATA, buf[i]);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing DP_DATA\n");
-+                      goto done;
-+              }
-+
-+              ret = smsc75xx_write_reg(dev, DP_CMD, DP_CMD_WRITE);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing DP_CMD\n");
-+                      goto done;
-+              }
-+
-+              ret = smsc75xx_dataport_wait_not_busy(dev);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "smsc75xx_dataport_write timeout\n");
-+                      goto done;
-+              }
-+      }
-+
-+done:
-+      mutex_unlock(&pdata->dataport_mutex);
-+      return ret;
-+}
-+
-+/* returns hash bit number for given MAC address */
-+static u32 smsc75xx_hash(char addr[ETH_ALEN])
-+{
-+      return (ether_crc(ETH_ALEN, addr) >> 23) & 0x1ff;
-+}
-+
-+static void smsc75xx_deferred_multicast_write(struct work_struct *param)
-+{
-+      struct smsc75xx_priv *pdata =
-+              container_of(param, struct smsc75xx_priv, set_multicast);
-+      struct usbnet *dev = pdata->dev;
-+      int ret;
-+
-+      netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x\n",
-+                pdata->rfe_ctl);
-+
-+      smsc75xx_dataport_write(dev, DP_SEL_VHF, DP_SEL_VHF_VLAN_LEN,
-+              DP_SEL_VHF_HASH_LEN, pdata->multicast_hash_table);
-+
-+      ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
-+      if (ret < 0)
-+              netdev_warn(dev->net, "Error writing RFE_CRL\n");
-+}
-+
-+static void smsc75xx_set_multicast(struct net_device *netdev)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      unsigned long flags;
-+      int i;
-+
-+      spin_lock_irqsave(&pdata->rfe_ctl_lock, flags);
-+
-+      pdata->rfe_ctl &=
-+              ~(RFE_CTL_AU | RFE_CTL_AM | RFE_CTL_DPF | RFE_CTL_MHF);
-+      pdata->rfe_ctl |= RFE_CTL_AB;
-+
-+      for (i = 0; i < DP_SEL_VHF_HASH_LEN; i++)
-+              pdata->multicast_hash_table[i] = 0;
-+
-+      if (dev->net->flags & IFF_PROMISC) {
-+              netif_dbg(dev, drv, dev->net, "promiscuous mode enabled\n");
-+              pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_AU;
-+      } else if (dev->net->flags & IFF_ALLMULTI) {
-+              netif_dbg(dev, drv, dev->net, "receive all multicast enabled\n");
-+              pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_DPF;
-+      } else if (!netdev_mc_empty(dev->net)) {
-+              struct netdev_hw_addr *ha;
-+
-+              netif_dbg(dev, drv, dev->net, "receive multicast hash filter\n");
-+
-+              pdata->rfe_ctl |= RFE_CTL_MHF | RFE_CTL_DPF;
-+
-+              netdev_for_each_mc_addr(ha, netdev) {
-+                      u32 bitnum = smsc75xx_hash(ha->addr);
-+                      pdata->multicast_hash_table[bitnum / 32] |=
-+                              (1 << (bitnum % 32));
-+              }
-+      } else {
-+              netif_dbg(dev, drv, dev->net, "receive own packets only\n");
-+              pdata->rfe_ctl |= RFE_CTL_DPF;
-+      }
-+
-+      spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags);
-+
-+      /* defer register writes to a sleepable context */
-+      schedule_work(&pdata->set_multicast);
-+}
-+
-+static int smsc75xx_update_flowcontrol(struct usbnet *dev, u8 duplex,
-+                                          u16 lcladv, u16 rmtadv)
-+{
-+      u32 flow = 0, fct_flow = 0;
-+      int ret;
-+
-+      if (duplex == DUPLEX_FULL) {
-+              u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
-+
-+              if (cap & FLOW_CTRL_TX) {
-+                      flow = (FLOW_TX_FCEN | 0xFFFF);
-+                      /* set fct_flow thresholds to 20% and 80% */
-+                      fct_flow = (8 << 8) | 32;
-+              }
-+
-+              if (cap & FLOW_CTRL_RX)
-+                      flow |= FLOW_RX_FCEN;
-+
-+              netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s\n",
-+                        (cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
-+                        (cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
-+      } else {
-+              netif_dbg(dev, link, dev->net, "half duplex\n");
-+      }
-+
-+      ret = smsc75xx_write_reg(dev, FLOW, flow);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing FLOW\n");
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_write_reg(dev, FCT_FLOW, fct_flow);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing FCT_FLOW\n");
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static int smsc75xx_link_reset(struct usbnet *dev)
-+{
-+      struct mii_if_info *mii = &dev->mii;
-+      struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
-+      u16 lcladv, rmtadv;
-+      int ret;
-+
-+      /* write to clear phy interrupt status */
-+      smsc75xx_mdio_write(dev->net, mii->phy_id, PHY_INT_SRC,
-+              PHY_INT_SRC_CLEAR_ALL);
-+
-+      ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing INT_STS\n");
-+              return ret;
-+      }
-+
-+      mii_check_media(mii, 1, 1);
-+      mii_ethtool_gset(&dev->mii, &ecmd);
-+      lcladv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE);
-+      rmtadv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_LPA);
-+
-+      netif_dbg(dev, link, dev->net, "speed: %u duplex: %d lcladv: %04x rmtadv: %04x\n",
-+                ethtool_cmd_speed(&ecmd), ecmd.duplex, lcladv, rmtadv);
-+
-+      return smsc75xx_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
-+}
-+
-+static void smsc75xx_status(struct usbnet *dev, struct urb *urb)
-+{
-+      u32 intdata;
-+
-+      if (urb->actual_length != 4) {
-+              netdev_warn(dev->net, "unexpected urb length %d\n",
-+                          urb->actual_length);
-+              return;
-+      }
-+
-+      memcpy(&intdata, urb->transfer_buffer, 4);
-+      le32_to_cpus(&intdata);
-+
-+      netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata);
-+
-+      if (intdata & INT_ENP_PHY_INT)
-+              usbnet_defer_kevent(dev, EVENT_LINK_RESET);
-+      else
-+              netdev_warn(dev->net, "unexpected interrupt, intdata=0x%08X\n",
-+                          intdata);
-+}
-+
-+static int smsc75xx_ethtool_get_eeprom_len(struct net_device *net)
-+{
-+      return MAX_EEPROM_SIZE;
-+}
-+
-+static int smsc75xx_ethtool_get_eeprom(struct net_device *netdev,
-+                                     struct ethtool_eeprom *ee, u8 *data)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+
-+      ee->magic = LAN75XX_EEPROM_MAGIC;
-+
-+      return smsc75xx_read_eeprom(dev, ee->offset, ee->len, data);
-+}
-+
-+static int smsc75xx_ethtool_set_eeprom(struct net_device *netdev,
-+                                     struct ethtool_eeprom *ee, u8 *data)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+
-+      if (ee->magic != LAN75XX_EEPROM_MAGIC) {
-+              netdev_warn(dev->net, "EEPROM: magic value mismatch: 0x%x\n",
-+                          ee->magic);
-+              return -EINVAL;
-+      }
-+
-+      return smsc75xx_write_eeprom(dev, ee->offset, ee->len, data);
-+}
-+
-+static void smsc75xx_ethtool_get_wol(struct net_device *net,
-+                                   struct ethtool_wolinfo *wolinfo)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+
-+      wolinfo->supported = SUPPORTED_WAKE;
-+      wolinfo->wolopts = pdata->wolopts;
-+}
-+
-+static int smsc75xx_ethtool_set_wol(struct net_device *net,
-+                                  struct ethtool_wolinfo *wolinfo)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      int ret;
-+
-+      pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
-+
-+      ret = device_set_wakeup_enable(&dev->udev->dev, pdata->wolopts);
-+      if (ret < 0)
-+              netdev_warn(dev->net, "device_set_wakeup_enable error %d\n", ret);
-+
-+      return ret;
-+}
-+
-+static const struct ethtool_ops smsc75xx_ethtool_ops = {
-+      .get_link       = usbnet_get_link,
-+      .nway_reset     = usbnet_nway_reset,
-+      .get_drvinfo    = usbnet_get_drvinfo,
-+      .get_msglevel   = usbnet_get_msglevel,
-+      .set_msglevel   = usbnet_set_msglevel,
-+      .get_settings   = usbnet_get_settings,
-+      .set_settings   = usbnet_set_settings,
-+      .get_eeprom_len = smsc75xx_ethtool_get_eeprom_len,
-+      .get_eeprom     = smsc75xx_ethtool_get_eeprom,
-+      .set_eeprom     = smsc75xx_ethtool_set_eeprom,
-+      .get_wol        = smsc75xx_ethtool_get_wol,
-+      .set_wol        = smsc75xx_ethtool_set_wol,
-+};
-+
-+static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+
-+      if (!netif_running(netdev))
-+              return -EINVAL;
-+
-+      return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
-+}
-+
-+static void smsc75xx_init_mac_address(struct usbnet *dev)
-+{
-+      /* try reading mac address from EEPROM */
-+      if (smsc75xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
-+                      dev->net->dev_addr) == 0) {
-+              if (is_valid_ether_addr(dev->net->dev_addr)) {
-+                      /* eeprom values are valid so use them */
-+                      netif_dbg(dev, ifup, dev->net,
-+                                "MAC address read from EEPROM\n");
-+                      return;
-+              }
-+      }
-+
-+      /* no eeprom, or eeprom values are invalid. generate random MAC */
-+      eth_hw_addr_random(dev->net);
-+      netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n");
-+}
-+
-+static int smsc75xx_set_mac_address(struct usbnet *dev)
-+{
-+      u32 addr_lo = dev->net->dev_addr[0] | dev->net->dev_addr[1] << 8 |
-+              dev->net->dev_addr[2] << 16 | dev->net->dev_addr[3] << 24;
-+      u32 addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8;
-+
-+      int ret = smsc75xx_write_reg(dev, RX_ADDRH, addr_hi);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write RX_ADDRH: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_write_reg(dev, RX_ADDRL, addr_lo);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write RX_ADDRL: %d\n", ret);
-+              return ret;
-+      }
-+
-+      addr_hi |= ADDR_FILTX_FB_VALID;
-+      ret = smsc75xx_write_reg(dev, ADDR_FILTX, addr_hi);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write ADDR_FILTX: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_write_reg(dev, ADDR_FILTX + 4, addr_lo);
-+      if (ret < 0)
-+              netdev_warn(dev->net, "Failed to write ADDR_FILTX+4: %d\n", ret);
-+
-+      return ret;
-+}
-+
-+static int smsc75xx_phy_initialize(struct usbnet *dev)
-+{
-+      int bmcr, ret, timeout = 0;
-+
-+      /* Initialize MII structure */
-+      dev->mii.dev = dev->net;
-+      dev->mii.mdio_read = smsc75xx_mdio_read;
-+      dev->mii.mdio_write = smsc75xx_mdio_write;
-+      dev->mii.phy_id_mask = 0x1f;
-+      dev->mii.reg_num_mask = 0x1f;
-+      dev->mii.supports_gmii = 1;
-+      dev->mii.phy_id = SMSC75XX_INTERNAL_PHY_ID;
-+
-+      /* reset phy and wait for reset to complete */
-+      smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-+
-+      do {
-+              msleep(10);
-+              bmcr = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
-+              if (bmcr < 0) {
-+                      netdev_warn(dev->net, "Error reading MII_BMCR\n");
-+                      return bmcr;
-+              }
-+              timeout++;
-+      } while ((bmcr & BMCR_RESET) && (timeout < 100));
-+
-+      if (timeout >= 100) {
-+              netdev_warn(dev->net, "timeout on PHY Reset\n");
-+              return -EIO;
-+      }
-+
-+      smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
-+              ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP |
-+              ADVERTISE_PAUSE_ASYM);
-+      smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000,
-+              ADVERTISE_1000FULL);
-+
-+      /* read and write to clear phy interrupt status */
-+      ret = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading PHY_INT_SRC\n");
-+              return ret;
-+      }
-+
-+      smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_SRC, 0xffff);
-+
-+      smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
-+              PHY_INT_MASK_DEFAULT);
-+      mii_nway_restart(&dev->mii);
-+
-+      netif_dbg(dev, ifup, dev->net, "phy initialised successfully\n");
-+      return 0;
-+}
-+
-+static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size)
-+{
-+      int ret = 0;
-+      u32 buf;
-+      bool rxenabled;
-+
-+      ret = smsc75xx_read_reg(dev, MAC_RX, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read MAC_RX: %d\n", ret);
-+              return ret;
-+      }
-+
-+      rxenabled = ((buf & MAC_RX_RXEN) != 0);
-+
-+      if (rxenabled) {
-+              buf &= ~MAC_RX_RXEN;
-+              ret = smsc75xx_write_reg(dev, MAC_RX, buf);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
-+                      return ret;
-+              }
-+      }
-+
-+      /* add 4 to size for FCS */
-+      buf &= ~MAC_RX_MAX_SIZE;
-+      buf |= (((size + 4) << MAC_RX_MAX_SIZE_SHIFT) & MAC_RX_MAX_SIZE);
-+
-+      ret = smsc75xx_write_reg(dev, MAC_RX, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
-+              return ret;
-+      }
-+
-+      if (rxenabled) {
-+              buf |= MAC_RX_RXEN;
-+              ret = smsc75xx_write_reg(dev, MAC_RX, buf);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
-+                      return ret;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      int ret;
-+
-+      if (new_mtu > MAX_SINGLE_PACKET_SIZE)
-+              return -EINVAL;
-+
-+      ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu + ETH_HLEN);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to set mac rx frame length\n");
-+              return ret;
-+      }
-+
-+      return usbnet_change_mtu(netdev, new_mtu);
-+}
-+
-+/* Enable or disable Rx checksum offload engine */
-+static int smsc75xx_set_features(struct net_device *netdev,
-+      netdev_features_t features)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      unsigned long flags;
-+      int ret;
-+
-+      spin_lock_irqsave(&pdata->rfe_ctl_lock, flags);
-+
-+      if (features & NETIF_F_RXCSUM)
-+              pdata->rfe_ctl |= RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM;
-+      else
-+              pdata->rfe_ctl &= ~(RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM);
-+
-+      spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags);
-+      /* it's racing here! */
-+
-+      ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
-+      if (ret < 0)
-+              netdev_warn(dev->net, "Error writing RFE_CTL\n");
-+
-+      return ret;
-+}
-+
-+static int smsc75xx_wait_ready(struct usbnet *dev, int in_pm)
-+{
-+      int timeout = 0;
-+
-+      do {
-+              u32 buf;
-+              int ret;
-+
-+              ret = __smsc75xx_read_reg(dev, PMT_CTL, &buf, in_pm);
-+
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret);
-+                      return ret;
-+              }
-+
-+              if (buf & PMT_CTL_DEV_RDY)
-+                      return 0;
-+
-+              msleep(10);
-+              timeout++;
-+      } while (timeout < 100);
-+
-+      netdev_warn(dev->net, "timeout waiting for device ready\n");
-+      return -EIO;
-+}
-+
-+static int smsc75xx_reset(struct usbnet *dev)
-+{
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      u32 buf;
-+      int ret = 0, timeout;
-+
-+      netif_dbg(dev, ifup, dev->net, "entering smsc75xx_reset\n");
-+
-+      ret = smsc75xx_wait_ready(dev, 0);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "device not ready in smsc75xx_reset\n");
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
-+              return ret;
-+      }
-+
-+      buf |= HW_CFG_LRST;
-+
-+      ret = smsc75xx_write_reg(dev, HW_CFG, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write HW_CFG: %d\n", ret);
-+              return ret;
-+      }
-+
-+      timeout = 0;
-+      do {
-+              msleep(10);
-+              ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
-+                      return ret;
-+              }
-+              timeout++;
-+      } while ((buf & HW_CFG_LRST) && (timeout < 100));
-+
-+      if (timeout >= 100) {
-+              netdev_warn(dev->net, "timeout on completion of Lite Reset\n");
-+              return -EIO;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "Lite reset complete, resetting PHY\n");
-+
-+      ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret);
-+              return ret;
-+      }
-+
-+      buf |= PMT_CTL_PHY_RST;
-+
-+      ret = smsc75xx_write_reg(dev, PMT_CTL, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write PMT_CTL: %d\n", ret);
-+              return ret;
-+      }
-+
-+      timeout = 0;
-+      do {
-+              msleep(10);
-+              ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret);
-+                      return ret;
-+              }
-+              timeout++;
-+      } while ((buf & PMT_CTL_PHY_RST) && (timeout < 100));
-+
-+      if (timeout >= 100) {
-+              netdev_warn(dev->net, "timeout waiting for PHY Reset\n");
-+              return -EIO;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "PHY reset complete\n");
-+
-+      ret = smsc75xx_set_mac_address(dev);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to set mac address\n");
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "MAC Address: %pM\n",
-+                dev->net->dev_addr);
-+
-+      ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x\n",
-+                buf);
-+
-+      buf |= HW_CFG_BIR;
-+
-+      ret = smsc75xx_write_reg(dev, HW_CFG, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net,  "Failed to write HW_CFG: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG after writing HW_CFG_BIR: 0x%08x\n",
-+                buf);
-+
-+      if (!turbo_mode) {
-+              buf = 0;
-+              dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE;
-+      } else if (dev->udev->speed == USB_SPEED_HIGH) {
-+              buf = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE;
-+              dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE;
-+      } else {
-+              buf = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE;
-+              dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n",
-+                (ulong)dev->rx_urb_size);
-+
-+      ret = smsc75xx_write_reg(dev, BURST_CAP, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write BURST_CAP: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_read_reg(dev, BURST_CAP, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read BURST_CAP: %d\n", ret);
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net,
-+                "Read Value from BURST_CAP after writing: 0x%08x\n", buf);
-+
-+      ret = smsc75xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write BULK_IN_DLY: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_read_reg(dev, BULK_IN_DLY, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read BULK_IN_DLY: %d\n", ret);
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net,
-+                "Read Value from BULK_IN_DLY after writing: 0x%08x\n", buf);
-+
-+      if (turbo_mode) {
-+              ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
-+                      return ret;
-+              }
-+
-+              netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x\n", buf);
-+
-+              buf |= (HW_CFG_MEF | HW_CFG_BCE);
-+
-+              ret = smsc75xx_write_reg(dev, HW_CFG, buf);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Failed to write HW_CFG: %d\n", ret);
-+                      return ret;
-+              }
-+
-+              ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
-+                      return ret;
-+              }
-+
-+              netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x\n", buf);
-+      }
-+
-+      /* set FIFO sizes */
-+      buf = (MAX_RX_FIFO_SIZE - 512) / 512;
-+      ret = smsc75xx_write_reg(dev, FCT_RX_FIFO_END, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write FCT_RX_FIFO_END: %d\n", ret);
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "FCT_RX_FIFO_END set to 0x%08x\n", buf);
-+
-+      buf = (MAX_TX_FIFO_SIZE - 512) / 512;
-+      ret = smsc75xx_write_reg(dev, FCT_TX_FIFO_END, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write FCT_TX_FIFO_END: %d\n", ret);
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "FCT_TX_FIFO_END set to 0x%08x\n", buf);
-+
-+      ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write INT_STS: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_read_reg(dev, ID_REV, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret);
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", buf);
-+
-+      ret = smsc75xx_read_reg(dev, E2P_CMD, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read E2P_CMD: %d\n", ret);
-+              return ret;
-+      }
-+
-+      /* only set default GPIO/LED settings if no EEPROM is detected */
-+      if (!(buf & E2P_CMD_LOADED)) {
-+              ret = smsc75xx_read_reg(dev, LED_GPIO_CFG, &buf);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Failed to read LED_GPIO_CFG: %d\n", ret);
-+                      return ret;
-+              }
-+
-+              buf &= ~(LED_GPIO_CFG_LED2_FUN_SEL | LED_GPIO_CFG_LED10_FUN_SEL);
-+              buf |= LED_GPIO_CFG_LEDGPIO_EN | LED_GPIO_CFG_LED2_FUN_SEL;
-+
-+              ret = smsc75xx_write_reg(dev, LED_GPIO_CFG, buf);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Failed to write LED_GPIO_CFG: %d\n", ret);
-+                      return ret;
-+              }
-+      }
-+
-+      ret = smsc75xx_write_reg(dev, FLOW, 0);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write FLOW: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_write_reg(dev, FCT_FLOW, 0);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write FCT_FLOW: %d\n", ret);
-+              return ret;
-+      }
-+
-+      /* Don't need rfe_ctl_lock during initialisation */
-+      ret = smsc75xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read RFE_CTL: %d\n", ret);
-+              return ret;
-+      }
-+
-+      pdata->rfe_ctl |= RFE_CTL_AB | RFE_CTL_DPF;
-+
-+      ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write RFE_CTL: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read RFE_CTL: %d\n", ret);
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "RFE_CTL set to 0x%08x\n",
-+                pdata->rfe_ctl);
-+
-+      /* Enable or disable checksum offload engines */
-+      smsc75xx_set_features(dev->net, dev->net->features);
-+
-+      smsc75xx_set_multicast(dev->net);
-+
-+      ret = smsc75xx_phy_initialize(dev);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to initialize PHY: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_read_reg(dev, INT_EP_CTL, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read INT_EP_CTL: %d\n", ret);
-+              return ret;
-+      }
-+
-+      /* enable PHY interrupts */
-+      buf |= INT_ENP_PHY_INT;
-+
-+      ret = smsc75xx_write_reg(dev, INT_EP_CTL, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write INT_EP_CTL: %d\n", ret);
-+              return ret;
-+      }
-+
-+      /* allow mac to detect speed and duplex from phy */
-+      ret = smsc75xx_read_reg(dev, MAC_CR, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read MAC_CR: %d\n", ret);
-+              return ret;
-+      }
-+
-+      buf |= (MAC_CR_ADD | MAC_CR_ASD);
-+      ret = smsc75xx_write_reg(dev, MAC_CR, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write MAC_CR: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_read_reg(dev, MAC_TX, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read MAC_TX: %d\n", ret);
-+              return ret;
-+      }
-+
-+      buf |= MAC_TX_TXEN;
-+
-+      ret = smsc75xx_write_reg(dev, MAC_TX, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write MAC_TX: %d\n", ret);
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "MAC_TX set to 0x%08x\n", buf);
-+
-+      ret = smsc75xx_read_reg(dev, FCT_TX_CTL, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read FCT_TX_CTL: %d\n", ret);
-+              return ret;
-+      }
-+
-+      buf |= FCT_TX_CTL_EN;
-+
-+      ret = smsc75xx_write_reg(dev, FCT_TX_CTL, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write FCT_TX_CTL: %d\n", ret);
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x\n", buf);
-+
-+      ret = smsc75xx_set_rx_max_frame_length(dev, dev->net->mtu + ETH_HLEN);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to set max rx frame length\n");
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_read_reg(dev, MAC_RX, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read MAC_RX: %d\n", ret);
-+              return ret;
-+      }
-+
-+      buf |= MAC_RX_RXEN;
-+
-+      ret = smsc75xx_write_reg(dev, MAC_RX, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "MAC_RX set to 0x%08x\n", buf);
-+
-+      ret = smsc75xx_read_reg(dev, FCT_RX_CTL, &buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read FCT_RX_CTL: %d\n", ret);
-+              return ret;
-+      }
-+
-+      buf |= FCT_RX_CTL_EN;
-+
-+      ret = smsc75xx_write_reg(dev, FCT_RX_CTL, buf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write FCT_RX_CTL: %d\n", ret);
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "FCT_RX_CTL set to 0x%08x\n", buf);
-+
-+      netif_dbg(dev, ifup, dev->net, "smsc75xx_reset, return 0\n");
-+      return 0;
-+}
-+
-+static const struct net_device_ops smsc75xx_netdev_ops = {
-+      .ndo_open               = usbnet_open,
-+      .ndo_stop               = usbnet_stop,
-+      .ndo_start_xmit         = usbnet_start_xmit,
-+      .ndo_tx_timeout         = usbnet_tx_timeout,
-+      .ndo_change_mtu         = smsc75xx_change_mtu,
-+      .ndo_set_mac_address    = eth_mac_addr,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_do_ioctl           = smsc75xx_ioctl,
-+      .ndo_set_rx_mode        = smsc75xx_set_multicast,
-+      .ndo_set_features       = smsc75xx_set_features,
-+};
-+
-+static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      struct smsc75xx_priv *pdata = NULL;
-+      int ret;
-+
-+      printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
-+
-+      ret = usbnet_get_endpoints(dev, intf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "usbnet_get_endpoints failed: %d\n", ret);
-+              return ret;
-+      }
-+
-+      dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc75xx_priv),
-+                                            GFP_KERNEL);
-+
-+      pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      if (!pdata)
-+              return -ENOMEM;
-+
-+      pdata->dev = dev;
-+
-+      spin_lock_init(&pdata->rfe_ctl_lock);
-+      mutex_init(&pdata->dataport_mutex);
-+
-+      INIT_WORK(&pdata->set_multicast, smsc75xx_deferred_multicast_write);
-+
-+      if (DEFAULT_TX_CSUM_ENABLE)
-+              dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-+
-+      if (DEFAULT_RX_CSUM_ENABLE)
-+              dev->net->features |= NETIF_F_RXCSUM;
-+
-+      dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-+                              NETIF_F_RXCSUM;
-+
-+      ret = smsc75xx_wait_ready(dev, 0);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "device not ready in smsc75xx_bind\n");
-+              return ret;
-+      }
-+
-+      smsc75xx_init_mac_address(dev);
-+
-+      /* Init all registers */
-+      ret = smsc75xx_reset(dev);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "smsc75xx_reset error %d\n", ret);
-+              return ret;
-+      }
-+
-+      dev->net->netdev_ops = &smsc75xx_netdev_ops;
-+      dev->net->ethtool_ops = &smsc75xx_ethtool_ops;
-+      dev->net->flags |= IFF_MULTICAST;
-+      dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD;
-+      dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
-+      return 0;
-+}
-+
-+static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      if (pdata) {
-+              netif_dbg(dev, ifdown, dev->net, "free pdata\n");
-+              kfree(pdata);
-+              pdata = NULL;
-+              dev->data[0] = 0;
-+      }
-+}
-+
-+static u16 smsc_crc(const u8 *buffer, size_t len)
-+{
-+      return bitrev16(crc16(0xFFFF, buffer, len));
-+}
-+
-+static int smsc75xx_write_wuff(struct usbnet *dev, int filter, u32 wuf_cfg,
-+                             u32 wuf_mask1)
-+{
-+      int cfg_base = WUF_CFGX + filter * 4;
-+      int mask_base = WUF_MASKX + filter * 16;
-+      int ret;
-+
-+      ret = smsc75xx_write_reg(dev, cfg_base, wuf_cfg);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing WUF_CFGX\n");
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_write_reg(dev, mask_base, wuf_mask1);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing WUF_MASKX\n");
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_write_reg(dev, mask_base + 4, 0);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing WUF_MASKX\n");
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_write_reg(dev, mask_base + 8, 0);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing WUF_MASKX\n");
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_write_reg(dev, mask_base + 12, 0);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing WUF_MASKX\n");
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static int smsc75xx_enter_suspend0(struct usbnet *dev)
-+{
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      u32 val;
-+      int ret;
-+
-+      ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading PMT_CTL\n");
-+              return ret;
-+      }
-+
-+      val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_PHY_RST));
-+      val |= PMT_CTL_SUS_MODE_0 | PMT_CTL_WOL_EN | PMT_CTL_WUPS;
-+
-+      ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing PMT_CTL\n");
-+              return ret;
-+      }
-+
-+      pdata->suspend_flags |= SUSPEND_SUSPEND0;
-+
-+      return 0;
-+}
-+
-+static int smsc75xx_enter_suspend1(struct usbnet *dev)
-+{
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      u32 val;
-+      int ret;
-+
-+      ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading PMT_CTL\n");
-+              return ret;
-+      }
-+
-+      val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
-+      val |= PMT_CTL_SUS_MODE_1;
-+
-+      ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing PMT_CTL\n");
-+              return ret;
-+      }
-+
-+      /* clear wol status, enable energy detection */
-+      val &= ~PMT_CTL_WUPS;
-+      val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN);
-+
-+      ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing PMT_CTL\n");
-+              return ret;
-+      }
-+
-+      pdata->suspend_flags |= SUSPEND_SUSPEND1;
-+
-+      return 0;
-+}
-+
-+static int smsc75xx_enter_suspend2(struct usbnet *dev)
-+{
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      u32 val;
-+      int ret;
-+
-+      ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading PMT_CTL\n");
-+              return ret;
-+      }
-+
-+      val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
-+      val |= PMT_CTL_SUS_MODE_2;
-+
-+      ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing PMT_CTL\n");
-+              return ret;
-+      }
-+
-+      pdata->suspend_flags |= SUSPEND_SUSPEND2;
-+
-+      return 0;
-+}
-+
-+static int smsc75xx_enter_suspend3(struct usbnet *dev)
-+{
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      u32 val;
-+      int ret;
-+
-+      ret = smsc75xx_read_reg_nopm(dev, FCT_RX_CTL, &val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading FCT_RX_CTL\n");
-+              return ret;
-+      }
-+
-+      if (val & FCT_RX_CTL_RXUSED) {
-+              netdev_dbg(dev->net, "rx fifo not empty in autosuspend\n");
-+              return -EBUSY;
-+      }
-+
-+      ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading PMT_CTL\n");
-+              return ret;
-+      }
-+
-+      val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
-+      val |= PMT_CTL_SUS_MODE_3 | PMT_CTL_RES_CLR_WKP_EN;
-+
-+      ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing PMT_CTL\n");
-+              return ret;
-+      }
-+
-+      /* clear wol status */
-+      val &= ~PMT_CTL_WUPS;
-+      val |= PMT_CTL_WUPS_WOL;
-+
-+      ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing PMT_CTL\n");
-+              return ret;
-+      }
-+
-+      pdata->suspend_flags |= SUSPEND_SUSPEND3;
-+
-+      return 0;
-+}
-+
-+static int smsc75xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
-+{
-+      struct mii_if_info *mii = &dev->mii;
-+      int ret;
-+
-+      netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n");
-+
-+      /* read to clear */
-+      ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_SRC);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading PHY_INT_SRC\n");
-+              return ret;
-+      }
-+
-+      /* enable interrupt source */
-+      ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_MASK);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading PHY_INT_MASK\n");
-+              return ret;
-+      }
-+
-+      ret |= mask;
-+
-+      smsc75xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_INT_MASK, ret);
-+
-+      return 0;
-+}
-+
-+static int smsc75xx_link_ok_nopm(struct usbnet *dev)
-+{
-+      struct mii_if_info *mii = &dev->mii;
-+      int ret;
-+
-+      /* first, a dummy read, needed to latch some MII phys */
-+      ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading MII_BMSR\n");
-+              return ret;
-+      }
-+
-+      ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading MII_BMSR\n");
-+              return ret;
-+      }
-+
-+      return !!(ret & BMSR_LSTATUS);
-+}
-+
-+static int smsc75xx_autosuspend(struct usbnet *dev, u32 link_up)
-+{
-+      int ret;
-+
-+      if (!netif_running(dev->net)) {
-+              /* interface is ifconfig down so fully power down hw */
-+              netdev_dbg(dev->net, "autosuspend entering SUSPEND2\n");
-+              return smsc75xx_enter_suspend2(dev);
-+      }
-+
-+      if (!link_up) {
-+              /* link is down so enter EDPD mode */
-+              netdev_dbg(dev->net, "autosuspend entering SUSPEND1\n");
-+
-+              /* enable PHY wakeup events for if cable is attached */
-+              ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
-+                      PHY_INT_MASK_ANEG_COMP);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
-+                      return ret;
-+              }
-+
-+              netdev_info(dev->net, "entering SUSPEND1 mode\n");
-+              return smsc75xx_enter_suspend1(dev);
-+      }
-+
-+      /* enable PHY wakeup events so we remote wakeup if cable is pulled */
-+      ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
-+              PHY_INT_MASK_LINK_DOWN);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
-+              return ret;
-+      }
-+
-+      netdev_dbg(dev->net, "autosuspend entering SUSPEND3\n");
-+      return smsc75xx_enter_suspend3(dev);
-+}
-+
-+static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
-+{
-+      struct usbnet *dev = usb_get_intfdata(intf);
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      u32 val, link_up;
-+      int ret;
-+
-+      ret = usbnet_suspend(intf, message);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "usbnet_suspend error\n");
-+              return ret;
-+      }
-+
-+      if (pdata->suspend_flags) {
-+              netdev_warn(dev->net, "error during last resume\n");
-+              pdata->suspend_flags = 0;
-+      }
-+
-+      /* determine if link is up using only _nopm functions */
-+      link_up = smsc75xx_link_ok_nopm(dev);
-+
-+      if (message.event == PM_EVENT_AUTO_SUSPEND) {
-+              ret = smsc75xx_autosuspend(dev, link_up);
-+              goto done;
-+      }
-+
-+      /* if we get this far we're not autosuspending */
-+      /* if no wol options set, or if link is down and we're not waking on
-+       * PHY activity, enter lowest power SUSPEND2 mode
-+       */
-+      if (!(pdata->wolopts & SUPPORTED_WAKE) ||
-+              !(link_up || (pdata->wolopts & WAKE_PHY))) {
-+              netdev_info(dev->net, "entering SUSPEND2 mode\n");
-+
-+              /* disable energy detect (link up) & wake up events */
-+              ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading WUCSR\n");
-+                      goto done;
-+              }
-+
-+              val &= ~(WUCSR_MPEN | WUCSR_WUEN);
-+
-+              ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing WUCSR\n");
-+                      goto done;
-+              }
-+
-+              ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading PMT_CTL\n");
-+                      goto done;
-+              }
-+
-+              val &= ~(PMT_CTL_ED_EN | PMT_CTL_WOL_EN);
-+
-+              ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing PMT_CTL\n");
-+                      goto done;
-+              }
-+
-+              ret = smsc75xx_enter_suspend2(dev);
-+              goto done;
-+      }
-+
-+      if (pdata->wolopts & WAKE_PHY) {
-+              ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
-+                      (PHY_INT_MASK_ANEG_COMP | PHY_INT_MASK_LINK_DOWN));
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
-+                      goto done;
-+              }
-+
-+              /* if link is down then configure EDPD and enter SUSPEND1,
-+               * otherwise enter SUSPEND0 below
-+               */
-+              if (!link_up) {
-+                      struct mii_if_info *mii = &dev->mii;
-+                      netdev_info(dev->net, "entering SUSPEND1 mode\n");
-+
-+                      /* enable energy detect power-down mode */
-+                      ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id,
-+                              PHY_MODE_CTRL_STS);
-+                      if (ret < 0) {
-+                              netdev_warn(dev->net, "Error reading PHY_MODE_CTRL_STS\n");
-+                              goto done;
-+                      }
-+
-+                      ret |= MODE_CTRL_STS_EDPWRDOWN;
-+
-+                      smsc75xx_mdio_write_nopm(dev->net, mii->phy_id,
-+                              PHY_MODE_CTRL_STS, ret);
-+
-+                      /* enter SUSPEND1 mode */
-+                      ret = smsc75xx_enter_suspend1(dev);
-+                      goto done;
-+              }
-+      }
-+
-+      if (pdata->wolopts & (WAKE_MCAST | WAKE_ARP)) {
-+              int i, filter = 0;
-+
-+              /* disable all filters */
-+              for (i = 0; i < WUF_NUM; i++) {
-+                      ret = smsc75xx_write_reg_nopm(dev, WUF_CFGX + i * 4, 0);
-+                      if (ret < 0) {
-+                              netdev_warn(dev->net, "Error writing WUF_CFGX\n");
-+                              goto done;
-+                      }
-+              }
-+
-+              if (pdata->wolopts & WAKE_MCAST) {
-+                      const u8 mcast[] = {0x01, 0x00, 0x5E};
-+                      netdev_info(dev->net, "enabling multicast detection\n");
-+
-+                      val = WUF_CFGX_EN | WUF_CFGX_ATYPE_MULTICAST
-+                              | smsc_crc(mcast, 3);
-+                      ret = smsc75xx_write_wuff(dev, filter++, val, 0x0007);
-+                      if (ret < 0) {
-+                              netdev_warn(dev->net, "Error writing wakeup filter\n");
-+                              goto done;
-+                      }
-+              }
-+
-+              if (pdata->wolopts & WAKE_ARP) {
-+                      const u8 arp[] = {0x08, 0x06};
-+                      netdev_info(dev->net, "enabling ARP detection\n");
-+
-+                      val = WUF_CFGX_EN | WUF_CFGX_ATYPE_ALL | (0x0C << 16)
-+                              | smsc_crc(arp, 2);
-+                      ret = smsc75xx_write_wuff(dev, filter++, val, 0x0003);
-+                      if (ret < 0) {
-+                              netdev_warn(dev->net, "Error writing wakeup filter\n");
-+                              goto done;
-+                      }
-+              }
-+
-+              /* clear any pending pattern match packet status */
-+              ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading WUCSR\n");
-+                      goto done;
-+              }
-+
-+              val |= WUCSR_WUFR;
-+
-+              ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing WUCSR\n");
-+                      goto done;
-+              }
-+
-+              netdev_info(dev->net, "enabling packet match detection\n");
-+              ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading WUCSR\n");
-+                      goto done;
-+              }
-+
-+              val |= WUCSR_WUEN;
-+
-+              ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing WUCSR\n");
-+                      goto done;
-+              }
-+      } else {
-+              netdev_info(dev->net, "disabling packet match detection\n");
-+              ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading WUCSR\n");
-+                      goto done;
-+              }
-+
-+              val &= ~WUCSR_WUEN;
-+
-+              ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing WUCSR\n");
-+                      goto done;
-+              }
-+      }
-+
-+      /* disable magic, bcast & unicast wakeup sources */
-+      ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading WUCSR\n");
-+              goto done;
-+      }
-+
-+      val &= ~(WUCSR_MPEN | WUCSR_BCST_EN | WUCSR_PFDA_EN);
-+
-+      ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing WUCSR\n");
-+              goto done;
-+      }
-+
-+      if (pdata->wolopts & WAKE_PHY) {
-+              netdev_info(dev->net, "enabling PHY wakeup\n");
-+
-+              ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading PMT_CTL\n");
-+                      goto done;
-+              }
-+
-+              /* clear wol status, enable energy detection */
-+              val &= ~PMT_CTL_WUPS;
-+              val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN);
-+
-+              ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing PMT_CTL\n");
-+                      goto done;
-+              }
-+      }
-+
-+      if (pdata->wolopts & WAKE_MAGIC) {
-+              netdev_info(dev->net, "enabling magic packet wakeup\n");
-+              ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading WUCSR\n");
-+                      goto done;
-+              }
-+
-+              /* clear any pending magic packet status */
-+              val |= WUCSR_MPR | WUCSR_MPEN;
-+
-+              ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing WUCSR\n");
-+                      goto done;
-+              }
-+      }
-+
-+      if (pdata->wolopts & WAKE_BCAST) {
-+              netdev_info(dev->net, "enabling broadcast detection\n");
-+              ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading WUCSR\n");
-+                      goto done;
-+              }
-+
-+              val |= WUCSR_BCAST_FR | WUCSR_BCST_EN;
-+
-+              ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing WUCSR\n");
-+                      goto done;
-+              }
-+      }
-+
-+      if (pdata->wolopts & WAKE_UCAST) {
-+              netdev_info(dev->net, "enabling unicast detection\n");
-+              ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading WUCSR\n");
-+                      goto done;
-+              }
-+
-+              val |= WUCSR_WUFR | WUCSR_PFDA_EN;
-+
-+              ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing WUCSR\n");
-+                      goto done;
-+              }
-+      }
-+
-+      /* enable receiver to enable frame reception */
-+      ret = smsc75xx_read_reg_nopm(dev, MAC_RX, &val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read MAC_RX: %d\n", ret);
-+              goto done;
-+      }
-+
-+      val |= MAC_RX_RXEN;
-+
-+      ret = smsc75xx_write_reg_nopm(dev, MAC_RX, val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
-+              goto done;
-+      }
-+
-+      /* some wol options are enabled, so enter SUSPEND0 */
-+      netdev_info(dev->net, "entering SUSPEND0 mode\n");
-+      ret = smsc75xx_enter_suspend0(dev);
-+
-+done:
-+      /*
-+       * TODO: resume() might need to handle the suspend failure
-+       * in system sleep
-+       */
-+      if (ret && PMSG_IS_AUTO(message))
-+              usbnet_resume(intf);
-+      return ret;
-+}
-+
-+static int smsc75xx_resume(struct usb_interface *intf)
-+{
-+      struct usbnet *dev = usb_get_intfdata(intf);
-+      struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
-+      u8 suspend_flags = pdata->suspend_flags;
-+      int ret;
-+      u32 val;
-+
-+      netdev_dbg(dev->net, "resume suspend_flags=0x%02x\n", suspend_flags);
-+
-+      /* do this first to ensure it's cleared even in error case */
-+      pdata->suspend_flags = 0;
-+
-+      if (suspend_flags & SUSPEND_ALLMODES) {
-+              /* Disable wakeup sources */
-+              ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading WUCSR\n");
-+                      return ret;
-+              }
-+
-+              val &= ~(WUCSR_WUEN | WUCSR_MPEN | WUCSR_PFDA_EN
-+                      | WUCSR_BCST_EN);
-+
-+              ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing WUCSR\n");
-+                      return ret;
-+              }
-+
-+              /* clear wake-up status */
-+              ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading PMT_CTL\n");
-+                      return ret;
-+              }
-+
-+              val &= ~PMT_CTL_WOL_EN;
-+              val |= PMT_CTL_WUPS;
-+
-+              ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing PMT_CTL\n");
-+                      return ret;
-+              }
-+      }
-+
-+      if (suspend_flags & SUSPEND_SUSPEND2) {
-+              netdev_info(dev->net, "resuming from SUSPEND2\n");
-+
-+              ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading PMT_CTL\n");
-+                      return ret;
-+              }
-+
-+              val |= PMT_CTL_PHY_PWRUP;
-+
-+              ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing PMT_CTL\n");
-+                      return ret;
-+              }
-+      }
-+
-+      ret = smsc75xx_wait_ready(dev, 1);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "device not ready in smsc75xx_resume\n");
-+              return ret;
-+      }
-+
-+      return usbnet_resume(intf);
-+}
-+
-+static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb,
-+                                   u32 rx_cmd_a, u32 rx_cmd_b)
-+{
-+      if (!(dev->net->features & NETIF_F_RXCSUM) ||
-+          unlikely(rx_cmd_a & RX_CMD_A_LCSM)) {
-+              skb->ip_summed = CHECKSUM_NONE;
-+      } else {
-+              skb->csum = ntohs((u16)(rx_cmd_b >> RX_CMD_B_CSUM_SHIFT));
-+              skb->ip_summed = CHECKSUM_COMPLETE;
-+      }
-+}
-+
-+static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      /* This check is no longer done by usbnet */
-+      if (skb->len < dev->net->hard_header_len)
-+              return 0;
-+
-+      while (skb->len > 0) {
-+              u32 rx_cmd_a, rx_cmd_b, align_count, size;
-+              struct sk_buff *ax_skb;
-+              unsigned char *packet;
-+
-+              memcpy(&rx_cmd_a, skb->data, sizeof(rx_cmd_a));
-+              le32_to_cpus(&rx_cmd_a);
-+              skb_pull(skb, 4);
-+
-+              memcpy(&rx_cmd_b, skb->data, sizeof(rx_cmd_b));
-+              le32_to_cpus(&rx_cmd_b);
-+              skb_pull(skb, 4 + RXW_PADDING);
-+
-+              packet = skb->data;
-+
-+              /* get the packet length */
-+              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,
-+                                "Error rx_cmd_a=0x%08x\n", rx_cmd_a);
-+                      dev->net->stats.rx_errors++;
-+                      dev->net->stats.rx_dropped++;
-+
-+                      if (rx_cmd_a & RX_CMD_A_FCS)
-+                              dev->net->stats.rx_crc_errors++;
-+                      else if (rx_cmd_a & (RX_CMD_A_LONG | RX_CMD_A_RUNT))
-+                              dev->net->stats.rx_frame_errors++;
-+              } else {
-+                      /* MAX_SINGLE_PACKET_SIZE + 4(CRC) + 2(COE) + 4(Vlan) */
-+                      if (unlikely(size > (MAX_SINGLE_PACKET_SIZE + ETH_HLEN + 12))) {
-+                              netif_dbg(dev, rx_err, dev->net,
-+                                        "size err rx_cmd_a=0x%08x\n",
-+                                        rx_cmd_a);
-+                              return 0;
-+                      }
-+
-+                      /* last frame in this batch */
-+                      if (skb->len == size) {
-+                              smsc75xx_rx_csum_offload(dev, skb, rx_cmd_a,
-+                                      rx_cmd_b);
-+
-+                              skb_trim(skb, skb->len - 4); /* remove fcs */
-+                              skb->truesize = size + sizeof(struct sk_buff);
-+
-+                              return 1;
-+                      }
-+
-+                      ax_skb = skb_clone(skb, GFP_ATOMIC);
-+                      if (unlikely(!ax_skb)) {
-+                              netdev_warn(dev->net, "Error allocating skb\n");
-+                              return 0;
-+                      }
-+
-+                      ax_skb->len = size;
-+                      ax_skb->data = packet;
-+                      skb_set_tail_pointer(ax_skb, size);
-+
-+                      smsc75xx_rx_csum_offload(dev, ax_skb, rx_cmd_a,
-+                              rx_cmd_b);
-+
-+                      skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */
-+                      ax_skb->truesize = size + sizeof(struct sk_buff);
-+
-+                      usbnet_skb_return(dev, ax_skb);
-+              }
-+
-+              skb_pull(skb, size);
-+
-+              /* padding bytes before the next frame starts */
-+              if (skb->len)
-+                      skb_pull(skb, align_count);
-+      }
-+
-+      if (unlikely(skb->len < 0)) {
-+              netdev_warn(dev->net, "invalid rx length<0 %d\n", skb->len);
-+              return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev,
-+                                       struct sk_buff *skb, gfp_t flags)
-+{
-+      u32 tx_cmd_a, tx_cmd_b;
-+
-+      if (skb_headroom(skb) < SMSC75XX_TX_OVERHEAD) {
-+              struct sk_buff *skb2 =
-+                      skb_copy_expand(skb, SMSC75XX_TX_OVERHEAD, 0, flags);
-+              dev_kfree_skb_any(skb);
-+              skb = skb2;
-+              if (!skb)
-+                      return NULL;
-+      }
-+
-+      tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN) | TX_CMD_A_FCS;
-+
-+      if (skb->ip_summed == CHECKSUM_PARTIAL)
-+              tx_cmd_a |= TX_CMD_A_IPE | TX_CMD_A_TPE;
-+
-+      if (skb_is_gso(skb)) {
-+              u16 mss = max(skb_shinfo(skb)->gso_size, TX_MSS_MIN);
-+              tx_cmd_b = (mss << TX_CMD_B_MSS_SHIFT) & TX_CMD_B_MSS;
-+
-+              tx_cmd_a |= TX_CMD_A_LSO;
-+      } else {
-+              tx_cmd_b = 0;
-+      }
-+
-+      skb_push(skb, 4);
-+      cpu_to_le32s(&tx_cmd_b);
-+      memcpy(skb->data, &tx_cmd_b, 4);
-+
-+      skb_push(skb, 4);
-+      cpu_to_le32s(&tx_cmd_a);
-+      memcpy(skb->data, &tx_cmd_a, 4);
-+
-+      return skb;
-+}
-+
-+static int smsc75xx_manage_power(struct usbnet *dev, int on)
-+{
-+      dev->intf->needs_remote_wakeup = on;
-+      return 0;
-+}
-+
-+static const struct driver_info smsc75xx_info = {
-+      .description    = "smsc75xx USB 2.0 Gigabit Ethernet",
-+      .bind           = smsc75xx_bind,
-+      .unbind         = smsc75xx_unbind,
-+      .link_reset     = smsc75xx_link_reset,
-+      .reset          = smsc75xx_reset,
-+      .rx_fixup       = smsc75xx_rx_fixup,
-+      .tx_fixup       = smsc75xx_tx_fixup,
-+      .status         = smsc75xx_status,
-+      .manage_power   = smsc75xx_manage_power,
-+      .flags          = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
-+};
-+
-+static const struct usb_device_id products[] = {
-+      {
-+              /* SMSC7500 USB Gigabit Ethernet Device */
-+              USB_DEVICE(USB_VENDOR_ID_SMSC, USB_PRODUCT_ID_LAN7500),
-+              .driver_info = (unsigned long) &smsc75xx_info,
-+      },
-+      {
-+              /* SMSC7500 USB Gigabit Ethernet Device */
-+              USB_DEVICE(USB_VENDOR_ID_SMSC, USB_PRODUCT_ID_LAN7505),
-+              .driver_info = (unsigned long) &smsc75xx_info,
-+      },
-+      { },            /* END */
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver smsc75xx_driver = {
-+      .name           = SMSC_CHIPNAME,
-+      .id_table       = products,
-+      .probe          = usbnet_probe,
-+      .suspend        = smsc75xx_suspend,
-+      .resume         = smsc75xx_resume,
-+      .reset_resume   = smsc75xx_resume,
-+      .disconnect     = usbnet_disconnect,
-+      .disable_hub_initiated_lpm = 1,
-+      .supports_autosuspend = 1,
-+};
-+
-+module_usb_driver(smsc75xx_driver);
-+
-+MODULE_AUTHOR("Nancy Lin");
-+MODULE_AUTHOR("Steve Glendinning <steve.glendinning@shawell.net>");
-+MODULE_DESCRIPTION("SMSC75XX USB 2.0 Gigabit Ethernet Devices");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/smsc75xx.h backports-4.2.6-1/drivers/net/usb/smsc75xx.h
---- backports-4.2.6-1.org/drivers/net/usb/smsc75xx.h   1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/smsc75xx.h       2016-06-28 14:35:18.008640551 +0200
-@@ -0,0 +1,421 @@
-+ /***************************************************************************
-+ *
-+ * Copyright (C) 2007-2010 SMSC
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ *
-+ *****************************************************************************/
-+
-+#ifndef _SMSC75XX_H
-+#define _SMSC75XX_H
-+
-+/* Tx command words */
-+#define TX_CMD_A_LSO                  (0x08000000)
-+#define TX_CMD_A_IPE                  (0x04000000)
-+#define TX_CMD_A_TPE                  (0x02000000)
-+#define TX_CMD_A_IVTG                 (0x01000000)
-+#define TX_CMD_A_RVTG                 (0x00800000)
-+#define TX_CMD_A_FCS                  (0x00400000)
-+#define TX_CMD_A_LEN                  (0x000FFFFF)
-+
-+#define TX_CMD_B_MSS                  (0x3FFF0000)
-+#define TX_CMD_B_MSS_SHIFT            (16)
-+#define TX_MSS_MIN                    ((u16)8)
-+#define TX_CMD_B_VTAG                 (0x0000FFFF)
-+
-+/* Rx command words */
-+#define RX_CMD_A_ICE                  (0x80000000)
-+#define RX_CMD_A_TCE                  (0x40000000)
-+#define RX_CMD_A_IPV                  (0x20000000)
-+#define RX_CMD_A_PID                  (0x18000000)
-+#define RX_CMD_A_PID_NIP              (0x00000000)
-+#define RX_CMD_A_PID_TCP              (0x08000000)
-+#define RX_CMD_A_PID_UDP              (0x10000000)
-+#define RX_CMD_A_PID_PP                       (0x18000000)
-+#define RX_CMD_A_PFF                  (0x04000000)
-+#define RX_CMD_A_BAM                  (0x02000000)
-+#define RX_CMD_A_MAM                  (0x01000000)
-+#define RX_CMD_A_FVTG                 (0x00800000)
-+#define RX_CMD_A_RED                  (0x00400000)
-+#define RX_CMD_A_RWT                  (0x00200000)
-+#define RX_CMD_A_RUNT                 (0x00100000)
-+#define RX_CMD_A_LONG                 (0x00080000)
-+#define RX_CMD_A_RXE                  (0x00040000)
-+#define RX_CMD_A_DRB                  (0x00020000)
-+#define RX_CMD_A_FCS                  (0x00010000)
-+#define RX_CMD_A_UAM                  (0x00008000)
-+#define RX_CMD_A_LCSM                 (0x00004000)
-+#define RX_CMD_A_LEN                  (0x00003FFF)
-+
-+#define RX_CMD_B_CSUM                 (0xFFFF0000)
-+#define RX_CMD_B_CSUM_SHIFT           (16)
-+#define RX_CMD_B_VTAG                 (0x0000FFFF)
-+
-+/* SCSRs */
-+#define ID_REV                                (0x0000)
-+
-+#define FPGA_REV                      (0x0004)
-+
-+#define BOND_CTL                      (0x0008)
-+
-+#define INT_STS                               (0x000C)
-+#define INT_STS_RDFO_INT              (0x00400000)
-+#define INT_STS_TXE_INT                       (0x00200000)
-+#define INT_STS_MACRTO_INT            (0x00100000)
-+#define INT_STS_TX_DIS_INT            (0x00080000)
-+#define INT_STS_RX_DIS_INT            (0x00040000)
-+#define INT_STS_PHY_INT_              (0x00020000)
-+#define INT_STS_MAC_ERR_INT           (0x00008000)
-+#define INT_STS_TDFU                  (0x00004000)
-+#define INT_STS_TDFO                  (0x00002000)
-+#define INT_STS_GPIOS                 (0x00000FFF)
-+#define INT_STS_CLEAR_ALL             (0xFFFFFFFF)
-+
-+#define HW_CFG                                (0x0010)
-+#define HW_CFG_SMDET_STS              (0x00008000)
-+#define HW_CFG_SMDET_EN                       (0x00004000)
-+#define HW_CFG_EEM                    (0x00002000)
-+#define HW_CFG_RST_PROTECT            (0x00001000)
-+#define HW_CFG_PORT_SWAP              (0x00000800)
-+#define HW_CFG_PHY_BOOST              (0x00000600)
-+#define HW_CFG_PHY_BOOST_NORMAL               (0x00000000)
-+#define HW_CFG_PHY_BOOST_4            (0x00002000)
-+#define HW_CFG_PHY_BOOST_8            (0x00004000)
-+#define HW_CFG_PHY_BOOST_12           (0x00006000)
-+#define HW_CFG_LEDB                   (0x00000100)
-+#define HW_CFG_BIR                    (0x00000080)
-+#define HW_CFG_SBP                    (0x00000040)
-+#define HW_CFG_IME                    (0x00000020)
-+#define HW_CFG_MEF                    (0x00000010)
-+#define HW_CFG_ETC                    (0x00000008)
-+#define HW_CFG_BCE                    (0x00000004)
-+#define HW_CFG_LRST                   (0x00000002)
-+#define HW_CFG_SRST                   (0x00000001)
-+
-+#define PMT_CTL                               (0x0014)
-+#define PMT_CTL_PHY_PWRUP             (0x00000400)
-+#define PMT_CTL_RES_CLR_WKP_EN                (0x00000100)
-+#define PMT_CTL_DEV_RDY                       (0x00000080)
-+#define PMT_CTL_SUS_MODE              (0x00000060)
-+#define PMT_CTL_SUS_MODE_0            (0x00000000)
-+#define PMT_CTL_SUS_MODE_1            (0x00000020)
-+#define PMT_CTL_SUS_MODE_2            (0x00000040)
-+#define PMT_CTL_SUS_MODE_3            (0x00000060)
-+#define PMT_CTL_PHY_RST                       (0x00000010)
-+#define PMT_CTL_WOL_EN                        (0x00000008)
-+#define PMT_CTL_ED_EN                 (0x00000004)
-+#define PMT_CTL_WUPS                  (0x00000003)
-+#define PMT_CTL_WUPS_NO                       (0x00000000)
-+#define PMT_CTL_WUPS_ED                       (0x00000001)
-+#define PMT_CTL_WUPS_WOL              (0x00000002)
-+#define PMT_CTL_WUPS_MULTI            (0x00000003)
-+
-+#define LED_GPIO_CFG                  (0x0018)
-+#define LED_GPIO_CFG_LED2_FUN_SEL     (0x80000000)
-+#define LED_GPIO_CFG_LED10_FUN_SEL    (0x40000000)
-+#define LED_GPIO_CFG_LEDGPIO_EN               (0x0000F000)
-+#define LED_GPIO_CFG_LEDGPIO_EN_0     (0x00001000)
-+#define LED_GPIO_CFG_LEDGPIO_EN_1     (0x00002000)
-+#define LED_GPIO_CFG_LEDGPIO_EN_2     (0x00004000)
-+#define LED_GPIO_CFG_LEDGPIO_EN_3     (0x00008000)
-+#define LED_GPIO_CFG_GPBUF            (0x00000F00)
-+#define LED_GPIO_CFG_GPBUF_0          (0x00000100)
-+#define LED_GPIO_CFG_GPBUF_1          (0x00000200)
-+#define LED_GPIO_CFG_GPBUF_2          (0x00000400)
-+#define LED_GPIO_CFG_GPBUF_3          (0x00000800)
-+#define LED_GPIO_CFG_GPDIR            (0x000000F0)
-+#define LED_GPIO_CFG_GPDIR_0          (0x00000010)
-+#define LED_GPIO_CFG_GPDIR_1          (0x00000020)
-+#define LED_GPIO_CFG_GPDIR_2          (0x00000040)
-+#define LED_GPIO_CFG_GPDIR_3          (0x00000080)
-+#define LED_GPIO_CFG_GPDATA           (0x0000000F)
-+#define LED_GPIO_CFG_GPDATA_0         (0x00000001)
-+#define LED_GPIO_CFG_GPDATA_1         (0x00000002)
-+#define LED_GPIO_CFG_GPDATA_2         (0x00000004)
-+#define LED_GPIO_CFG_GPDATA_3         (0x00000008)
-+
-+#define GPIO_CFG                      (0x001C)
-+#define GPIO_CFG_SHIFT                        (24)
-+#define GPIO_CFG_GPEN                 (0xFF000000)
-+#define GPIO_CFG_GPBUF                        (0x00FF0000)
-+#define GPIO_CFG_GPDIR                        (0x0000FF00)
-+#define GPIO_CFG_GPDATA                       (0x000000FF)
-+
-+#define GPIO_WAKE                     (0x0020)
-+#define GPIO_WAKE_PHY_LINKUP_EN               (0x80000000)
-+#define GPIO_WAKE_POL                 (0x0FFF0000)
-+#define GPIO_WAKE_POL_SHIFT           (16)
-+#define GPIO_WAKE_WK                  (0x00000FFF)
-+
-+#define DP_SEL                                (0x0024)
-+#define DP_SEL_DPRDY                  (0x80000000)
-+#define DP_SEL_RSEL                   (0x0000000F)
-+#define DP_SEL_URX                    (0x00000000)
-+#define DP_SEL_VHF                    (0x00000001)
-+#define DP_SEL_VHF_HASH_LEN           (16)
-+#define DP_SEL_VHF_VLAN_LEN           (128)
-+#define DP_SEL_LSO_HEAD                       (0x00000002)
-+#define DP_SEL_FCT_RX                 (0x00000003)
-+#define DP_SEL_FCT_TX                 (0x00000004)
-+#define DP_SEL_DESCRIPTOR             (0x00000005)
-+#define DP_SEL_WOL                    (0x00000006)
-+
-+#define DP_CMD                                (0x0028)
-+#define DP_CMD_WRITE                  (0x01)
-+#define DP_CMD_READ                   (0x00)
-+
-+#define DP_ADDR                               (0x002C)
-+
-+#define DP_DATA                               (0x0030)
-+
-+#define BURST_CAP                     (0x0034)
-+#define BURST_CAP_MASK                        (0x0000000F)
-+
-+#define INT_EP_CTL                    (0x0038)
-+#define INT_EP_CTL_INTEP_ON           (0x80000000)
-+#define INT_EP_CTL_RDFO_EN            (0x00400000)
-+#define INT_EP_CTL_TXE_EN             (0x00200000)
-+#define INT_EP_CTL_MACROTO_EN         (0x00100000)
-+#define INT_EP_CTL_TX_DIS_EN          (0x00080000)
-+#define INT_EP_CTL_RX_DIS_EN          (0x00040000)
-+#define INT_EP_CTL_PHY_EN_            (0x00020000)
-+#define INT_EP_CTL_MAC_ERR_EN         (0x00008000)
-+#define INT_EP_CTL_TDFU_EN            (0x00004000)
-+#define INT_EP_CTL_TDFO_EN            (0x00002000)
-+#define INT_EP_CTL_RX_FIFO_EN         (0x00001000)
-+#define INT_EP_CTL_GPIOX_EN           (0x00000FFF)
-+
-+#define BULK_IN_DLY                   (0x003C)
-+#define BULK_IN_DLY_MASK              (0xFFFF)
-+
-+#define E2P_CMD                               (0x0040)
-+#define E2P_CMD_BUSY                  (0x80000000)
-+#define E2P_CMD_MASK                  (0x70000000)
-+#define E2P_CMD_READ                  (0x00000000)
-+#define E2P_CMD_EWDS                  (0x10000000)
-+#define E2P_CMD_EWEN                  (0x20000000)
-+#define E2P_CMD_WRITE                 (0x30000000)
-+#define E2P_CMD_WRAL                  (0x40000000)
-+#define E2P_CMD_ERASE                 (0x50000000)
-+#define E2P_CMD_ERAL                  (0x60000000)
-+#define E2P_CMD_RELOAD                        (0x70000000)
-+#define E2P_CMD_TIMEOUT                       (0x00000400)
-+#define E2P_CMD_LOADED                        (0x00000200)
-+#define E2P_CMD_ADDR                  (0x000001FF)
-+
-+#define MAX_EEPROM_SIZE                       (512)
-+
-+#define E2P_DATA                      (0x0044)
-+#define E2P_DATA_MASK_                        (0x000000FF)
-+
-+#define RFE_CTL                               (0x0060)
-+#define RFE_CTL_TCPUDP_CKM            (0x00001000)
-+#define RFE_CTL_IP_CKM                        (0x00000800)
-+#define RFE_CTL_AB                    (0x00000400)
-+#define RFE_CTL_AM                    (0x00000200)
-+#define RFE_CTL_AU                    (0x00000100)
-+#define RFE_CTL_VS                    (0x00000080)
-+#define RFE_CTL_UF                    (0x00000040)
-+#define RFE_CTL_VF                    (0x00000020)
-+#define RFE_CTL_SPF                   (0x00000010)
-+#define RFE_CTL_MHF                   (0x00000008)
-+#define RFE_CTL_DHF                   (0x00000004)
-+#define RFE_CTL_DPF                   (0x00000002)
-+#define RFE_CTL_RST_RF                        (0x00000001)
-+
-+#define VLAN_TYPE                     (0x0064)
-+#define VLAN_TYPE_MASK                        (0x0000FFFF)
-+
-+#define FCT_RX_CTL                    (0x0090)
-+#define FCT_RX_CTL_EN                 (0x80000000)
-+#define FCT_RX_CTL_RST                        (0x40000000)
-+#define FCT_RX_CTL_SBF                        (0x02000000)
-+#define FCT_RX_CTL_OVERFLOW           (0x01000000)
-+#define FCT_RX_CTL_FRM_DROP           (0x00800000)
-+#define FCT_RX_CTL_RX_NOT_EMPTY               (0x00400000)
-+#define FCT_RX_CTL_RX_EMPTY           (0x00200000)
-+#define FCT_RX_CTL_RX_DISABLED                (0x00100000)
-+#define FCT_RX_CTL_RXUSED             (0x0000FFFF)
-+
-+#define FCT_TX_CTL                    (0x0094)
-+#define FCT_TX_CTL_EN                 (0x80000000)
-+#define FCT_TX_CTL_RST                        (0x40000000)
-+#define FCT_TX_CTL_TX_NOT_EMPTY               (0x00400000)
-+#define FCT_TX_CTL_TX_EMPTY           (0x00200000)
-+#define FCT_TX_CTL_TX_DISABLED                (0x00100000)
-+#define FCT_TX_CTL_TXUSED             (0x0000FFFF)
-+
-+#define FCT_RX_FIFO_END                       (0x0098)
-+#define FCT_RX_FIFO_END_MASK          (0x0000007F)
-+
-+#define FCT_TX_FIFO_END                       (0x009C)
-+#define FCT_TX_FIFO_END_MASK          (0x0000003F)
-+
-+#define FCT_FLOW                      (0x00A0)
-+#define FCT_FLOW_THRESHOLD_OFF                (0x00007F00)
-+#define FCT_FLOW_THRESHOLD_OFF_SHIFT  (8)
-+#define FCT_FLOW_THRESHOLD_ON         (0x0000007F)
-+
-+/* MAC CSRs */
-+#define MAC_CR                                (0x100)
-+#define MAC_CR_ADP                    (0x00002000)
-+#define MAC_CR_ADD                    (0x00001000)
-+#define MAC_CR_ASD                    (0x00000800)
-+#define MAC_CR_INT_LOOP                       (0x00000400)
-+#define MAC_CR_BOLMT                  (0x000000C0)
-+#define MAC_CR_FDPX                   (0x00000008)
-+#define MAC_CR_CFG                    (0x00000006)
-+#define MAC_CR_CFG_10                 (0x00000000)
-+#define MAC_CR_CFG_100                        (0x00000002)
-+#define MAC_CR_CFG_1000                       (0x00000004)
-+#define MAC_CR_RST                    (0x00000001)
-+
-+#define MAC_RX                                (0x104)
-+#define MAC_RX_MAX_SIZE                       (0x3FFF0000)
-+#define MAC_RX_MAX_SIZE_SHIFT         (16)
-+#define MAC_RX_FCS_STRIP              (0x00000010)
-+#define MAC_RX_FSE                    (0x00000004)
-+#define MAC_RX_RXD                    (0x00000002)
-+#define MAC_RX_RXEN                   (0x00000001)
-+
-+#define MAC_TX                                (0x108)
-+#define MAC_TX_BFCS                   (0x00000004)
-+#define MAC_TX_TXD                    (0x00000002)
-+#define MAC_TX_TXEN                   (0x00000001)
-+
-+#define FLOW                          (0x10C)
-+#define FLOW_FORCE_FC                 (0x80000000)
-+#define FLOW_TX_FCEN                  (0x40000000)
-+#define FLOW_RX_FCEN                  (0x20000000)
-+#define FLOW_FPF                      (0x10000000)
-+#define FLOW_PAUSE_TIME                       (0x0000FFFF)
-+
-+#define RAND_SEED                     (0x110)
-+#define RAND_SEED_MASK                        (0x0000FFFF)
-+
-+#define ERR_STS                               (0x114)
-+#define ERR_STS_FCS_ERR                       (0x00000100)
-+#define ERR_STS_LFRM_ERR              (0x00000080)
-+#define ERR_STS_RUNT_ERR              (0x00000040)
-+#define ERR_STS_COLLISION_ERR         (0x00000010)
-+#define ERR_STS_ALIGN_ERR             (0x00000008)
-+#define ERR_STS_URUN_ERR              (0x00000004)
-+
-+#define RX_ADDRH                      (0x118)
-+#define RX_ADDRH_MASK                 (0x0000FFFF)
-+
-+#define RX_ADDRL                      (0x11C)
-+
-+#define MII_ACCESS                    (0x120)
-+#define MII_ACCESS_PHY_ADDR           (0x0000F800)
-+#define MII_ACCESS_PHY_ADDR_SHIFT     (11)
-+#define MII_ACCESS_REG_ADDR           (0x000007C0)
-+#define MII_ACCESS_REG_ADDR_SHIFT     (6)
-+#define MII_ACCESS_READ                       (0x00000000)
-+#define MII_ACCESS_WRITE              (0x00000002)
-+#define MII_ACCESS_BUSY                       (0x00000001)
-+
-+#define MII_DATA                      (0x124)
-+#define MII_DATA_MASK                 (0x0000FFFF)
-+
-+#define WUCSR                         (0x140)
-+#define WUCSR_PFDA_FR                 (0x00000080)
-+#define WUCSR_WUFR                    (0x00000040)
-+#define WUCSR_MPR                     (0x00000020)
-+#define WUCSR_BCAST_FR                        (0x00000010)
-+#define WUCSR_PFDA_EN                 (0x00000008)
-+#define WUCSR_WUEN                    (0x00000004)
-+#define WUCSR_MPEN                    (0x00000002)
-+#define WUCSR_BCST_EN                 (0x00000001)
-+
-+#define WUF_CFGX                      (0x144)
-+#define WUF_CFGX_EN                   (0x80000000)
-+#define WUF_CFGX_ATYPE                        (0x03000000)
-+#define WUF_CFGX_ATYPE_UNICAST                (0x00000000)
-+#define WUF_CFGX_ATYPE_MULTICAST      (0x02000000)
-+#define WUF_CFGX_ATYPE_ALL            (0x03000000)
-+#define WUF_CFGX_PATTERN_OFFSET               (0x007F0000)
-+#define WUF_CFGX_PATTERN_OFFSET_SHIFT (16)
-+#define WUF_CFGX_CRC16                        (0x0000FFFF)
-+#define WUF_NUM                               (8)
-+
-+#define WUF_MASKX                     (0x170)
-+#define WUF_MASKX_AVALID              (0x80000000)
-+#define WUF_MASKX_ATYPE                       (0x40000000)
-+
-+#define ADDR_FILTX                    (0x300)
-+#define ADDR_FILTX_FB_VALID           (0x80000000)
-+#define ADDR_FILTX_FB_TYPE            (0x40000000)
-+#define ADDR_FILTX_FB_ADDRHI          (0x0000FFFF)
-+#define ADDR_FILTX_SB_ADDRLO          (0xFFFFFFFF)
-+
-+#define WUCSR2                                (0x500)
-+#define WUCSR2_NS_RCD                 (0x00000040)
-+#define WUCSR2_ARP_RCD                        (0x00000020)
-+#define WUCSR2_TCPSYN_RCD             (0x00000010)
-+#define WUCSR2_NS_OFFLOAD             (0x00000004)
-+#define WUCSR2_ARP_OFFLOAD            (0x00000002)
-+#define WUCSR2_TCPSYN_OFFLOAD         (0x00000001)
-+
-+#define WOL_FIFO_STS                  (0x504)
-+
-+#define IPV6_ADDRX                    (0x510)
-+
-+#define IPV4_ADDRX                    (0x590)
-+
-+
-+/* Vendor-specific PHY Definitions */
-+
-+/* Mode Control/Status Register */
-+#define PHY_MODE_CTRL_STS             (17)
-+#define MODE_CTRL_STS_EDPWRDOWN               ((u16)0x2000)
-+#define MODE_CTRL_STS_ENERGYON                ((u16)0x0002)
-+
-+#define PHY_INT_SRC                   (29)
-+#define PHY_INT_SRC_ENERGY_ON         ((u16)0x0080)
-+#define PHY_INT_SRC_ANEG_COMP         ((u16)0x0040)
-+#define PHY_INT_SRC_REMOTE_FAULT      ((u16)0x0020)
-+#define PHY_INT_SRC_LINK_DOWN         ((u16)0x0010)
-+#define PHY_INT_SRC_CLEAR_ALL         ((u16)0xffff)
-+
-+#define PHY_INT_MASK                  (30)
-+#define PHY_INT_MASK_ENERGY_ON                ((u16)0x0080)
-+#define PHY_INT_MASK_ANEG_COMP                ((u16)0x0040)
-+#define PHY_INT_MASK_REMOTE_FAULT     ((u16)0x0020)
-+#define PHY_INT_MASK_LINK_DOWN                ((u16)0x0010)
-+#define PHY_INT_MASK_DEFAULT          (PHY_INT_MASK_ANEG_COMP | \
-+                                       PHY_INT_MASK_LINK_DOWN)
-+
-+#define PHY_SPECIAL                   (31)
-+#define PHY_SPECIAL_SPD                       ((u16)0x001C)
-+#define PHY_SPECIAL_SPD_10HALF                ((u16)0x0004)
-+#define PHY_SPECIAL_SPD_10FULL                ((u16)0x0014)
-+#define PHY_SPECIAL_SPD_100HALF               ((u16)0x0008)
-+#define PHY_SPECIAL_SPD_100FULL               ((u16)0x0018)
-+
-+/* USB Vendor Requests */
-+#define USB_VENDOR_REQUEST_WRITE_REGISTER     0xA0
-+#define USB_VENDOR_REQUEST_READ_REGISTER      0xA1
-+#define USB_VENDOR_REQUEST_GET_STATS          0xA2
-+
-+/* Interrupt Endpoint status word bitfields */
-+#define INT_ENP_RDFO_INT              ((u32)BIT(22))
-+#define INT_ENP_TXE_INT                       ((u32)BIT(21))
-+#define INT_ENP_TX_DIS_INT            ((u32)BIT(19))
-+#define INT_ENP_RX_DIS_INT            ((u32)BIT(18))
-+#define INT_ENP_PHY_INT                       ((u32)BIT(17))
-+#define INT_ENP_MAC_ERR_INT           ((u32)BIT(15))
-+#define INT_ENP_RX_FIFO_DATA_INT      ((u32)BIT(12))
-+
-+#endif /* _SMSC75XX_H */
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/smsc95xx.c backports-4.2.6-1/drivers/net/usb/smsc95xx.c
---- backports-4.2.6-1.org/drivers/net/usb/smsc95xx.c   1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/smsc95xx.c       2016-06-28 14:35:18.011973884 +0200
-@@ -0,0 +1,2032 @@
-+ /***************************************************************************
-+ *
-+ * Copyright (C) 2007-2008 SMSC
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ *
-+ *****************************************************************************/
-+
-+#include <linux/module.h>
-+#include <linux/kmod.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/bitrev.h>
-+#include <linux/crc16.h>
-+#include <linux/crc32.h>
-+#include <linux/usb/usbnet.h>
-+#include <linux/slab.h>
-+#include "smsc95xx.h"
-+
-+#define SMSC_CHIPNAME                 "smsc95xx"
-+#define SMSC_DRIVER_VERSION           "1.0.4"
-+#define HS_USB_PKT_SIZE                       (512)
-+#define FS_USB_PKT_SIZE                       (64)
-+#define DEFAULT_HS_BURST_CAP_SIZE     (16 * 1024 + 5 * HS_USB_PKT_SIZE)
-+#define DEFAULT_FS_BURST_CAP_SIZE     (6 * 1024 + 33 * FS_USB_PKT_SIZE)
-+#define DEFAULT_BULK_IN_DELAY         (0x00002000)
-+#define MAX_SINGLE_PACKET_SIZE                (2048)
-+#define LAN95XX_EEPROM_MAGIC          (0x9500)
-+#define EEPROM_MAC_OFFSET             (0x01)
-+#define DEFAULT_TX_CSUM_ENABLE                (true)
-+#define DEFAULT_RX_CSUM_ENABLE                (true)
-+#define SMSC95XX_INTERNAL_PHY_ID      (1)
-+#define SMSC95XX_TX_OVERHEAD          (8)
-+#define SMSC95XX_TX_OVERHEAD_CSUM     (12)
-+#define SUPPORTED_WAKE                        (WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
-+                                       WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
-+
-+#define FEATURE_8_WAKEUP_FILTERS      (0x01)
-+#define FEATURE_PHY_NLP_CROSSOVER     (0x02)
-+#define FEATURE_REMOTE_WAKEUP         (0x04)
-+
-+#define SUSPEND_SUSPEND0              (0x01)
-+#define SUSPEND_SUSPEND1              (0x02)
-+#define SUSPEND_SUSPEND2              (0x04)
-+#define SUSPEND_SUSPEND3              (0x08)
-+#define SUSPEND_ALLMODES              (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
-+                                       SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
-+
-+struct smsc95xx_priv {
-+      u32 mac_cr;
-+      u32 hash_hi;
-+      u32 hash_lo;
-+      u32 wolopts;
-+      spinlock_t mac_cr_lock;
-+      u8 features;
-+      u8 suspend_flags;
-+};
-+
-+static bool turbo_mode = true;
-+module_param(turbo_mode, bool, 0644);
-+MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
-+
-+static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
-+                                          u32 *data, int in_pm)
-+{
-+      u32 buf;
-+      int ret;
-+      int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
-+
-+      BUG_ON(!dev);
-+
-+      if (!in_pm)
-+              fn = usbnet_read_cmd;
-+      else
-+              fn = usbnet_read_cmd_nopm;
-+
-+      ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
-+               | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+               0, index, &buf, 4);
-+      if (unlikely(ret < 0))
-+              netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
-+                          index, ret);
-+
-+      le32_to_cpus(&buf);
-+      *data = buf;
-+
-+      return ret;
-+}
-+
-+static int __must_check __smsc95xx_write_reg(struct usbnet *dev, u32 index,
-+                                           u32 data, int in_pm)
-+{
-+      u32 buf;
-+      int ret;
-+      int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
-+
-+      BUG_ON(!dev);
-+
-+      if (!in_pm)
-+              fn = usbnet_write_cmd;
-+      else
-+              fn = usbnet_write_cmd_nopm;
-+
-+      buf = data;
-+      cpu_to_le32s(&buf);
-+
-+      ret = fn(dev, USB_VENDOR_REQUEST_WRITE_REGISTER, USB_DIR_OUT
-+               | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-+               0, index, &buf, 4);
-+      if (unlikely(ret < 0))
-+              netdev_warn(dev->net, "Failed to write reg index 0x%08x: %d\n",
-+                          index, ret);
-+
-+      return ret;
-+}
-+
-+static int __must_check smsc95xx_read_reg_nopm(struct usbnet *dev, u32 index,
-+                                             u32 *data)
-+{
-+      return __smsc95xx_read_reg(dev, index, data, 1);
-+}
-+
-+static int __must_check smsc95xx_write_reg_nopm(struct usbnet *dev, u32 index,
-+                                              u32 data)
-+{
-+      return __smsc95xx_write_reg(dev, index, data, 1);
-+}
-+
-+static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index,
-+                                        u32 *data)
-+{
-+      return __smsc95xx_read_reg(dev, index, data, 0);
-+}
-+
-+static int __must_check smsc95xx_write_reg(struct usbnet *dev, u32 index,
-+                                         u32 data)
-+{
-+      return __smsc95xx_write_reg(dev, index, data, 0);
-+}
-+
-+/* Loop until the read is completed with timeout
-+ * called with phy_mutex held */
-+static int __must_check __smsc95xx_phy_wait_not_busy(struct usbnet *dev,
-+                                                   int in_pm)
-+{
-+      unsigned long start_time = jiffies;
-+      u32 val;
-+      int ret;
-+
-+      do {
-+              ret = __smsc95xx_read_reg(dev, MII_ADDR, &val, in_pm);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading MII_ACCESS\n");
-+                      return ret;
-+              }
-+
-+              if (!(val & MII_BUSY_))
-+                      return 0;
-+      } while (!time_after(jiffies, start_time + HZ));
-+
-+      return -EIO;
-+}
-+
-+static int __smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx,
-+                              int in_pm)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      u32 val, addr;
-+      int ret;
-+
-+      mutex_lock(&dev->phy_mutex);
-+
-+      /* confirm MII not busy */
-+      ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "MII is busy in smsc95xx_mdio_read\n");
-+              goto done;
-+      }
-+
-+      /* set the address, index & direction (read from PHY) */
-+      phy_id &= dev->mii.phy_id_mask;
-+      idx &= dev->mii.reg_num_mask;
-+      addr = (phy_id << 11) | (idx << 6) | MII_READ_ | MII_BUSY_;
-+      ret = __smsc95xx_write_reg(dev, MII_ADDR, addr, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing MII_ADDR\n");
-+              goto done;
-+      }
-+
-+      ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Timed out reading MII reg %02X\n", idx);
-+              goto done;
-+      }
-+
-+      ret = __smsc95xx_read_reg(dev, MII_DATA, &val, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error reading MII_DATA\n");
-+              goto done;
-+      }
-+
-+      ret = (u16)(val & 0xFFFF);
-+
-+done:
-+      mutex_unlock(&dev->phy_mutex);
-+      return ret;
-+}
-+
-+static void __smsc95xx_mdio_write(struct net_device *netdev, int phy_id,
-+                                int idx, int regval, int in_pm)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      u32 val, addr;
-+      int ret;
-+
-+      mutex_lock(&dev->phy_mutex);
-+
-+      /* confirm MII not busy */
-+      ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "MII is busy in smsc95xx_mdio_write\n");
-+              goto done;
-+      }
-+
-+      val = regval;
-+      ret = __smsc95xx_write_reg(dev, MII_DATA, val, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing MII_DATA\n");
-+              goto done;
-+      }
-+
-+      /* set the address, index & direction (write to PHY) */
-+      phy_id &= dev->mii.phy_id_mask;
-+      idx &= dev->mii.reg_num_mask;
-+      addr = (phy_id << 11) | (idx << 6) | MII_WRITE_ | MII_BUSY_;
-+      ret = __smsc95xx_write_reg(dev, MII_ADDR, addr, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing MII_ADDR\n");
-+              goto done;
-+      }
-+
-+      ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Timed out writing MII reg %02X\n", idx);
-+              goto done;
-+      }
-+
-+done:
-+      mutex_unlock(&dev->phy_mutex);
-+}
-+
-+static int smsc95xx_mdio_read_nopm(struct net_device *netdev, int phy_id,
-+                                 int idx)
-+{
-+      return __smsc95xx_mdio_read(netdev, phy_id, idx, 1);
-+}
-+
-+static void smsc95xx_mdio_write_nopm(struct net_device *netdev, int phy_id,
-+                                   int idx, int regval)
-+{
-+      __smsc95xx_mdio_write(netdev, phy_id, idx, regval, 1);
-+}
-+
-+static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
-+{
-+      return __smsc95xx_mdio_read(netdev, phy_id, idx, 0);
-+}
-+
-+static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
-+                              int regval)
-+{
-+      __smsc95xx_mdio_write(netdev, phy_id, idx, regval, 0);
-+}
-+
-+static int __must_check smsc95xx_wait_eeprom(struct usbnet *dev)
-+{
-+      unsigned long start_time = jiffies;
-+      u32 val;
-+      int ret;
-+
-+      do {
-+              ret = smsc95xx_read_reg(dev, E2P_CMD, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading E2P_CMD\n");
-+                      return ret;
-+              }
-+
-+              if (!(val & E2P_CMD_BUSY_) || (val & E2P_CMD_TIMEOUT_))
-+                      break;
-+              udelay(40);
-+      } while (!time_after(jiffies, start_time + HZ));
-+
-+      if (val & (E2P_CMD_TIMEOUT_ | E2P_CMD_BUSY_)) {
-+              netdev_warn(dev->net, "EEPROM read operation timeout\n");
-+              return -EIO;
-+      }
-+
-+      return 0;
-+}
-+
-+static int __must_check smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev)
-+{
-+      unsigned long start_time = jiffies;
-+      u32 val;
-+      int ret;
-+
-+      do {
-+              ret = smsc95xx_read_reg(dev, E2P_CMD, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading E2P_CMD\n");
-+                      return ret;
-+              }
-+
-+              if (!(val & E2P_CMD_BUSY_))
-+                      return 0;
-+
-+              udelay(40);
-+      } while (!time_after(jiffies, start_time + HZ));
-+
-+      netdev_warn(dev->net, "EEPROM is busy\n");
-+      return -EIO;
-+}
-+
-+static int smsc95xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
-+                              u8 *data)
-+{
-+      u32 val;
-+      int i, ret;
-+
-+      BUG_ON(!dev);
-+      BUG_ON(!data);
-+
-+      ret = smsc95xx_eeprom_confirm_not_busy(dev);
-+      if (ret)
-+              return ret;
-+
-+      for (i = 0; i < length; i++) {
-+              val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_);
-+              ret = smsc95xx_write_reg(dev, E2P_CMD, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing E2P_CMD\n");
-+                      return ret;
-+              }
-+
-+              ret = smsc95xx_wait_eeprom(dev);
-+              if (ret < 0)
-+                      return ret;
-+
-+              ret = smsc95xx_read_reg(dev, E2P_DATA, &val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error reading E2P_DATA\n");
-+                      return ret;
-+              }
-+
-+              data[i] = val & 0xFF;
-+              offset++;
-+      }
-+
-+      return 0;
-+}
-+
-+static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
-+                               u8 *data)
-+{
-+      u32 val;
-+      int i, ret;
-+
-+      BUG_ON(!dev);
-+      BUG_ON(!data);
-+
-+      ret = smsc95xx_eeprom_confirm_not_busy(dev);
-+      if (ret)
-+              return ret;
-+
-+      /* Issue write/erase enable command */
-+      val = E2P_CMD_BUSY_ | E2P_CMD_EWEN_;
-+      ret = smsc95xx_write_reg(dev, E2P_CMD, val);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Error writing E2P_DATA\n");
-+              return ret;
-+      }
-+
-+      ret = smsc95xx_wait_eeprom(dev);
-+      if (ret < 0)
-+              return ret;
-+
-+      for (i = 0; i < length; i++) {
-+
-+              /* Fill data register */
-+              val = data[i];
-+              ret = smsc95xx_write_reg(dev, E2P_DATA, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing E2P_DATA\n");
-+                      return ret;
-+              }
-+
-+              /* Send "write" command */
-+              val = E2P_CMD_BUSY_ | E2P_CMD_WRITE_ | (offset & E2P_CMD_ADDR_);
-+              ret = smsc95xx_write_reg(dev, E2P_CMD, val);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "Error writing E2P_CMD\n");
-+                      return ret;
-+              }
-+
-+              ret = smsc95xx_wait_eeprom(dev);
-+              if (ret < 0)
-+                      return ret;
-+
-+              offset++;
-+      }
-+
-+      return 0;
-+}
-+
-+static int __must_check smsc95xx_write_reg_async(struct usbnet *dev, u16 index,
-+                                               u32 data)
-+{
-+      const u16 size = 4;
-+      u32 buf;
-+      int ret;
-+
-+      buf = data;
-+      cpu_to_le32s(&buf);
-+
-+      ret = usbnet_write_cmd_async(dev, USB_VENDOR_REQUEST_WRITE_REGISTER,
-+                                   USB_DIR_OUT | USB_TYPE_VENDOR |
-+                                   USB_RECIP_DEVICE,
-+                                   0, index, &buf, size);
-+      if (ret < 0)
-+              netdev_warn(dev->net, "Error write async cmd, sts=%d\n",
-+                          ret);
-+      return ret;
-+}
-+
-+/* returns hash bit number for given MAC address
-+ * example:
-+ * 01 00 5E 00 00 01 -> returns bit number 31 */
-+static unsigned int smsc95xx_hash(char addr[ETH_ALEN])
-+{
-+      return (ether_crc(ETH_ALEN, addr) >> 26) & 0x3f;
-+}
-+
-+static void smsc95xx_set_multicast(struct net_device *netdev)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      unsigned long flags;
-+      int ret;
-+
-+      pdata->hash_hi = 0;
-+      pdata->hash_lo = 0;
-+
-+      spin_lock_irqsave(&pdata->mac_cr_lock, flags);
-+
-+      if (dev->net->flags & IFF_PROMISC) {
-+              netif_dbg(dev, drv, dev->net, "promiscuous mode enabled\n");
-+              pdata->mac_cr |= MAC_CR_PRMS_;
-+              pdata->mac_cr &= ~(MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
-+      } else if (dev->net->flags & IFF_ALLMULTI) {
-+              netif_dbg(dev, drv, dev->net, "receive all multicast enabled\n");
-+              pdata->mac_cr |= MAC_CR_MCPAS_;
-+              pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_HPFILT_);
-+      } else if (!netdev_mc_empty(dev->net)) {
-+              struct netdev_hw_addr *ha;
-+
-+              pdata->mac_cr |= MAC_CR_HPFILT_;
-+              pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_);
-+
-+              netdev_for_each_mc_addr(ha, netdev) {
-+                      u32 bitnum = smsc95xx_hash(ha->addr);
-+                      u32 mask = 0x01 << (bitnum & 0x1F);
-+                      if (bitnum & 0x20)
-+                              pdata->hash_hi |= mask;
-+                      else
-+                              pdata->hash_lo |= mask;
-+              }
-+
-+              netif_dbg(dev, drv, dev->net, "HASHH=0x%08X, HASHL=0x%08X\n",
-+                                 pdata->hash_hi, pdata->hash_lo);
-+      } else {
-+              netif_dbg(dev, drv, dev->net, "receive own packets only\n");
-+              pdata->mac_cr &=
-+                      ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
-+      }
-+
-+      spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
-+
-+      /* Initiate async writes, as we can't wait for completion here */
-+      ret = smsc95xx_write_reg_async(dev, HASHH, pdata->hash_hi);
-+      if (ret < 0)
-+              netdev_warn(dev->net, "failed to initiate async write to HASHH\n");
-+
-+      ret = smsc95xx_write_reg_async(dev, HASHL, pdata->hash_lo);
-+      if (ret < 0)
-+              netdev_warn(dev->net, "failed to initiate async write to HASHL\n");
-+
-+      ret = smsc95xx_write_reg_async(dev, MAC_CR, pdata->mac_cr);
-+      if (ret < 0)
-+              netdev_warn(dev->net, "failed to initiate async write to MAC_CR\n");
-+}
-+
-+static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
-+                                         u16 lcladv, u16 rmtadv)
-+{
-+      u32 flow, afc_cfg = 0;
-+
-+      int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg);
-+      if (ret < 0)
-+              return ret;
-+
-+      if (duplex == DUPLEX_FULL) {
-+              u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
-+
-+              if (cap & FLOW_CTRL_RX)
-+                      flow = 0xFFFF0002;
-+              else
-+                      flow = 0;
-+
-+              if (cap & FLOW_CTRL_TX)
-+                      afc_cfg |= 0xF;
-+              else
-+                      afc_cfg &= ~0xF;
-+
-+              netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s\n",
-+                                 cap & FLOW_CTRL_RX ? "enabled" : "disabled",
-+                                 cap & FLOW_CTRL_TX ? "enabled" : "disabled");
-+      } else {
-+              netif_dbg(dev, link, dev->net, "half duplex\n");
-+              flow = 0;
-+              afc_cfg |= 0xF;
-+      }
-+
-+      ret = smsc95xx_write_reg(dev, FLOW, flow);
-+      if (ret < 0)
-+              return ret;
-+
-+      return smsc95xx_write_reg(dev, AFC_CFG, afc_cfg);
-+}
-+
-+static int smsc95xx_link_reset(struct usbnet *dev)
-+{
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      struct mii_if_info *mii = &dev->mii;
-+      struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
-+      unsigned long flags;
-+      u16 lcladv, rmtadv;
-+      int ret;
-+
-+      /* clear interrupt status */
-+      ret = smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
-+      if (ret < 0)
-+              return ret;
-+
-+      mii_check_media(mii, 1, 1);
-+      mii_ethtool_gset(&dev->mii, &ecmd);
-+      lcladv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE);
-+      rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA);
-+
-+      netif_dbg(dev, link, dev->net,
-+                "speed: %u duplex: %d lcladv: %04x rmtadv: %04x\n",
-+                ethtool_cmd_speed(&ecmd), ecmd.duplex, lcladv, rmtadv);
-+
-+      spin_lock_irqsave(&pdata->mac_cr_lock, flags);
-+      if (ecmd.duplex != DUPLEX_FULL) {
-+              pdata->mac_cr &= ~MAC_CR_FDPX_;
-+              pdata->mac_cr |= MAC_CR_RCVOWN_;
-+      } else {
-+              pdata->mac_cr &= ~MAC_CR_RCVOWN_;
-+              pdata->mac_cr |= MAC_CR_FDPX_;
-+      }
-+      spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
-+
-+      ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
-+      if (ret < 0)
-+              netdev_warn(dev->net, "Error updating PHY flow control\n");
-+
-+      return ret;
-+}
-+
-+static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
-+{
-+      u32 intdata;
-+
-+      if (urb->actual_length != 4) {
-+              netdev_warn(dev->net, "unexpected urb length %d\n",
-+                          urb->actual_length);
-+              return;
-+      }
-+
-+      memcpy(&intdata, urb->transfer_buffer, 4);
-+      le32_to_cpus(&intdata);
-+
-+      netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata);
-+
-+      if (intdata & INT_ENP_PHY_INT_)
-+              usbnet_defer_kevent(dev, EVENT_LINK_RESET);
-+      else
-+              netdev_warn(dev->net, "unexpected interrupt, intdata=0x%08X\n",
-+                          intdata);
-+}
-+
-+/* Enable or disable Tx & Rx checksum offload engines */
-+static int smsc95xx_set_features(struct net_device *netdev,
-+      netdev_features_t features)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      u32 read_buf;
-+      int ret;
-+
-+      ret = smsc95xx_read_reg(dev, COE_CR, &read_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      if (features & NETIF_F_HW_CSUM)
-+              read_buf |= Tx_COE_EN_;
-+      else
-+              read_buf &= ~Tx_COE_EN_;
-+
-+      if (features & NETIF_F_RXCSUM)
-+              read_buf |= Rx_COE_EN_;
-+      else
-+              read_buf &= ~Rx_COE_EN_;
-+
-+      ret = smsc95xx_write_reg(dev, COE_CR, read_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      netif_dbg(dev, hw, dev->net, "COE_CR = 0x%08x\n", read_buf);
-+      return 0;
-+}
-+
-+static int smsc95xx_ethtool_get_eeprom_len(struct net_device *net)
-+{
-+      return MAX_EEPROM_SIZE;
-+}
-+
-+static int smsc95xx_ethtool_get_eeprom(struct net_device *netdev,
-+                                     struct ethtool_eeprom *ee, u8 *data)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+
-+      ee->magic = LAN95XX_EEPROM_MAGIC;
-+
-+      return smsc95xx_read_eeprom(dev, ee->offset, ee->len, data);
-+}
-+
-+static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev,
-+                                     struct ethtool_eeprom *ee, u8 *data)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+
-+      if (ee->magic != LAN95XX_EEPROM_MAGIC) {
-+              netdev_warn(dev->net, "EEPROM: magic value mismatch, magic = 0x%x\n",
-+                          ee->magic);
-+              return -EINVAL;
-+      }
-+
-+      return smsc95xx_write_eeprom(dev, ee->offset, ee->len, data);
-+}
-+
-+static int smsc95xx_ethtool_getregslen(struct net_device *netdev)
-+{
-+      /* all smsc95xx registers */
-+      return COE_CR - ID_REV + sizeof(u32);
-+}
-+
-+static void
-+smsc95xx_ethtool_getregs(struct net_device *netdev, struct ethtool_regs *regs,
-+                       void *buf)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      unsigned int i, j;
-+      int retval;
-+      u32 *data = buf;
-+
-+      retval = smsc95xx_read_reg(dev, ID_REV, &regs->version);
-+      if (retval < 0) {
-+              netdev_warn(netdev, "REGS: cannot read ID_REV\n");
-+              return;
-+      }
-+
-+      for (i = ID_REV, j = 0; i <= COE_CR; i += (sizeof(u32)), j++) {
-+              retval = smsc95xx_read_reg(dev, i, &data[j]);
-+              if (retval < 0) {
-+                      netdev_warn(netdev, "REGS: cannot read reg[%x]\n", i);
-+                      return;
-+              }
-+      }
-+}
-+
-+static void smsc95xx_ethtool_get_wol(struct net_device *net,
-+                                   struct ethtool_wolinfo *wolinfo)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+
-+      wolinfo->supported = SUPPORTED_WAKE;
-+      wolinfo->wolopts = pdata->wolopts;
-+}
-+
-+static int smsc95xx_ethtool_set_wol(struct net_device *net,
-+                                  struct ethtool_wolinfo *wolinfo)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      int ret;
-+
-+      pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
-+
-+      ret = device_set_wakeup_enable(&dev->udev->dev, pdata->wolopts);
-+      if (ret < 0)
-+              netdev_warn(dev->net, "device_set_wakeup_enable error %d\n", ret);
-+
-+      return ret;
-+}
-+
-+static const struct ethtool_ops smsc95xx_ethtool_ops = {
-+      .get_link       = usbnet_get_link,
-+      .nway_reset     = usbnet_nway_reset,
-+      .get_drvinfo    = usbnet_get_drvinfo,
-+      .get_msglevel   = usbnet_get_msglevel,
-+      .set_msglevel   = usbnet_set_msglevel,
-+      .get_settings   = usbnet_get_settings,
-+      .set_settings   = usbnet_set_settings,
-+      .get_eeprom_len = smsc95xx_ethtool_get_eeprom_len,
-+      .get_eeprom     = smsc95xx_ethtool_get_eeprom,
-+      .set_eeprom     = smsc95xx_ethtool_set_eeprom,
-+      .get_regs_len   = smsc95xx_ethtool_getregslen,
-+      .get_regs       = smsc95xx_ethtool_getregs,
-+      .get_wol        = smsc95xx_ethtool_get_wol,
-+      .set_wol        = smsc95xx_ethtool_set_wol,
-+};
-+
-+static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+
-+      if (!netif_running(netdev))
-+              return -EINVAL;
-+
-+      return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
-+}
-+
-+static void smsc95xx_init_mac_address(struct usbnet *dev)
-+{
-+      /* try reading mac address from EEPROM */
-+      if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
-+                      dev->net->dev_addr) == 0) {
-+              if (is_valid_ether_addr(dev->net->dev_addr)) {
-+                      /* eeprom values are valid so use them */
-+                      netif_dbg(dev, ifup, dev->net, "MAC address read from EEPROM\n");
-+                      return;
-+              }
-+      }
-+
-+      /* no eeprom, or eeprom values are invalid. generate random MAC */
-+      eth_hw_addr_random(dev->net);
-+      netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n");
-+}
-+
-+static int smsc95xx_set_mac_address(struct usbnet *dev)
-+{
-+      u32 addr_lo = dev->net->dev_addr[0] | dev->net->dev_addr[1] << 8 |
-+              dev->net->dev_addr[2] << 16 | dev->net->dev_addr[3] << 24;
-+      u32 addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8;
-+      int ret;
-+
-+      ret = smsc95xx_write_reg(dev, ADDRL, addr_lo);
-+      if (ret < 0)
-+              return ret;
-+
-+      return smsc95xx_write_reg(dev, ADDRH, addr_hi);
-+}
-+
-+/* starts the TX path */
-+static int smsc95xx_start_tx_path(struct usbnet *dev)
-+{
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      unsigned long flags;
-+      int ret;
-+
-+      /* Enable Tx at MAC */
-+      spin_lock_irqsave(&pdata->mac_cr_lock, flags);
-+      pdata->mac_cr |= MAC_CR_TXEN_;
-+      spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
-+
-+      ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* Enable Tx at SCSRs */
-+      return smsc95xx_write_reg(dev, TX_CFG, TX_CFG_ON_);
-+}
-+
-+/* Starts the Receive path */
-+static int smsc95xx_start_rx_path(struct usbnet *dev, int in_pm)
-+{
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&pdata->mac_cr_lock, flags);
-+      pdata->mac_cr |= MAC_CR_RXEN_;
-+      spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
-+
-+      return __smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr, in_pm);
-+}
-+
-+static int smsc95xx_phy_initialize(struct usbnet *dev)
-+{
-+      int bmcr, ret, timeout = 0;
-+
-+      /* Initialize MII structure */
-+      dev->mii.dev = dev->net;
-+      dev->mii.mdio_read = smsc95xx_mdio_read;
-+      dev->mii.mdio_write = smsc95xx_mdio_write;
-+      dev->mii.phy_id_mask = 0x1f;
-+      dev->mii.reg_num_mask = 0x1f;
-+      dev->mii.phy_id = SMSC95XX_INTERNAL_PHY_ID;
-+
-+      /* reset phy and wait for reset to complete */
-+      smsc95xx_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-+
-+      do {
-+              msleep(10);
-+              bmcr = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
-+              timeout++;
-+      } while ((bmcr & BMCR_RESET) && (timeout < 100));
-+
-+      if (timeout >= 100) {
-+              netdev_warn(dev->net, "timeout on PHY Reset");
-+              return -EIO;
-+      }
-+
-+      smsc95xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
-+              ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP |
-+              ADVERTISE_PAUSE_ASYM);
-+
-+      /* read to clear */
-+      ret = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to read PHY_INT_SRC during init\n");
-+              return ret;
-+      }
-+
-+      smsc95xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
-+              PHY_INT_MASK_DEFAULT_);
-+      mii_nway_restart(&dev->mii);
-+
-+      netif_dbg(dev, ifup, dev->net, "phy initialised successfully\n");
-+      return 0;
-+}
-+
-+static int smsc95xx_reset(struct usbnet *dev)
-+{
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      u32 read_buf, write_buf, burst_cap;
-+      int ret = 0, timeout;
-+
-+      netif_dbg(dev, ifup, dev->net, "entering smsc95xx_reset\n");
-+
-+      ret = smsc95xx_write_reg(dev, HW_CFG, HW_CFG_LRST_);
-+      if (ret < 0)
-+              return ret;
-+
-+      timeout = 0;
-+      do {
-+              msleep(10);
-+              ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
-+              if (ret < 0)
-+                      return ret;
-+              timeout++;
-+      } while ((read_buf & HW_CFG_LRST_) && (timeout < 100));
-+
-+      if (timeout >= 100) {
-+              netdev_warn(dev->net, "timeout waiting for completion of Lite Reset\n");
-+              return ret;
-+      }
-+
-+      ret = smsc95xx_write_reg(dev, PM_CTRL, PM_CTL_PHY_RST_);
-+      if (ret < 0)
-+              return ret;
-+
-+      timeout = 0;
-+      do {
-+              msleep(10);
-+              ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf);
-+              if (ret < 0)
-+                      return ret;
-+              timeout++;
-+      } while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100));
-+
-+      if (timeout >= 100) {
-+              netdev_warn(dev->net, "timeout waiting for PHY Reset\n");
-+              return ret;
-+      }
-+
-+      ret = smsc95xx_set_mac_address(dev);
-+      if (ret < 0)
-+              return ret;
-+
-+      netif_dbg(dev, ifup, dev->net, "MAC Address: %pM\n",
-+                dev->net->dev_addr);
-+
-+      ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x\n",
-+                read_buf);
-+
-+      read_buf |= HW_CFG_BIR_;
-+
-+      ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      netif_dbg(dev, ifup, dev->net,
-+                "Read Value from HW_CFG after writing HW_CFG_BIR_: 0x%08x\n",
-+                read_buf);
-+
-+      if (!turbo_mode) {
-+              burst_cap = 0;
-+              dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE;
-+      } else if (dev->udev->speed == USB_SPEED_HIGH) {
-+              burst_cap = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE;
-+              dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE;
-+      } else {
-+              burst_cap = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE;
-+              dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n",
-+                (ulong)dev->rx_urb_size);
-+
-+      ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      netif_dbg(dev, ifup, dev->net,
-+                "Read Value from BURST_CAP after writing: 0x%08x\n",
-+                read_buf);
-+
-+      ret = smsc95xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      netif_dbg(dev, ifup, dev->net,
-+                "Read Value from BULK_IN_DLY after writing: 0x%08x\n",
-+                read_buf);
-+
-+      ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG: 0x%08x\n",
-+                read_buf);
-+
-+      if (turbo_mode)
-+              read_buf |= (HW_CFG_MEF_ | HW_CFG_BCE_);
-+
-+      read_buf &= ~HW_CFG_RXDOFF_;
-+
-+      /* set Rx data offset=2, Make IP header aligns on word boundary. */
-+      read_buf |= NET_IP_ALIGN << 9;
-+
-+      ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      netif_dbg(dev, ifup, dev->net,
-+                "Read Value from HW_CFG after writing: 0x%08x\n", read_buf);
-+
-+      ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = smsc95xx_read_reg(dev, ID_REV, &read_buf);
-+      if (ret < 0)
-+              return ret;
-+      netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", read_buf);
-+
-+      /* Configure GPIO pins as LED outputs */
-+      write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED |
-+              LED_GPIO_CFG_FDX_LED;
-+      ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* Init Tx */
-+      ret = smsc95xx_write_reg(dev, FLOW, 0);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = smsc95xx_write_reg(dev, AFC_CFG, AFC_CFG_DEFAULT);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* Don't need mac_cr_lock during initialisation */
-+      ret = smsc95xx_read_reg(dev, MAC_CR, &pdata->mac_cr);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* Init Rx */
-+      /* Set Vlan */
-+      ret = smsc95xx_write_reg(dev, VLAN1, (u32)ETH_P_8021Q);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* Enable or disable checksum offload engines */
-+      ret = smsc95xx_set_features(dev->net, dev->net->features);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to set checksum offload features\n");
-+              return ret;
-+      }
-+
-+      smsc95xx_set_multicast(dev->net);
-+
-+      ret = smsc95xx_phy_initialize(dev);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to init PHY\n");
-+              return ret;
-+      }
-+
-+      ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* enable PHY interrupts */
-+      read_buf |= INT_EP_CTL_PHY_INT_;
-+
-+      ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = smsc95xx_start_tx_path(dev);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to start TX path\n");
-+              return ret;
-+      }
-+
-+      ret = smsc95xx_start_rx_path(dev, 0);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "Failed to start RX path\n");
-+              return ret;
-+      }
-+
-+      netif_dbg(dev, ifup, dev->net, "smsc95xx_reset, return 0\n");
-+      return 0;
-+}
-+
-+static const struct net_device_ops smsc95xx_netdev_ops = {
-+      .ndo_open               = usbnet_open,
-+      .ndo_stop               = usbnet_stop,
-+      .ndo_start_xmit         = usbnet_start_xmit,
-+      .ndo_tx_timeout         = usbnet_tx_timeout,
-+      .ndo_change_mtu         = usbnet_change_mtu,
-+      .ndo_set_mac_address    = eth_mac_addr,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_do_ioctl           = smsc95xx_ioctl,
-+      .ndo_set_rx_mode        = smsc95xx_set_multicast,
-+      .ndo_set_features       = smsc95xx_set_features,
-+};
-+
-+static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      struct smsc95xx_priv *pdata = NULL;
-+      u32 val;
-+      int ret;
-+
-+      printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
-+
-+      ret = usbnet_get_endpoints(dev, intf);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "usbnet_get_endpoints failed: %d\n", ret);
-+              return ret;
-+      }
-+
-+      dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc95xx_priv),
-+                                            GFP_KERNEL);
-+
-+      pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      if (!pdata)
-+              return -ENOMEM;
-+
-+      spin_lock_init(&pdata->mac_cr_lock);
-+
-+      if (DEFAULT_TX_CSUM_ENABLE)
-+              dev->net->features |= NETIF_F_HW_CSUM;
-+      if (DEFAULT_RX_CSUM_ENABLE)
-+              dev->net->features |= NETIF_F_RXCSUM;
-+
-+      dev->net->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
-+
-+      smsc95xx_init_mac_address(dev);
-+
-+      /* Init all registers */
-+      ret = smsc95xx_reset(dev);
-+
-+      /* detect device revision as different features may be available */
-+      ret = smsc95xx_read_reg(dev, ID_REV, &val);
-+      if (ret < 0)
-+              return ret;
-+      val >>= 16;
-+
-+      if ((val == ID_REV_CHIP_ID_9500A_) || (val == ID_REV_CHIP_ID_9530_) ||
-+          (val == ID_REV_CHIP_ID_89530_) || (val == ID_REV_CHIP_ID_9730_))
-+              pdata->features = (FEATURE_8_WAKEUP_FILTERS |
-+                      FEATURE_PHY_NLP_CROSSOVER |
-+                      FEATURE_REMOTE_WAKEUP);
-+      else if (val == ID_REV_CHIP_ID_9512_)
-+              pdata->features = FEATURE_8_WAKEUP_FILTERS;
-+
-+      dev->net->netdev_ops = &smsc95xx_netdev_ops;
-+      dev->net->ethtool_ops = &smsc95xx_ethtool_ops;
-+      dev->net->flags |= IFF_MULTICAST;
-+      dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM;
-+      dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
-+      return 0;
-+}
-+
-+static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      if (pdata) {
-+              netif_dbg(dev, ifdown, dev->net, "free pdata\n");
-+              kfree(pdata);
-+              pdata = NULL;
-+              dev->data[0] = 0;
-+      }
-+}
-+
-+static u32 smsc_crc(const u8 *buffer, size_t len, int filter)
-+{
-+      u32 crc = bitrev16(crc16(0xFFFF, buffer, len));
-+      return crc << ((filter % 2) * 16);
-+}
-+
-+static int smsc95xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
-+{
-+      struct mii_if_info *mii = &dev->mii;
-+      int ret;
-+
-+      netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n");
-+
-+      /* read to clear */
-+      ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_SRC);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* enable interrupt source */
-+      ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_MASK);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret |= mask;
-+
-+      smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_INT_MASK, ret);
-+
-+      return 0;
-+}
-+
-+static int smsc95xx_link_ok_nopm(struct usbnet *dev)
-+{
-+      struct mii_if_info *mii = &dev->mii;
-+      int ret;
-+
-+      /* first, a dummy read, needed to latch some MII phys */
-+      ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
-+      if (ret < 0)
-+              return ret;
-+
-+      return !!(ret & BMSR_LSTATUS);
-+}
-+
-+static int smsc95xx_enter_suspend0(struct usbnet *dev)
-+{
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      u32 val;
-+      int ret;
-+
-+      ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
-+      if (ret < 0)
-+              return ret;
-+
-+      val &= (~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_));
-+      val |= PM_CTL_SUS_MODE_0;
-+
-+      ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* clear wol status */
-+      val &= ~PM_CTL_WUPS_;
-+      val |= PM_CTL_WUPS_WOL_;
-+
-+      /* enable energy detection */
-+      if (pdata->wolopts & WAKE_PHY)
-+              val |= PM_CTL_WUPS_ED_;
-+
-+      ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* read back PM_CTRL */
-+      ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
-+      if (ret < 0)
-+              return ret;
-+
-+      pdata->suspend_flags |= SUSPEND_SUSPEND0;
-+
-+      return 0;
-+}
-+
-+static int smsc95xx_enter_suspend1(struct usbnet *dev)
-+{
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      struct mii_if_info *mii = &dev->mii;
-+      u32 val;
-+      int ret;
-+
-+      /* reconfigure link pulse detection timing for
-+       * compatibility with non-standard link partners
-+       */
-+      if (pdata->features & FEATURE_PHY_NLP_CROSSOVER)
-+              smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_EDPD_CONFIG,
-+                      PHY_EDPD_CONFIG_DEFAULT);
-+
-+      /* enable energy detect power-down mode */
-+      ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_MODE_CTRL_STS);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret |= MODE_CTRL_STS_EDPWRDOWN_;
-+
-+      smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_MODE_CTRL_STS, ret);
-+
-+      /* enter SUSPEND1 mode */
-+      ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
-+      if (ret < 0)
-+              return ret;
-+
-+      val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
-+      val |= PM_CTL_SUS_MODE_1;
-+
-+      ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* clear wol status, enable energy detection */
-+      val &= ~PM_CTL_WUPS_;
-+      val |= (PM_CTL_WUPS_ED_ | PM_CTL_ED_EN_);
-+
-+      ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
-+      if (ret < 0)
-+              return ret;
-+
-+      pdata->suspend_flags |= SUSPEND_SUSPEND1;
-+
-+      return 0;
-+}
-+
-+static int smsc95xx_enter_suspend2(struct usbnet *dev)
-+{
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      u32 val;
-+      int ret;
-+
-+      ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
-+      if (ret < 0)
-+              return ret;
-+
-+      val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
-+      val |= PM_CTL_SUS_MODE_2;
-+
-+      ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
-+      if (ret < 0)
-+              return ret;
-+
-+      pdata->suspend_flags |= SUSPEND_SUSPEND2;
-+
-+      return 0;
-+}
-+
-+static int smsc95xx_enter_suspend3(struct usbnet *dev)
-+{
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      u32 val;
-+      int ret;
-+
-+      ret = smsc95xx_read_reg_nopm(dev, RX_FIFO_INF, &val);
-+      if (ret < 0)
-+              return ret;
-+
-+      if (val & 0xFFFF) {
-+              netdev_info(dev->net, "rx fifo not empty in autosuspend\n");
-+              return -EBUSY;
-+      }
-+
-+      ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
-+      if (ret < 0)
-+              return ret;
-+
-+      val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
-+      val |= PM_CTL_SUS_MODE_3 | PM_CTL_RES_CLR_WKP_STS;
-+
-+      ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* clear wol status */
-+      val &= ~PM_CTL_WUPS_;
-+      val |= PM_CTL_WUPS_WOL_;
-+
-+      ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
-+      if (ret < 0)
-+              return ret;
-+
-+      pdata->suspend_flags |= SUSPEND_SUSPEND3;
-+
-+      return 0;
-+}
-+
-+static int smsc95xx_autosuspend(struct usbnet *dev, u32 link_up)
-+{
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      int ret;
-+
-+      if (!netif_running(dev->net)) {
-+              /* interface is ifconfig down so fully power down hw */
-+              netdev_dbg(dev->net, "autosuspend entering SUSPEND2\n");
-+              return smsc95xx_enter_suspend2(dev);
-+      }
-+
-+      if (!link_up) {
-+              /* link is down so enter EDPD mode, but only if device can
-+               * reliably resume from it.  This check should be redundant
-+               * as current FEATURE_REMOTE_WAKEUP parts also support
-+               * FEATURE_PHY_NLP_CROSSOVER but it's included for clarity */
-+              if (!(pdata->features & FEATURE_PHY_NLP_CROSSOVER)) {
-+                      netdev_warn(dev->net, "EDPD not supported\n");
-+                      return -EBUSY;
-+              }
-+
-+              netdev_dbg(dev->net, "autosuspend entering SUSPEND1\n");
-+
-+              /* enable PHY wakeup events for if cable is attached */
-+              ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
-+                      PHY_INT_MASK_ANEG_COMP_);
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
-+                      return ret;
-+              }
-+
-+              netdev_info(dev->net, "entering SUSPEND1 mode\n");
-+              return smsc95xx_enter_suspend1(dev);
-+      }
-+
-+      /* enable PHY wakeup events so we remote wakeup if cable is pulled */
-+      ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
-+              PHY_INT_MASK_LINK_DOWN_);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
-+              return ret;
-+      }
-+
-+      netdev_dbg(dev->net, "autosuspend entering SUSPEND3\n");
-+      return smsc95xx_enter_suspend3(dev);
-+}
-+
-+static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
-+{
-+      struct usbnet *dev = usb_get_intfdata(intf);
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      u32 val, link_up;
-+      int ret;
-+
-+      ret = usbnet_suspend(intf, message);
-+      if (ret < 0) {
-+              netdev_warn(dev->net, "usbnet_suspend error\n");
-+              return ret;
-+      }
-+
-+      if (pdata->suspend_flags) {
-+              netdev_warn(dev->net, "error during last resume\n");
-+              pdata->suspend_flags = 0;
-+      }
-+
-+      /* determine if link is up using only _nopm functions */
-+      link_up = smsc95xx_link_ok_nopm(dev);
-+
-+      if (message.event == PM_EVENT_AUTO_SUSPEND &&
-+          (pdata->features & FEATURE_REMOTE_WAKEUP)) {
-+              ret = smsc95xx_autosuspend(dev, link_up);
-+              goto done;
-+      }
-+
-+      /* if we get this far we're not autosuspending */
-+      /* if no wol options set, or if link is down and we're not waking on
-+       * PHY activity, enter lowest power SUSPEND2 mode
-+       */
-+      if (!(pdata->wolopts & SUPPORTED_WAKE) ||
-+              !(link_up || (pdata->wolopts & WAKE_PHY))) {
-+              netdev_info(dev->net, "entering SUSPEND2 mode\n");
-+
-+              /* disable energy detect (link up) & wake up events */
-+              ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
-+              if (ret < 0)
-+                      goto done;
-+
-+              val &= ~(WUCSR_MPEN_ | WUCSR_WAKE_EN_);
-+
-+              ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
-+              if (ret < 0)
-+                      goto done;
-+
-+              ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
-+              if (ret < 0)
-+                      goto done;
-+
-+              val &= ~(PM_CTL_ED_EN_ | PM_CTL_WOL_EN_);
-+
-+              ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
-+              if (ret < 0)
-+                      goto done;
-+
-+              ret = smsc95xx_enter_suspend2(dev);
-+              goto done;
-+      }
-+
-+      if (pdata->wolopts & WAKE_PHY) {
-+              ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
-+                      (PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_LINK_DOWN_));
-+              if (ret < 0) {
-+                      netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
-+                      goto done;
-+              }
-+
-+              /* if link is down then configure EDPD and enter SUSPEND1,
-+               * otherwise enter SUSPEND0 below
-+               */
-+              if (!link_up) {
-+                      netdev_info(dev->net, "entering SUSPEND1 mode\n");
-+                      ret = smsc95xx_enter_suspend1(dev);
-+                      goto done;
-+              }
-+      }
-+
-+      if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
-+              u32 *filter_mask = kzalloc(sizeof(u32) * 32, GFP_KERNEL);
-+              u32 command[2];
-+              u32 offset[2];
-+              u32 crc[4];
-+              int wuff_filter_count =
-+                      (pdata->features & FEATURE_8_WAKEUP_FILTERS) ?
-+                      LAN9500A_WUFF_NUM : LAN9500_WUFF_NUM;
-+              int i, filter = 0;
-+
-+              if (!filter_mask) {
-+                      netdev_warn(dev->net, "Unable to allocate filter_mask\n");
-+                      ret = -ENOMEM;
-+                      goto done;
-+              }
-+
-+              memset(command, 0, sizeof(command));
-+              memset(offset, 0, sizeof(offset));
-+              memset(crc, 0, sizeof(crc));
-+
-+              if (pdata->wolopts & WAKE_BCAST) {
-+                      const u8 bcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-+                      netdev_info(dev->net, "enabling broadcast detection\n");
-+                      filter_mask[filter * 4] = 0x003F;
-+                      filter_mask[filter * 4 + 1] = 0x00;
-+                      filter_mask[filter * 4 + 2] = 0x00;
-+                      filter_mask[filter * 4 + 3] = 0x00;
-+                      command[filter/4] |= 0x05UL << ((filter % 4) * 8);
-+                      offset[filter/4] |= 0x00 << ((filter % 4) * 8);
-+                      crc[filter/2] |= smsc_crc(bcast, 6, filter);
-+                      filter++;
-+              }
-+
-+              if (pdata->wolopts & WAKE_MCAST) {
-+                      const u8 mcast[] = {0x01, 0x00, 0x5E};
-+                      netdev_info(dev->net, "enabling multicast detection\n");
-+                      filter_mask[filter * 4] = 0x0007;
-+                      filter_mask[filter * 4 + 1] = 0x00;
-+                      filter_mask[filter * 4 + 2] = 0x00;
-+                      filter_mask[filter * 4 + 3] = 0x00;
-+                      command[filter/4] |= 0x09UL << ((filter % 4) * 8);
-+                      offset[filter/4] |= 0x00  << ((filter % 4) * 8);
-+                      crc[filter/2] |= smsc_crc(mcast, 3, filter);
-+                      filter++;
-+              }
-+
-+              if (pdata->wolopts & WAKE_ARP) {
-+                      const u8 arp[] = {0x08, 0x06};
-+                      netdev_info(dev->net, "enabling ARP detection\n");
-+                      filter_mask[filter * 4] = 0x0003;
-+                      filter_mask[filter * 4 + 1] = 0x00;
-+                      filter_mask[filter * 4 + 2] = 0x00;
-+                      filter_mask[filter * 4 + 3] = 0x00;
-+                      command[filter/4] |= 0x05UL << ((filter % 4) * 8);
-+                      offset[filter/4] |= 0x0C << ((filter % 4) * 8);
-+                      crc[filter/2] |= smsc_crc(arp, 2, filter);
-+                      filter++;
-+              }
-+
-+              if (pdata->wolopts & WAKE_UCAST) {
-+                      netdev_info(dev->net, "enabling unicast detection\n");
-+                      filter_mask[filter * 4] = 0x003F;
-+                      filter_mask[filter * 4 + 1] = 0x00;
-+                      filter_mask[filter * 4 + 2] = 0x00;
-+                      filter_mask[filter * 4 + 3] = 0x00;
-+                      command[filter/4] |= 0x01UL << ((filter % 4) * 8);
-+                      offset[filter/4] |= 0x00 << ((filter % 4) * 8);
-+                      crc[filter/2] |= smsc_crc(dev->net->dev_addr, ETH_ALEN, filter);
-+                      filter++;
-+              }
-+
-+              for (i = 0; i < (wuff_filter_count * 4); i++) {
-+                      ret = smsc95xx_write_reg_nopm(dev, WUFF, filter_mask[i]);
-+                      if (ret < 0) {
-+                              kfree(filter_mask);
-+                              goto done;
-+                      }
-+              }
-+              kfree(filter_mask);
-+
-+              for (i = 0; i < (wuff_filter_count / 4); i++) {
-+                      ret = smsc95xx_write_reg_nopm(dev, WUFF, command[i]);
-+                      if (ret < 0)
-+                              goto done;
-+              }
-+
-+              for (i = 0; i < (wuff_filter_count / 4); i++) {
-+                      ret = smsc95xx_write_reg_nopm(dev, WUFF, offset[i]);
-+                      if (ret < 0)
-+                              goto done;
-+              }
-+
-+              for (i = 0; i < (wuff_filter_count / 2); i++) {
-+                      ret = smsc95xx_write_reg_nopm(dev, WUFF, crc[i]);
-+                      if (ret < 0)
-+                              goto done;
-+              }
-+
-+              /* clear any pending pattern match packet status */
-+              ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
-+              if (ret < 0)
-+                      goto done;
-+
-+              val |= WUCSR_WUFR_;
-+
-+              ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
-+              if (ret < 0)
-+                      goto done;
-+      }
-+
-+      if (pdata->wolopts & WAKE_MAGIC) {
-+              /* clear any pending magic packet status */
-+              ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
-+              if (ret < 0)
-+                      goto done;
-+
-+              val |= WUCSR_MPR_;
-+
-+              ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
-+              if (ret < 0)
-+                      goto done;
-+      }
-+
-+      /* enable/disable wakeup sources */
-+      ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
-+      if (ret < 0)
-+              goto done;
-+
-+      if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
-+              netdev_info(dev->net, "enabling pattern match wakeup\n");
-+              val |= WUCSR_WAKE_EN_;
-+      } else {
-+              netdev_info(dev->net, "disabling pattern match wakeup\n");
-+              val &= ~WUCSR_WAKE_EN_;
-+      }
-+
-+      if (pdata->wolopts & WAKE_MAGIC) {
-+              netdev_info(dev->net, "enabling magic packet wakeup\n");
-+              val |= WUCSR_MPEN_;
-+      } else {
-+              netdev_info(dev->net, "disabling magic packet wakeup\n");
-+              val &= ~WUCSR_MPEN_;
-+      }
-+
-+      ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
-+      if (ret < 0)
-+              goto done;
-+
-+      /* enable wol wakeup source */
-+      ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
-+      if (ret < 0)
-+              goto done;
-+
-+      val |= PM_CTL_WOL_EN_;
-+
-+      /* phy energy detect wakeup source */
-+      if (pdata->wolopts & WAKE_PHY)
-+              val |= PM_CTL_ED_EN_;
-+
-+      ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
-+      if (ret < 0)
-+              goto done;
-+
-+      /* enable receiver to enable frame reception */
-+      smsc95xx_start_rx_path(dev, 1);
-+
-+      /* some wol options are enabled, so enter SUSPEND0 */
-+      netdev_info(dev->net, "entering SUSPEND0 mode\n");
-+      ret = smsc95xx_enter_suspend0(dev);
-+
-+done:
-+      /*
-+       * TODO: resume() might need to handle the suspend failure
-+       * in system sleep
-+       */
-+      if (ret && PMSG_IS_AUTO(message))
-+              usbnet_resume(intf);
-+      return ret;
-+}
-+
-+static int smsc95xx_resume(struct usb_interface *intf)
-+{
-+      struct usbnet *dev = usb_get_intfdata(intf);
-+      struct smsc95xx_priv *pdata;
-+      u8 suspend_flags;
-+      int ret;
-+      u32 val;
-+
-+      BUG_ON(!dev);
-+      pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+      suspend_flags = pdata->suspend_flags;
-+
-+      netdev_dbg(dev->net, "resume suspend_flags=0x%02x\n", suspend_flags);
-+
-+      /* do this first to ensure it's cleared even in error case */
-+      pdata->suspend_flags = 0;
-+
-+      if (suspend_flags & SUSPEND_ALLMODES) {
-+              /* clear wake-up sources */
-+              ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
-+              if (ret < 0)
-+                      return ret;
-+
-+              val &= ~(WUCSR_WAKE_EN_ | WUCSR_MPEN_);
-+
-+              ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
-+              if (ret < 0)
-+                      return ret;
-+
-+              /* clear wake-up status */
-+              ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
-+              if (ret < 0)
-+                      return ret;
-+
-+              val &= ~PM_CTL_WOL_EN_;
-+              val |= PM_CTL_WUPS_;
-+
-+              ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
-+              if (ret < 0)
-+                      return ret;
-+      }
-+
-+      ret = usbnet_resume(intf);
-+      if (ret < 0)
-+              netdev_warn(dev->net, "usbnet_resume error\n");
-+
-+      return ret;
-+}
-+
-+static int smsc95xx_reset_resume(struct usb_interface *intf)
-+{
-+      struct usbnet *dev = usb_get_intfdata(intf);
-+      int ret;
-+
-+      ret = smsc95xx_reset(dev);
-+      if (ret < 0)
-+              return ret;
-+
-+      return smsc95xx_resume(intf);
-+}
-+
-+static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
-+{
-+      skb->csum = *(u16 *)(skb_tail_pointer(skb) - 2);
-+      skb->ip_summed = CHECKSUM_COMPLETE;
-+      skb_trim(skb, skb->len - 2);
-+}
-+
-+static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      /* This check is no longer done by usbnet */
-+      if (skb->len < dev->net->hard_header_len)
-+              return 0;
-+
-+      while (skb->len > 0) {
-+              u32 header, align_count;
-+              struct sk_buff *ax_skb;
-+              unsigned char *packet;
-+              u16 size;
-+
-+              memcpy(&header, skb->data, sizeof(header));
-+              le32_to_cpus(&header);
-+              skb_pull(skb, 4 + NET_IP_ALIGN);
-+              packet = skb->data;
-+
-+              /* get the packet length */
-+              size = (u16)((header & RX_STS_FL_) >> 16);
-+              align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4;
-+
-+              if (unlikely(header & RX_STS_ES_)) {
-+                      netif_dbg(dev, rx_err, dev->net,
-+                                "Error header=0x%08x\n", header);
-+                      dev->net->stats.rx_errors++;
-+                      dev->net->stats.rx_dropped++;
-+
-+                      if (header & RX_STS_CRC_) {
-+                              dev->net->stats.rx_crc_errors++;
-+                      } else {
-+                              if (header & (RX_STS_TL_ | RX_STS_RF_))
-+                                      dev->net->stats.rx_frame_errors++;
-+
-+                              if ((header & RX_STS_LE_) &&
-+                                      (!(header & RX_STS_FT_)))
-+                                      dev->net->stats.rx_length_errors++;
-+                      }
-+              } else {
-+                      /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
-+                      if (unlikely(size > (ETH_FRAME_LEN + 12))) {
-+                              netif_dbg(dev, rx_err, dev->net,
-+                                        "size err header=0x%08x\n", header);
-+                              return 0;
-+                      }
-+
-+                      /* last frame in this batch */
-+                      if (skb->len == size) {
-+                              if (dev->net->features & NETIF_F_RXCSUM)
-+                                      smsc95xx_rx_csum_offload(skb);
-+                              skb_trim(skb, skb->len - 4); /* remove fcs */
-+                              skb->truesize = size + sizeof(struct sk_buff);
-+
-+                              return 1;
-+                      }
-+
-+                      ax_skb = skb_clone(skb, GFP_ATOMIC);
-+                      if (unlikely(!ax_skb)) {
-+                              netdev_warn(dev->net, "Error allocating skb\n");
-+                              return 0;
-+                      }
-+
-+                      ax_skb->len = size;
-+                      ax_skb->data = packet;
-+                      skb_set_tail_pointer(ax_skb, size);
-+
-+                      if (dev->net->features & NETIF_F_RXCSUM)
-+                              smsc95xx_rx_csum_offload(ax_skb);
-+                      skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */
-+                      ax_skb->truesize = size + sizeof(struct sk_buff);
-+
-+                      usbnet_skb_return(dev, ax_skb);
-+              }
-+
-+              skb_pull(skb, size);
-+
-+              /* padding bytes before the next frame starts */
-+              if (skb->len)
-+                      skb_pull(skb, align_count);
-+      }
-+
-+      if (unlikely(skb->len < 0)) {
-+              netdev_warn(dev->net, "invalid rx length<0 %d\n", skb->len);
-+              return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+static u32 smsc95xx_calc_csum_preamble(struct sk_buff *skb)
-+{
-+      u16 low_16 = (u16)skb_checksum_start_offset(skb);
-+      u16 high_16 = low_16 + skb->csum_offset;
-+      return (high_16 << 16) | low_16;
-+}
-+
-+static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
-+                                       struct sk_buff *skb, gfp_t flags)
-+{
-+      bool csum = skb->ip_summed == CHECKSUM_PARTIAL;
-+      int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD;
-+      u32 tx_cmd_a, tx_cmd_b;
-+
-+      /* We do not advertise SG, so skbs should be already linearized */
-+      BUG_ON(skb_shinfo(skb)->nr_frags);
-+
-+      if (skb_headroom(skb) < overhead) {
-+              struct sk_buff *skb2 = skb_copy_expand(skb,
-+                      overhead, 0, flags);
-+              dev_kfree_skb_any(skb);
-+              skb = skb2;
-+              if (!skb)
-+                      return NULL;
-+      }
-+
-+      if (csum) {
-+              if (skb->len <= 45) {
-+                      /* workaround - hardware tx checksum does not work
-+                       * properly with extremely small packets */
-+                      long csstart = skb_checksum_start_offset(skb);
-+                      __wsum calc = csum_partial(skb->data + csstart,
-+                              skb->len - csstart, 0);
-+                      *((__sum16 *)(skb->data + csstart
-+                              + skb->csum_offset)) = csum_fold(calc);
-+
-+                      csum = false;
-+              } else {
-+                      u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
-+                      skb_push(skb, 4);
-+                      cpu_to_le32s(&csum_preamble);
-+                      memcpy(skb->data, &csum_preamble, 4);
-+              }
-+      }
-+
-+      skb_push(skb, 4);
-+      tx_cmd_b = (u32)(skb->len - 4);
-+      if (csum)
-+              tx_cmd_b |= TX_CMD_B_CSUM_ENABLE;
-+      cpu_to_le32s(&tx_cmd_b);
-+      memcpy(skb->data, &tx_cmd_b, 4);
-+
-+      skb_push(skb, 4);
-+      tx_cmd_a = (u32)(skb->len - 8) | TX_CMD_A_FIRST_SEG_ |
-+              TX_CMD_A_LAST_SEG_;
-+      cpu_to_le32s(&tx_cmd_a);
-+      memcpy(skb->data, &tx_cmd_a, 4);
-+
-+      return skb;
-+}
-+
-+static int smsc95xx_manage_power(struct usbnet *dev, int on)
-+{
-+      struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-+
-+      dev->intf->needs_remote_wakeup = on;
-+
-+      if (pdata->features & FEATURE_REMOTE_WAKEUP)
-+              return 0;
-+
-+      /* this chip revision isn't capable of remote wakeup */
-+      netdev_info(dev->net, "hardware isn't capable of remote wakeup\n");
-+
-+      if (on)
-+              usb_autopm_get_interface_no_resume(dev->intf);
-+      else
-+              usb_autopm_put_interface(dev->intf);
-+
-+      return 0;
-+}
-+
-+static const struct driver_info smsc95xx_info = {
-+      .description    = "smsc95xx USB 2.0 Ethernet",
-+      .bind           = smsc95xx_bind,
-+      .unbind         = smsc95xx_unbind,
-+      .link_reset     = smsc95xx_link_reset,
-+      .reset          = smsc95xx_reset,
-+      .rx_fixup       = smsc95xx_rx_fixup,
-+      .tx_fixup       = smsc95xx_tx_fixup,
-+      .status         = smsc95xx_status,
-+      .manage_power   = smsc95xx_manage_power,
-+      .flags          = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
-+};
-+
-+static const struct usb_device_id products[] = {
-+      {
-+              /* SMSC9500 USB Ethernet Device */
-+              USB_DEVICE(0x0424, 0x9500),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9505 USB Ethernet Device */
-+              USB_DEVICE(0x0424, 0x9505),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9500A USB Ethernet Device */
-+              USB_DEVICE(0x0424, 0x9E00),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9505A USB Ethernet Device */
-+              USB_DEVICE(0x0424, 0x9E01),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9512/9514 USB Hub & Ethernet Device */
-+              USB_DEVICE(0x0424, 0xec00),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9500 USB Ethernet Device (SAL10) */
-+              USB_DEVICE(0x0424, 0x9900),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9505 USB Ethernet Device (SAL10) */
-+              USB_DEVICE(0x0424, 0x9901),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9500A USB Ethernet Device (SAL10) */
-+              USB_DEVICE(0x0424, 0x9902),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9505A USB Ethernet Device (SAL10) */
-+              USB_DEVICE(0x0424, 0x9903),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9512/9514 USB Hub & Ethernet Device (SAL10) */
-+              USB_DEVICE(0x0424, 0x9904),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9500A USB Ethernet Device (HAL) */
-+              USB_DEVICE(0x0424, 0x9905),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9505A USB Ethernet Device (HAL) */
-+              USB_DEVICE(0x0424, 0x9906),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9500 USB Ethernet Device (Alternate ID) */
-+              USB_DEVICE(0x0424, 0x9907),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9500A USB Ethernet Device (Alternate ID) */
-+              USB_DEVICE(0x0424, 0x9908),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC9512/9514 USB Hub & Ethernet Device (Alternate ID) */
-+              USB_DEVICE(0x0424, 0x9909),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC LAN9530 USB Ethernet Device */
-+              USB_DEVICE(0x0424, 0x9530),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC LAN9730 USB Ethernet Device */
-+              USB_DEVICE(0x0424, 0x9730),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      {
-+              /* SMSC LAN89530 USB Ethernet Device */
-+              USB_DEVICE(0x0424, 0x9E08),
-+              .driver_info = (unsigned long) &smsc95xx_info,
-+      },
-+      { },            /* END */
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver smsc95xx_driver = {
-+      .name           = "smsc95xx",
-+      .id_table       = products,
-+      .probe          = usbnet_probe,
-+      .suspend        = smsc95xx_suspend,
-+      .resume         = smsc95xx_resume,
-+      .reset_resume   = smsc95xx_reset_resume,
-+      .disconnect     = usbnet_disconnect,
-+      .disable_hub_initiated_lpm = 1,
-+      .supports_autosuspend = 1,
-+};
-+
-+module_usb_driver(smsc95xx_driver);
-+
-+MODULE_AUTHOR("Nancy Lin");
-+MODULE_AUTHOR("Steve Glendinning <steve.glendinning@shawell.net>");
-+MODULE_DESCRIPTION("SMSC95XX USB 2.0 Ethernet Devices");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/smsc95xx.h backports-4.2.6-1/drivers/net/usb/smsc95xx.h
---- backports-4.2.6-1.org/drivers/net/usb/smsc95xx.h   1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/smsc95xx.h       2016-06-28 14:35:18.011973884 +0200
-@@ -0,0 +1,290 @@
-+ /***************************************************************************
-+ *
-+ * Copyright (C) 2007-2008 SMSC
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ *
-+ *****************************************************************************/
-+
-+#ifndef _SMSC95XX_H
-+#define _SMSC95XX_H
-+
-+/* Tx command words */
-+#define TX_CMD_A_DATA_OFFSET_         (0x001F0000)
-+#define TX_CMD_A_FIRST_SEG_           (0x00002000)
-+#define TX_CMD_A_LAST_SEG_            (0x00001000)
-+#define TX_CMD_A_BUF_SIZE_            (0x000007FF)
-+
-+#define TX_CMD_B_CSUM_ENABLE          (0x00004000)
-+#define TX_CMD_B_ADD_CRC_DISABLE_     (0x00002000)
-+#define TX_CMD_B_DISABLE_PADDING_     (0x00001000)
-+#define TX_CMD_B_PKT_BYTE_LENGTH_     (0x000007FF)
-+
-+/* Rx status word */
-+#define RX_STS_FF_                    (0x40000000)    /* Filter Fail */
-+#define RX_STS_FL_                    (0x3FFF0000)    /* Frame Length */
-+#define RX_STS_ES_                    (0x00008000)    /* Error Summary */
-+#define RX_STS_BF_                    (0x00002000)    /* Broadcast Frame */
-+#define RX_STS_LE_                    (0x00001000)    /* Length Error */
-+#define RX_STS_RF_                    (0x00000800)    /* Runt Frame */
-+#define RX_STS_MF_                    (0x00000400)    /* Multicast Frame */
-+#define RX_STS_TL_                    (0x00000080)    /* Frame too long */
-+#define RX_STS_CS_                    (0x00000040)    /* Collision Seen */
-+#define RX_STS_FT_                    (0x00000020)    /* Frame Type */
-+#define RX_STS_RW_                    (0x00000010)    /* Receive Watchdog */
-+#define RX_STS_ME_                    (0x00000008)    /* Mii Error */
-+#define RX_STS_DB_                    (0x00000004)    /* Dribbling */
-+#define RX_STS_CRC_                   (0x00000002)    /* CRC Error */
-+
-+/* SCSRs */
-+#define ID_REV                                (0x00)
-+#define ID_REV_CHIP_ID_MASK_          (0xFFFF0000)
-+#define ID_REV_CHIP_REV_MASK_         (0x0000FFFF)
-+#define ID_REV_CHIP_ID_9500_          (0x9500)
-+#define ID_REV_CHIP_ID_9500A_         (0x9E00)
-+#define ID_REV_CHIP_ID_9512_          (0xEC00)
-+#define ID_REV_CHIP_ID_9530_          (0x9530)
-+#define ID_REV_CHIP_ID_89530_         (0x9E08)
-+#define ID_REV_CHIP_ID_9730_          (0x9730)
-+
-+#define INT_STS                               (0x08)
-+#define INT_STS_TX_STOP_              (0x00020000)
-+#define INT_STS_RX_STOP_              (0x00010000)
-+#define INT_STS_PHY_INT_              (0x00008000)
-+#define INT_STS_TXE_                  (0x00004000)
-+#define INT_STS_TDFU_                 (0x00002000)
-+#define INT_STS_TDFO_                 (0x00001000)
-+#define INT_STS_RXDF_                 (0x00000800)
-+#define INT_STS_GPIOS_                        (0x000007FF)
-+#define INT_STS_CLEAR_ALL_            (0xFFFFFFFF)
-+
-+#define RX_CFG                                (0x0C)
-+#define RX_FIFO_FLUSH_                        (0x00000001)
-+
-+#define TX_CFG                                (0x10)
-+#define TX_CFG_ON_                    (0x00000004)
-+#define TX_CFG_STOP_                  (0x00000002)
-+#define TX_CFG_FIFO_FLUSH_            (0x00000001)
-+
-+#define HW_CFG                                (0x14)
-+#define HW_CFG_BIR_                   (0x00001000)
-+#define HW_CFG_LEDB_                  (0x00000800)
-+#define HW_CFG_RXDOFF_                        (0x00000600)
-+#define HW_CFG_DRP_                   (0x00000040)
-+#define HW_CFG_MEF_                   (0x00000020)
-+#define HW_CFG_LRST_                  (0x00000008)
-+#define HW_CFG_PSEL_                  (0x00000004)
-+#define HW_CFG_BCE_                   (0x00000002)
-+#define HW_CFG_SRST_                  (0x00000001)
-+
-+#define RX_FIFO_INF                   (0x18)
-+
-+#define PM_CTRL                               (0x20)
-+#define PM_CTL_RES_CLR_WKP_STS                (0x00000200)
-+#define PM_CTL_DEV_RDY_                       (0x00000080)
-+#define PM_CTL_SUS_MODE_              (0x00000060)
-+#define PM_CTL_SUS_MODE_0             (0x00000000)
-+#define PM_CTL_SUS_MODE_1             (0x00000020)
-+#define PM_CTL_SUS_MODE_2             (0x00000040)
-+#define PM_CTL_SUS_MODE_3             (0x00000060)
-+#define PM_CTL_PHY_RST_                       (0x00000010)
-+#define PM_CTL_WOL_EN_                        (0x00000008)
-+#define PM_CTL_ED_EN_                 (0x00000004)
-+#define PM_CTL_WUPS_                  (0x00000003)
-+#define PM_CTL_WUPS_NO_                       (0x00000000)
-+#define PM_CTL_WUPS_ED_                       (0x00000001)
-+#define PM_CTL_WUPS_WOL_              (0x00000002)
-+#define PM_CTL_WUPS_MULTI_            (0x00000003)
-+
-+#define LED_GPIO_CFG                  (0x24)
-+#define LED_GPIO_CFG_SPD_LED          (0x01000000)
-+#define LED_GPIO_CFG_LNK_LED          (0x00100000)
-+#define LED_GPIO_CFG_FDX_LED          (0x00010000)
-+
-+#define GPIO_CFG                      (0x28)
-+
-+#define AFC_CFG                               (0x2C)
-+
-+/* Hi watermark = 15.5Kb (~10 mtu pkts) */
-+/* low watermark = 3k (~2 mtu pkts) */
-+/* backpressure duration = ~ 350us */
-+/* Apply FC on any frame. */
-+#define AFC_CFG_DEFAULT                       (0x00F830A1)
-+
-+#define E2P_CMD                               (0x30)
-+#define E2P_CMD_BUSY_                 (0x80000000)
-+#define E2P_CMD_MASK_                 (0x70000000)
-+#define E2P_CMD_READ_                 (0x00000000)
-+#define E2P_CMD_EWDS_                 (0x10000000)
-+#define E2P_CMD_EWEN_                 (0x20000000)
-+#define E2P_CMD_WRITE_                        (0x30000000)
-+#define E2P_CMD_WRAL_                 (0x40000000)
-+#define E2P_CMD_ERASE_                        (0x50000000)
-+#define E2P_CMD_ERAL_                 (0x60000000)
-+#define E2P_CMD_RELOAD_                       (0x70000000)
-+#define E2P_CMD_TIMEOUT_              (0x00000400)
-+#define E2P_CMD_LOADED_                       (0x00000200)
-+#define E2P_CMD_ADDR_                 (0x000001FF)
-+
-+#define MAX_EEPROM_SIZE                       (512)
-+
-+#define E2P_DATA                      (0x34)
-+#define E2P_DATA_MASK_                        (0x000000FF)
-+
-+#define BURST_CAP                     (0x38)
-+
-+#define GPIO_WAKE                     (0x64)
-+
-+#define INT_EP_CTL                    (0x68)
-+#define INT_EP_CTL_INTEP_             (0x80000000)
-+#define INT_EP_CTL_MACRTO_            (0x00080000)
-+#define INT_EP_CTL_TX_STOP_           (0x00020000)
-+#define INT_EP_CTL_RX_STOP_           (0x00010000)
-+#define INT_EP_CTL_PHY_INT_           (0x00008000)
-+#define INT_EP_CTL_TXE_                       (0x00004000)
-+#define INT_EP_CTL_TDFU_              (0x00002000)
-+#define INT_EP_CTL_TDFO_              (0x00001000)
-+#define INT_EP_CTL_RXDF_              (0x00000800)
-+#define INT_EP_CTL_GPIOS_             (0x000007FF)
-+
-+#define BULK_IN_DLY                   (0x6C)
-+
-+/* MAC CSRs */
-+#define MAC_CR                                (0x100)
-+#define MAC_CR_RXALL_                 (0x80000000)
-+#define MAC_CR_RCVOWN_                        (0x00800000)
-+#define MAC_CR_LOOPBK_                        (0x00200000)
-+#define MAC_CR_FDPX_                  (0x00100000)
-+#define MAC_CR_MCPAS_                 (0x00080000)
-+#define MAC_CR_PRMS_                  (0x00040000)
-+#define MAC_CR_INVFILT_                       (0x00020000)
-+#define MAC_CR_PASSBAD_                       (0x00010000)
-+#define MAC_CR_HFILT_                 (0x00008000)
-+#define MAC_CR_HPFILT_                        (0x00002000)
-+#define MAC_CR_LCOLL_                 (0x00001000)
-+#define MAC_CR_BCAST_                 (0x00000800)
-+#define MAC_CR_DISRTY_                        (0x00000400)
-+#define MAC_CR_PADSTR_                        (0x00000100)
-+#define MAC_CR_BOLMT_MASK             (0x000000C0)
-+#define MAC_CR_DFCHK_                 (0x00000020)
-+#define MAC_CR_TXEN_                  (0x00000008)
-+#define MAC_CR_RXEN_                  (0x00000004)
-+
-+#define ADDRH                         (0x104)
-+
-+#define ADDRL                         (0x108)
-+
-+#define HASHH                         (0x10C)
-+
-+#define HASHL                         (0x110)
-+
-+#define MII_ADDR                      (0x114)
-+#define MII_WRITE_                    (0x02)
-+#define MII_BUSY_                     (0x01)
-+#define MII_READ_                     (0x00) /* ~of MII Write bit */
-+
-+#define MII_DATA                      (0x118)
-+
-+#define FLOW                          (0x11C)
-+#define FLOW_FCPT_                    (0xFFFF0000)
-+#define FLOW_FCPASS_                  (0x00000004)
-+#define FLOW_FCEN_                    (0x00000002)
-+#define FLOW_FCBSY_                   (0x00000001)
-+
-+#define VLAN1                         (0x120)
-+
-+#define VLAN2                         (0x124)
-+
-+#define WUFF                          (0x128)
-+#define LAN9500_WUFF_NUM              (4)
-+#define LAN9500A_WUFF_NUM             (8)
-+
-+#define WUCSR                         (0x12C)
-+#define WUCSR_WFF_PTR_RST_            (0x80000000)
-+#define WUCSR_GUE_                    (0x00000200)
-+#define WUCSR_WUFR_                   (0x00000040)
-+#define WUCSR_MPR_                    (0x00000020)
-+#define WUCSR_WAKE_EN_                        (0x00000004)
-+#define WUCSR_MPEN_                   (0x00000002)
-+
-+#define COE_CR                                (0x130)
-+#define Tx_COE_EN_                    (0x00010000)
-+#define Rx_COE_MODE_                  (0x00000002)
-+#define Rx_COE_EN_                    (0x00000001)
-+
-+/* Vendor-specific PHY Definitions */
-+
-+/* EDPD NLP / crossover time configuration (LAN9500A only) */
-+#define PHY_EDPD_CONFIG                       (16)
-+#define PHY_EDPD_CONFIG_TX_NLP_EN_    ((u16)0x8000)
-+#define PHY_EDPD_CONFIG_TX_NLP_1000_  ((u16)0x0000)
-+#define PHY_EDPD_CONFIG_TX_NLP_768_   ((u16)0x2000)
-+#define PHY_EDPD_CONFIG_TX_NLP_512_   ((u16)0x4000)
-+#define PHY_EDPD_CONFIG_TX_NLP_256_   ((u16)0x6000)
-+#define PHY_EDPD_CONFIG_RX_1_NLP_     ((u16)0x1000)
-+#define PHY_EDPD_CONFIG_RX_NLP_64_    ((u16)0x0000)
-+#define PHY_EDPD_CONFIG_RX_NLP_256_   ((u16)0x0400)
-+#define PHY_EDPD_CONFIG_RX_NLP_512_   ((u16)0x0800)
-+#define PHY_EDPD_CONFIG_RX_NLP_1000_  ((u16)0x0C00)
-+#define PHY_EDPD_CONFIG_EXT_CROSSOVER_        ((u16)0x0001)
-+#define PHY_EDPD_CONFIG_DEFAULT               (PHY_EDPD_CONFIG_TX_NLP_EN_ | \
-+                                       PHY_EDPD_CONFIG_TX_NLP_768_ | \
-+                                       PHY_EDPD_CONFIG_RX_1_NLP_)
-+
-+/* Mode Control/Status Register */
-+#define PHY_MODE_CTRL_STS             (17)
-+#define MODE_CTRL_STS_EDPWRDOWN_      ((u16)0x2000)
-+#define MODE_CTRL_STS_ENERGYON_               ((u16)0x0002)
-+
-+#define SPECIAL_CTRL_STS              (27)
-+#define SPECIAL_CTRL_STS_OVRRD_AMDIX_ ((u16)0x8000)
-+#define SPECIAL_CTRL_STS_AMDIX_ENABLE_        ((u16)0x4000)
-+#define SPECIAL_CTRL_STS_AMDIX_STATE_ ((u16)0x2000)
-+
-+#define PHY_INT_SRC                   (29)
-+#define PHY_INT_SRC_ENERGY_ON_                ((u16)0x0080)
-+#define PHY_INT_SRC_ANEG_COMP_                ((u16)0x0040)
-+#define PHY_INT_SRC_REMOTE_FAULT_     ((u16)0x0020)
-+#define PHY_INT_SRC_LINK_DOWN_                ((u16)0x0010)
-+
-+#define PHY_INT_MASK                  (30)
-+#define PHY_INT_MASK_ENERGY_ON_               ((u16)0x0080)
-+#define PHY_INT_MASK_ANEG_COMP_               ((u16)0x0040)
-+#define PHY_INT_MASK_REMOTE_FAULT_    ((u16)0x0020)
-+#define PHY_INT_MASK_LINK_DOWN_               ((u16)0x0010)
-+#define PHY_INT_MASK_DEFAULT_         (PHY_INT_MASK_ANEG_COMP_ | \
-+                                       PHY_INT_MASK_LINK_DOWN_)
-+
-+#define PHY_SPECIAL                   (31)
-+#define PHY_SPECIAL_SPD_              ((u16)0x001C)
-+#define PHY_SPECIAL_SPD_10HALF_               ((u16)0x0004)
-+#define PHY_SPECIAL_SPD_10FULL_               ((u16)0x0014)
-+#define PHY_SPECIAL_SPD_100HALF_      ((u16)0x0008)
-+#define PHY_SPECIAL_SPD_100FULL_      ((u16)0x0018)
-+
-+/* USB Vendor Requests */
-+#define USB_VENDOR_REQUEST_WRITE_REGISTER     0xA0
-+#define USB_VENDOR_REQUEST_READ_REGISTER      0xA1
-+#define USB_VENDOR_REQUEST_GET_STATS          0xA2
-+
-+/* Interrupt Endpoint status word bitfields */
-+#define INT_ENP_TX_STOP_              ((u32)BIT(17))
-+#define INT_ENP_RX_STOP_              ((u32)BIT(16))
-+#define INT_ENP_PHY_INT_              ((u32)BIT(15))
-+#define INT_ENP_TXE_                  ((u32)BIT(14))
-+#define INT_ENP_TDFU_                 ((u32)BIT(13))
-+#define INT_ENP_TDFO_                 ((u32)BIT(12))
-+#define INT_ENP_RXDF_                 ((u32)BIT(11))
-+
-+#endif /* _SMSC95XX_H */
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/sr9700.c backports-4.2.6-1/drivers/net/usb/sr9700.c
---- backports-4.2.6-1.org/drivers/net/usb/sr9700.c     1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/sr9700.c 2016-06-28 14:35:18.011973884 +0200
-@@ -0,0 +1,559 @@
-+/*
-+ * CoreChip-sz SR9700 one chip USB 1.1 Ethernet Devices
-+ *
-+ * Author : Liu Junliang <liujunliang_ljl@163.com>
-+ *
-+ * Based on dm9601.c
-+ *
-+ * 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
-+ * kind, whether express or implied.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/sched.h>
-+#include <linux/stddef.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/crc32.h>
-+#include <linux/usb/usbnet.h>
-+
-+#include "sr9700.h"
-+
-+static int sr_read(struct usbnet *dev, u8 reg, u16 length, void *data)
-+{
-+      int err;
-+
-+      err = usbnet_read_cmd(dev, SR_RD_REGS, SR_REQ_RD_REG, 0, reg, data,
-+                            length);
-+      if ((err != length) && (err >= 0))
-+              err = -EINVAL;
-+      return err;
-+}
-+
-+static int sr_write(struct usbnet *dev, u8 reg, u16 length, void *data)
-+{
-+      int err;
-+
-+      err = usbnet_write_cmd(dev, SR_WR_REGS, SR_REQ_WR_REG, 0, reg, data,
-+                             length);
-+      if ((err >= 0) && (err < length))
-+              err = -EINVAL;
-+      return err;
-+}
-+
-+static int sr_read_reg(struct usbnet *dev, u8 reg, u8 *value)
-+{
-+      return sr_read(dev, reg, 1, value);
-+}
-+
-+static int sr_write_reg(struct usbnet *dev, u8 reg, u8 value)
-+{
-+      return usbnet_write_cmd(dev, SR_WR_REGS, SR_REQ_WR_REG,
-+                              value, reg, NULL, 0);
-+}
-+
-+static void sr_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
-+{
-+      usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG,
-+                             0, reg, data, length);
-+}
-+
-+static void sr_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
-+{
-+      usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG,
-+                             value, reg, NULL, 0);
-+}
-+
-+static int wait_phy_eeprom_ready(struct usbnet *dev, int phy)
-+{
-+      int i;
-+
-+      for (i = 0; i < SR_SHARE_TIMEOUT; i++) {
-+              u8 tmp = 0;
-+              int ret;
-+
-+              udelay(1);
-+              ret = sr_read_reg(dev, SR_EPCR, &tmp);
-+              if (ret < 0)
-+                      return ret;
-+
-+              /* ready */
-+              if (!(tmp & EPCR_ERRE))
-+                      return 0;
-+      }
-+
-+      netdev_err(dev->net, "%s write timed out!\n", phy ? "phy" : "eeprom");
-+
-+      return -EIO;
-+}
-+
-+static int sr_share_read_word(struct usbnet *dev, int phy, u8 reg,
-+                            __le16 *value)
-+{
-+      int ret;
-+
-+      mutex_lock(&dev->phy_mutex);
-+
-+      sr_write_reg(dev, SR_EPAR, phy ? (reg | EPAR_PHY_ADR) : reg);
-+      sr_write_reg(dev, SR_EPCR, phy ? (EPCR_EPOS | EPCR_ERPRR) : EPCR_ERPRR);
-+
-+      ret = wait_phy_eeprom_ready(dev, phy);
-+      if (ret < 0)
-+              goto out_unlock;
-+
-+      sr_write_reg(dev, SR_EPCR, 0x0);
-+      ret = sr_read(dev, SR_EPDR, 2, value);
-+
-+      netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n",
-+                 phy, reg, *value, ret);
-+
-+out_unlock:
-+      mutex_unlock(&dev->phy_mutex);
-+      return ret;
-+}
-+
-+static int sr_share_write_word(struct usbnet *dev, int phy, u8 reg,
-+                             __le16 value)
-+{
-+      int ret;
-+
-+      mutex_lock(&dev->phy_mutex);
-+
-+      ret = sr_write(dev, SR_EPDR, 2, &value);
-+      if (ret < 0)
-+              goto out_unlock;
-+
-+      sr_write_reg(dev, SR_EPAR, phy ? (reg | EPAR_PHY_ADR) : reg);
-+      sr_write_reg(dev, SR_EPCR, phy ? (EPCR_WEP | EPCR_EPOS | EPCR_ERPRW) :
-+                  (EPCR_WEP | EPCR_ERPRW));
-+
-+      ret = wait_phy_eeprom_ready(dev, phy);
-+      if (ret < 0)
-+              goto out_unlock;
-+
-+      sr_write_reg(dev, SR_EPCR, 0x0);
-+
-+out_unlock:
-+      mutex_unlock(&dev->phy_mutex);
-+      return ret;
-+}
-+
-+static int sr_read_eeprom_word(struct usbnet *dev, u8 offset, void *value)
-+{
-+      return sr_share_read_word(dev, 0, offset, value);
-+}
-+
-+static int sr9700_get_eeprom_len(struct net_device *netdev)
-+{
-+      return SR_EEPROM_LEN;
-+}
-+
-+static int sr9700_get_eeprom(struct net_device *netdev,
-+                           struct ethtool_eeprom *eeprom, u8 *data)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      __le16 *buf = (__le16 *)data;
-+      int ret = 0;
-+      int i;
-+
-+      /* access is 16bit */
-+      if ((eeprom->offset & 0x01) || (eeprom->len & 0x01))
-+              return -EINVAL;
-+
-+      for (i = 0; i < eeprom->len / 2; i++) {
-+              ret = sr_read_eeprom_word(dev, eeprom->offset / 2 + i, buf + i);
-+              if (ret < 0)
-+                      break;
-+      }
-+
-+      return ret;
-+}
-+
-+static int sr_mdio_read(struct net_device *netdev, int phy_id, int loc)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      __le16 res;
-+      int rc = 0;
-+
-+      if (phy_id) {
-+              netdev_dbg(netdev, "Only internal phy supported\n");
-+              return 0;
-+      }
-+
-+      /* Access NSR_LINKST bit for link status instead of MII_BMSR */
-+      if (loc == MII_BMSR) {
-+              u8 value;
-+
-+              sr_read_reg(dev, SR_NSR, &value);
-+              if (value & NSR_LINKST)
-+                      rc = 1;
-+      }
-+      sr_share_read_word(dev, 1, loc, &res);
-+      if (rc == 1)
-+              res = le16_to_cpu(res) | BMSR_LSTATUS;
-+      else
-+              res = le16_to_cpu(res) & ~BMSR_LSTATUS;
-+
-+      netdev_dbg(netdev, "sr_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
-+                 phy_id, loc, res);
-+
-+      return res;
-+}
-+
-+static void sr_mdio_write(struct net_device *netdev, int phy_id, int loc,
-+                        int val)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      __le16 res = cpu_to_le16(val);
-+
-+      if (phy_id) {
-+              netdev_dbg(netdev, "Only internal phy supported\n");
-+              return;
-+      }
-+
-+      netdev_dbg(netdev, "sr_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
-+                 phy_id, loc, val);
-+
-+      sr_share_write_word(dev, 1, loc, res);
-+}
-+
-+static u32 sr9700_get_link(struct net_device *netdev)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      u8 value = 0;
-+      int rc = 0;
-+
-+      /* Get the Link Status directly */
-+      sr_read_reg(dev, SR_NSR, &value);
-+      if (value & NSR_LINKST)
-+              rc = 1;
-+
-+      return rc;
-+}
-+
-+static int sr9700_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+
-+      return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
-+}
-+
-+static const struct ethtool_ops sr9700_ethtool_ops = {
-+      .get_drvinfo    = usbnet_get_drvinfo,
-+      .get_link       = sr9700_get_link,
-+      .get_msglevel   = usbnet_get_msglevel,
-+      .set_msglevel   = usbnet_set_msglevel,
-+      .get_eeprom_len = sr9700_get_eeprom_len,
-+      .get_eeprom     = sr9700_get_eeprom,
-+      .get_settings   = usbnet_get_settings,
-+      .set_settings   = usbnet_set_settings,
-+      .nway_reset     = usbnet_nway_reset,
-+};
-+
-+static void sr9700_set_multicast(struct net_device *netdev)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      /* We use the 20 byte dev->data for our 8 byte filter buffer
-+       * to avoid allocating memory that is tricky to free later
-+       */
-+      u8 *hashes = (u8 *)&dev->data;
-+      /* rx_ctl setting : enable, disable_long, disable_crc */
-+      u8 rx_ctl = RCR_RXEN | RCR_DIS_CRC | RCR_DIS_LONG;
-+
-+      memset(hashes, 0x00, SR_MCAST_SIZE);
-+      /* broadcast address */
-+      hashes[SR_MCAST_SIZE - 1] |= SR_MCAST_ADDR_FLAG;
-+      if (netdev->flags & IFF_PROMISC) {
-+              rx_ctl |= RCR_PRMSC;
-+      } else if (netdev->flags & IFF_ALLMULTI ||
-+                 netdev_mc_count(netdev) > SR_MCAST_MAX) {
-+              rx_ctl |= RCR_RUNT;
-+      } else if (!netdev_mc_empty(netdev)) {
-+              struct netdev_hw_addr *ha;
-+
-+              netdev_for_each_mc_addr(ha, netdev) {
-+                      u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26;
-+                      hashes[crc >> 3] |= 1 << (crc & 0x7);
-+              }
-+      }
-+
-+      sr_write_async(dev, SR_MAR, SR_MCAST_SIZE, hashes);
-+      sr_write_reg_async(dev, SR_RCR, rx_ctl);
-+}
-+
-+static int sr9700_set_mac_address(struct net_device *netdev, void *p)
-+{
-+      struct usbnet *dev = netdev_priv(netdev);
-+      struct sockaddr *addr = p;
-+
-+      if (!is_valid_ether_addr(addr->sa_data)) {
-+              netdev_err(netdev, "not setting invalid mac address %pM\n",
-+                         addr->sa_data);
-+              return -EINVAL;
-+      }
-+
-+      memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-+      sr_write_async(dev, SR_PAR, 6, netdev->dev_addr);
-+
-+      return 0;
-+}
-+
-+static const struct net_device_ops sr9700_netdev_ops = {
-+      .ndo_open               = usbnet_open,
-+      .ndo_stop               = usbnet_stop,
-+      .ndo_start_xmit         = usbnet_start_xmit,
-+      .ndo_tx_timeout         = usbnet_tx_timeout,
-+      .ndo_change_mtu         = usbnet_change_mtu,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_do_ioctl           = sr9700_ioctl,
-+      .ndo_set_rx_mode        = sr9700_set_multicast,
-+      .ndo_set_mac_address    = sr9700_set_mac_address,
-+};
-+
-+static int sr9700_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      struct net_device *netdev;
-+      struct mii_if_info *mii;
-+      int ret;
-+
-+      ret = usbnet_get_endpoints(dev, intf);
-+      if (ret)
-+              goto out;
-+
-+      netdev = dev->net;
-+
-+      netdev->netdev_ops = &sr9700_netdev_ops;
-+      netdev->ethtool_ops = &sr9700_ethtool_ops;
-+      netdev->hard_header_len += SR_TX_OVERHEAD;
-+      dev->hard_mtu = netdev->mtu + netdev->hard_header_len;
-+      /* bulkin buffer is preferably not less than 3K */
-+      dev->rx_urb_size = 3072;
-+
-+      mii = &dev->mii;
-+      mii->dev = netdev;
-+      mii->mdio_read = sr_mdio_read;
-+      mii->mdio_write = sr_mdio_write;
-+      mii->phy_id_mask = 0x1f;
-+      mii->reg_num_mask = 0x1f;
-+
-+      sr_write_reg(dev, SR_NCR, NCR_RST);
-+      udelay(20);
-+
-+      /* read MAC
-+       * After Chip Power on, the Chip will reload the MAC from
-+       * EEPROM automatically to PAR. In case there is no EEPROM externally,
-+       * a default MAC address is stored in PAR for making chip work properly.
-+       */
-+      if (sr_read(dev, SR_PAR, ETH_ALEN, netdev->dev_addr) < 0) {
-+              netdev_err(netdev, "Error reading MAC address\n");
-+              ret = -ENODEV;
-+              goto out;
-+      }
-+
-+      /* power up and reset phy */
-+      sr_write_reg(dev, SR_PRR, PRR_PHY_RST);
-+      /* at least 10ms, here 20ms for safe */
-+      mdelay(20);
-+      sr_write_reg(dev, SR_PRR, 0);
-+      /* at least 1ms, here 2ms for reading right register */
-+      udelay(2 * 1000);
-+
-+      /* receive broadcast packets */
-+      sr9700_set_multicast(netdev);
-+
-+      sr_mdio_write(netdev, mii->phy_id, MII_BMCR, BMCR_RESET);
-+      sr_mdio_write(netdev, mii->phy_id, MII_ADVERTISE, ADVERTISE_ALL |
-+                    ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
-+      mii_nway_restart(mii);
-+
-+out:
-+      return ret;
-+}
-+
-+static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      struct sk_buff *sr_skb;
-+      int len;
-+
-+      /* skb content (packets) format :
-+       *                    p0            p1            p2    ......    pm
-+       *                 /      \
-+       *            /                \
-+       *        /                            \
-+       *  /                                        \
-+       * p0b0 p0b1 p0b2 p0b3 ...... p0b(n-4) p0b(n-3)...p0bn
-+       *
-+       * p0 : packet 0
-+       * p0b0 : packet 0 byte 0
-+       *
-+       * b0: rx status
-+       * b1: packet length (incl crc) low
-+       * b2: packet length (incl crc) high
-+       * b3..n-4: packet data
-+       * bn-3..bn: ethernet packet crc
-+       */
-+      if (unlikely(skb->len < SR_RX_OVERHEAD)) {
-+              netdev_err(dev->net, "unexpected tiny rx frame\n");
-+              return 0;
-+      }
-+
-+      /* one skb may contains multiple packets */
-+      while (skb->len > SR_RX_OVERHEAD) {
-+              if (skb->data[0] != 0x40)
-+                      return 0;
-+
-+              /* ignore the CRC length */
-+              len = (skb->data[1] | (skb->data[2] << 8)) - 4;
-+
-+              if (len > ETH_FRAME_LEN)
-+                      return 0;
-+
-+              /* the last packet of current skb */
-+              if (skb->len == (len + SR_RX_OVERHEAD)) {
-+                      skb_pull(skb, 3);
-+                      skb->len = len;
-+                      skb_set_tail_pointer(skb, len);
-+                      skb->truesize = len + sizeof(struct sk_buff);
-+                      return 2;
-+              }
-+
-+              /* skb_clone is used for address align */
-+              sr_skb = skb_clone(skb, GFP_ATOMIC);
-+              if (!sr_skb)
-+                      return 0;
-+
-+              sr_skb->len = len;
-+              sr_skb->data = skb->data + 3;
-+              skb_set_tail_pointer(sr_skb, len);
-+              sr_skb->truesize = len + sizeof(struct sk_buff);
-+              usbnet_skb_return(dev, sr_skb);
-+
-+              skb_pull(skb, len + SR_RX_OVERHEAD);
-+      };
-+
-+      return 0;
-+}
-+
-+static struct sk_buff *sr9700_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
-+                                     gfp_t flags)
-+{
-+      int len;
-+
-+      /* SR9700 can only send out one ethernet packet at once.
-+       *
-+       * b0 b1 b2 b3 ...... b(n-4) b(n-3)...bn
-+       *
-+       * b0: rx status
-+       * b1: packet length (incl crc) low
-+       * b2: packet length (incl crc) high
-+       * b3..n-4: packet data
-+       * bn-3..bn: ethernet packet crc
-+       */
-+
-+      len = skb->len;
-+
-+      if (skb_headroom(skb) < SR_TX_OVERHEAD) {
-+              struct sk_buff *skb2;
-+
-+              skb2 = skb_copy_expand(skb, SR_TX_OVERHEAD, 0, flags);
-+              dev_kfree_skb_any(skb);
-+              skb = skb2;
-+              if (!skb)
-+                      return NULL;
-+      }
-+
-+      __skb_push(skb, SR_TX_OVERHEAD);
-+
-+      /* usbnet adds padding if length is a multiple of packet size
-+       * if so, adjust length value in header
-+       */
-+      if ((skb->len % dev->maxpacket) == 0)
-+              len++;
-+
-+      skb->data[0] = len;
-+      skb->data[1] = len >> 8;
-+
-+      return skb;
-+}
-+
-+static void sr9700_status(struct usbnet *dev, struct urb *urb)
-+{
-+      int link;
-+      u8 *buf;
-+
-+      /* format:
-+         b0: net status
-+         b1: tx status 1
-+         b2: tx status 2
-+         b3: rx status
-+         b4: rx overflow
-+         b5: rx count
-+         b6: tx count
-+         b7: gpr
-+      */
-+
-+      if (urb->actual_length < 8)
-+              return;
-+
-+      buf = urb->transfer_buffer;
-+
-+      link = !!(buf[0] & 0x40);
-+      if (netif_carrier_ok(dev->net) != link) {
-+              usbnet_link_change(dev, link, 1);
-+              netdev_dbg(dev->net, "Link Status is: %d\n", link);
-+      }
-+}
-+
-+static int sr9700_link_reset(struct usbnet *dev)
-+{
-+      struct ethtool_cmd ecmd;
-+
-+      mii_check_media(&dev->mii, 1, 1);
-+      mii_ethtool_gset(&dev->mii, &ecmd);
-+
-+      netdev_dbg(dev->net, "link_reset() speed: %d duplex: %d\n",
-+                 ecmd.speed, ecmd.duplex);
-+
-+      return 0;
-+}
-+
-+static const struct driver_info sr9700_driver_info = {
-+      .description    = "CoreChip SR9700 USB Ethernet",
-+      .flags          = FLAG_ETHER,
-+      .bind           = sr9700_bind,
-+      .rx_fixup       = sr9700_rx_fixup,
-+      .tx_fixup       = sr9700_tx_fixup,
-+      .status         = sr9700_status,
-+      .link_reset     = sr9700_link_reset,
-+      .reset          = sr9700_link_reset,
-+};
-+
-+static const struct usb_device_id products[] = {
-+      {
-+              USB_DEVICE(0x0fe6, 0x9700),     /* SR9700 device */
-+              .driver_info = (unsigned long)&sr9700_driver_info,
-+      },
-+      {},                     /* END */
-+};
-+
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver sr9700_usb_driver = {
-+      .name           = "sr9700",
-+      .id_table       = products,
-+      .probe          = usbnet_probe,
-+      .disconnect     = usbnet_disconnect,
-+      .suspend        = usbnet_suspend,
-+      .resume         = usbnet_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(sr9700_usb_driver);
-+
-+MODULE_AUTHOR("liujl <liujunliang_ljl@163.com>");
-+MODULE_DESCRIPTION("SR9700 one chip USB 1.1 USB to Ethernet device from http://www.corechip-sz.com/");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/sr9700.h backports-4.2.6-1/drivers/net/usb/sr9700.h
---- backports-4.2.6-1.org/drivers/net/usb/sr9700.h     1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/sr9700.h 2016-06-28 14:35:18.011973884 +0200
-@@ -0,0 +1,173 @@
-+/*
-+ * CoreChip-sz SR9700 one chip USB 1.1 Ethernet Devices
-+ *
-+ * Author : Liu Junliang <liujunliang_ljl@163.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.
-+ */
-+
-+#ifndef _SR9700_H
-+#define       _SR9700_H
-+
-+/* sr9700 spec. register table on Linux platform */
-+
-+/* Network Control Reg */
-+#define       SR_NCR                  0x00
-+#define               NCR_RST                 (1 << 0)
-+#define               NCR_LBK                 (3 << 1)
-+#define               NCR_FDX                 (1 << 3)
-+#define               NCR_WAKEEN              (1 << 6)
-+/* Network Status Reg */
-+#define       SR_NSR                  0x01
-+#define               NSR_RXRDY               (1 << 0)
-+#define               NSR_RXOV                (1 << 1)
-+#define               NSR_TX1END              (1 << 2)
-+#define               NSR_TX2END              (1 << 3)
-+#define               NSR_TXFULL              (1 << 4)
-+#define               NSR_WAKEST              (1 << 5)
-+#define               NSR_LINKST              (1 << 6)
-+#define               NSR_SPEED               (1 << 7)
-+/* Tx Control Reg */
-+#define       SR_TCR                  0x02
-+#define               TCR_CRC_DIS             (1 << 1)
-+#define               TCR_PAD_DIS             (1 << 2)
-+#define               TCR_LC_CARE             (1 << 3)
-+#define               TCR_CRS_CARE    (1 << 4)
-+#define               TCR_EXCECM              (1 << 5)
-+#define               TCR_LF_EN               (1 << 6)
-+/* Tx Status Reg for Packet Index 1 */
-+#define       SR_TSR1         0x03
-+#define               TSR1_EC                 (1 << 2)
-+#define               TSR1_COL                (1 << 3)
-+#define               TSR1_LC                 (1 << 4)
-+#define               TSR1_NC                 (1 << 5)
-+#define               TSR1_LOC                (1 << 6)
-+#define               TSR1_TLF                (1 << 7)
-+/* Tx Status Reg for Packet Index 2 */
-+#define       SR_TSR2         0x04
-+#define               TSR2_EC                 (1 << 2)
-+#define               TSR2_COL                (1 << 3)
-+#define               TSR2_LC                 (1 << 4)
-+#define               TSR2_NC                 (1 << 5)
-+#define               TSR2_LOC                (1 << 6)
-+#define               TSR2_TLF                (1 << 7)
-+/* Rx Control Reg*/
-+#define       SR_RCR                  0x05
-+#define               RCR_RXEN                (1 << 0)
-+#define               RCR_PRMSC               (1 << 1)
-+#define               RCR_RUNT                (1 << 2)
-+#define               RCR_ALL                 (1 << 3)
-+#define               RCR_DIS_CRC             (1 << 4)
-+#define               RCR_DIS_LONG    (1 << 5)
-+/* Rx Status Reg */
-+#define       SR_RSR                  0x06
-+#define               RSR_AE                  (1 << 2)
-+#define               RSR_MF                  (1 << 6)
-+#define               RSR_RF                  (1 << 7)
-+/* Rx Overflow Counter Reg */
-+#define       SR_ROCR         0x07
-+#define               ROCR_ROC                (0x7F << 0)
-+#define               ROCR_RXFU               (1 << 7)
-+/* Back Pressure Threshold Reg */
-+#define       SR_BPTR         0x08
-+#define               BPTR_JPT                (0x0F << 0)
-+#define               BPTR_BPHW               (0x0F << 4)
-+/* Flow Control Threshold Reg */
-+#define       SR_FCTR         0x09
-+#define               FCTR_LWOT               (0x0F << 0)
-+#define               FCTR_HWOT               (0x0F << 4)
-+/* rx/tx Flow Control Reg */
-+#define       SR_FCR                  0x0A
-+#define               FCR_FLCE                (1 << 0)
-+#define               FCR_BKPA                (1 << 4)
-+#define               FCR_TXPEN               (1 << 5)
-+#define               FCR_TXPF                (1 << 6)
-+#define               FCR_TXP0                (1 << 7)
-+/* Eeprom & Phy Control Reg */
-+#define       SR_EPCR         0x0B
-+#define               EPCR_ERRE               (1 << 0)
-+#define               EPCR_ERPRW              (1 << 1)
-+#define               EPCR_ERPRR              (1 << 2)
-+#define               EPCR_EPOS               (1 << 3)
-+#define               EPCR_WEP                (1 << 4)
-+/* Eeprom & Phy Address Reg */
-+#define       SR_EPAR         0x0C
-+#define               EPAR_EROA               (0x3F << 0)
-+#define               EPAR_PHY_ADR_MASK       (0x03 << 6)
-+#define               EPAR_PHY_ADR            (0x01 << 6)
-+/* Eeprom &   Phy Data Reg */
-+#define       SR_EPDR         0x0D    /* 0x0D ~ 0x0E for Data Reg Low & High */
-+/* Wakeup Control Reg */
-+#define       SR_WCR                  0x0F
-+#define               WCR_MAGICST             (1 << 0)
-+#define               WCR_LINKST              (1 << 2)
-+#define               WCR_MAGICEN             (1 << 3)
-+#define               WCR_LINKEN              (1 << 5)
-+/* Physical Address Reg */
-+#define       SR_PAR                  0x10    /* 0x10 ~ 0x15 6 bytes for PAR */
-+/* Multicast Address Reg */
-+#define       SR_MAR                  0x16    /* 0x16 ~ 0x1D 8 bytes for MAR */
-+/* 0x1e unused */
-+/* Phy Reset Reg */
-+#define       SR_PRR                  0x1F
-+#define               PRR_PHY_RST             (1 << 0)
-+/* Tx sdram Write Pointer Address Low */
-+#define       SR_TWPAL                0x20
-+/* Tx sdram Write Pointer Address High */
-+#define       SR_TWPAH                0x21
-+/* Tx sdram Read Pointer Address Low */
-+#define       SR_TRPAL                0x22
-+/* Tx sdram Read Pointer Address High */
-+#define       SR_TRPAH                0x23
-+/* Rx sdram Write Pointer Address Low */
-+#define       SR_RWPAL                0x24
-+/* Rx sdram Write Pointer Address High */
-+#define       SR_RWPAH                0x25
-+/* Rx sdram Read Pointer Address Low */
-+#define       SR_RRPAL                0x26
-+/* Rx sdram Read Pointer Address High */
-+#define       SR_RRPAH                0x27
-+/* Vendor ID register */
-+#define       SR_VID                  0x28    /* 0x28 ~ 0x29 2 bytes for VID */
-+/* Product ID register */
-+#define       SR_PID                  0x2A    /* 0x2A ~ 0x2B 2 bytes for PID */
-+/* CHIP Revision register */
-+#define       SR_CHIPR                0x2C
-+/* 0x2D --> 0xEF unused */
-+/* USB Device Address */
-+#define       SR_USBDA                0xF0
-+#define               USBDA_USBFA             (0x7F << 0)
-+/* RX packet Counter Reg */
-+#define       SR_RXC                  0xF1
-+/* Tx packet Counter & USB Status Reg */
-+#define       SR_TXC_USBS             0xF2
-+#define               TXC_USBS_TXC0           (1 << 0)
-+#define               TXC_USBS_TXC1           (1 << 1)
-+#define               TXC_USBS_TXC2           (1 << 2)
-+#define               TXC_USBS_EP1RDY         (1 << 5)
-+#define               TXC_USBS_SUSFLAG        (1 << 6)
-+#define               TXC_USBS_RXFAULT        (1 << 7)
-+/* USB Control register */
-+#define       SR_USBC                 0xF4
-+#define               USBC_EP3NAK             (1 << 4)
-+#define               USBC_EP3ACK             (1 << 5)
-+
-+/* Register access commands and flags */
-+#define       SR_RD_REGS              0x00
-+#define       SR_WR_REGS              0x01
-+#define       SR_WR_REG               0x03
-+#define       SR_REQ_RD_REG   (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
-+#define       SR_REQ_WR_REG   (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
-+
-+/* parameters */
-+#define       SR_SHARE_TIMEOUT        1000
-+#define       SR_EEPROM_LEN           256
-+#define       SR_MCAST_SIZE           8
-+#define       SR_MCAST_ADDR_FLAG      0x80
-+#define       SR_MCAST_MAX            64
-+#define       SR_TX_OVERHEAD          2       /* 2bytes header */
-+#define       SR_RX_OVERHEAD          7       /* 3bytes header + 4crc tail */
-+
-+#endif        /* _SR9700_H */
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/sr9800.c backports-4.2.6-1/drivers/net/usb/sr9800.c
---- backports-4.2.6-1.org/drivers/net/usb/sr9800.c     1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/sr9800.c 2016-06-28 14:35:18.015307217 +0200
-@@ -0,0 +1,875 @@
-+/* CoreChip-sz SR9800 one chip USB 2.0 Ethernet Devices
-+ *
-+ * Author : Liu Junliang <liujunliang_ljl@163.com>
-+ *
-+ * Based on asix_common.c, asix_devices.c
-+ *
-+ * 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
-+ * kind, whether express or implied.*
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kmod.h>
-+#include <linux/init.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/workqueue.h>
-+#include <linux/mii.h>
-+#include <linux/usb.h>
-+#include <linux/crc32.h>
-+#include <linux/usb/usbnet.h>
-+#include <linux/slab.h>
-+#include <linux/if_vlan.h>
-+
-+#include "sr9800.h"
-+
-+static int sr_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-+                          u16 size, void *data)
-+{
-+      int err;
-+
-+      err = usbnet_read_cmd(dev, cmd, SR_REQ_RD_REG, value, index,
-+                            data, size);
-+      if ((err != size) && (err >= 0))
-+              err = -EINVAL;
-+
-+      return err;
-+}
-+
-+static int sr_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-+                           u16 size, void *data)
-+{
-+      int err;
-+
-+      err = usbnet_write_cmd(dev, cmd, SR_REQ_WR_REG, value, index,
-+                            data, size);
-+      if ((err != size) && (err >= 0))
-+              err = -EINVAL;
-+
-+      return err;
-+}
-+
-+static void
-+sr_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-+                 u16 size, void *data)
-+{
-+      usbnet_write_cmd_async(dev, cmd, SR_REQ_WR_REG, value, index, data,
-+                             size);
-+}
-+
-+static int sr_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-+{
-+      int offset = 0;
-+
-+      /* This check is no longer done by usbnet */
-+      if (skb->len < dev->net->hard_header_len)
-+              return 0;
-+
-+      while (offset + sizeof(u32) < skb->len) {
-+              struct sk_buff *sr_skb;
-+              u16 size;
-+              u32 header = get_unaligned_le32(skb->data + offset);
-+
-+              offset += sizeof(u32);
-+              /* get the packet length */
-+              size = (u16) (header & 0x7ff);
-+              if (size != ((~header >> 16) & 0x07ff)) {
-+                      netdev_err(dev->net, "%s : Bad Header Length\n",
-+                                 __func__);
-+                      return 0;
-+              }
-+
-+              if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) ||
-+                  (size + offset > skb->len)) {
-+                      netdev_err(dev->net, "%s : Bad RX Length %d\n",
-+                                 __func__, size);
-+                      return 0;
-+              }
-+              sr_skb = netdev_alloc_skb_ip_align(dev->net, size);
-+              if (!sr_skb)
-+                      return 0;
-+
-+              skb_put(sr_skb, size);
-+              memcpy(sr_skb->data, skb->data + offset, size);
-+              usbnet_skb_return(dev, sr_skb);
-+
-+              offset += (size + 1) & 0xfffe;
-+      }
-+
-+      if (skb->len != offset) {
-+              netdev_err(dev->net, "%s : Bad SKB Length %d\n", __func__,
-+                         skb->len);
-+              return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+static struct sk_buff *sr_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
-+                                      gfp_t flags)
-+{
-+      int headroom = skb_headroom(skb);
-+      int tailroom = skb_tailroom(skb);
-+      u32 padbytes = 0xffff0000;
-+      u32 packet_len;
-+      int padlen;
-+
-+      padlen = ((skb->len + 4) % (dev->maxpacket - 1)) ? 0 : 4;
-+
-+      if ((!skb_cloned(skb)) && ((headroom + tailroom) >= (4 + padlen))) {
-+              if ((headroom < 4) || (tailroom < padlen)) {
-+                      skb->data = memmove(skb->head + 4, skb->data,
-+                                          skb->len);
-+                      skb_set_tail_pointer(skb, skb->len);
-+              }
-+      } else {
-+              struct sk_buff *skb2;
-+              skb2 = skb_copy_expand(skb, 4, padlen, flags);
-+              dev_kfree_skb_any(skb);
-+              skb = skb2;
-+              if (!skb)
-+                      return NULL;
-+      }
-+
-+      skb_push(skb, 4);
-+      packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
-+      cpu_to_le32s(&packet_len);
-+      skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
-+
-+      if (padlen) {
-+              cpu_to_le32s(&padbytes);
-+              memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
-+              skb_put(skb, sizeof(padbytes));
-+      }
-+
-+      usbnet_set_skb_tx_stats(skb, 1, 0);
-+      return skb;
-+}
-+
-+static void sr_status(struct usbnet *dev, struct urb *urb)
-+{
-+      struct sr9800_int_data *event;
-+      int link;
-+
-+      if (urb->actual_length < 8)
-+              return;
-+
-+      event = urb->transfer_buffer;
-+      link = event->link & 0x01;
-+      if (netif_carrier_ok(dev->net) != link) {
-+              usbnet_link_change(dev, link, 1);
-+              netdev_dbg(dev->net, "Link Status is: %d\n", link);
-+      }
-+
-+      return;
-+}
-+
-+static inline int sr_set_sw_mii(struct usbnet *dev)
-+{
-+      int ret;
-+
-+      ret = sr_write_cmd(dev, SR_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
-+      if (ret < 0)
-+              netdev_err(dev->net, "Failed to enable software MII access\n");
-+      return ret;
-+}
-+
-+static inline int sr_set_hw_mii(struct usbnet *dev)
-+{
-+      int ret;
-+
-+      ret = sr_write_cmd(dev, SR_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
-+      if (ret < 0)
-+              netdev_err(dev->net, "Failed to enable hardware MII access\n");
-+      return ret;
-+}
-+
-+static inline int sr_get_phy_addr(struct usbnet *dev)
-+{
-+      u8 buf[2];
-+      int ret;
-+
-+      ret = sr_read_cmd(dev, SR_CMD_READ_PHY_ID, 0, 0, 2, buf);
-+      if (ret < 0) {
-+              netdev_err(dev->net, "%s : Error reading PHYID register:%02x\n",
-+                         __func__, ret);
-+              goto out;
-+      }
-+      netdev_dbg(dev->net, "%s : returning 0x%04x\n", __func__,
-+                 *((__le16 *)buf));
-+
-+      ret = buf[1];
-+
-+out:
-+      return ret;
-+}
-+
-+static int sr_sw_reset(struct usbnet *dev, u8 flags)
-+{
-+      int ret;
-+
-+      ret = sr_write_cmd(dev, SR_CMD_SW_RESET, flags, 0, 0, NULL);
-+      if (ret < 0)
-+              netdev_err(dev->net, "Failed to send software reset:%02x\n",
-+                         ret);
-+
-+      return ret;
-+}
-+
-+static u16 sr_read_rx_ctl(struct usbnet *dev)
-+{
-+      __le16 v;
-+      int ret;
-+
-+      ret = sr_read_cmd(dev, SR_CMD_READ_RX_CTL, 0, 0, 2, &v);
-+      if (ret < 0) {
-+              netdev_err(dev->net, "Error reading RX_CTL register:%02x\n",
-+                         ret);
-+              goto out;
-+      }
-+
-+      ret = le16_to_cpu(v);
-+out:
-+      return ret;
-+}
-+
-+static int sr_write_rx_ctl(struct usbnet *dev, u16 mode)
-+{
-+      int ret;
-+
-+      netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode);
-+      ret = sr_write_cmd(dev, SR_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
-+      if (ret < 0)
-+              netdev_err(dev->net,
-+                         "Failed to write RX_CTL mode to 0x%04x:%02x\n",
-+                         mode, ret);
-+
-+      return ret;
-+}
-+
-+static u16 sr_read_medium_status(struct usbnet *dev)
-+{
-+      __le16 v;
-+      int ret;
-+
-+      ret = sr_read_cmd(dev, SR_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v);
-+      if (ret < 0) {
-+              netdev_err(dev->net,
-+                         "Error reading Medium Status register:%02x\n", ret);
-+              return ret;     /* TODO: callers not checking for error ret */
-+      }
-+
-+      return le16_to_cpu(v);
-+}
-+
-+static int sr_write_medium_mode(struct usbnet *dev, u16 mode)
-+{
-+      int ret;
-+
-+      netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode);
-+      ret = sr_write_cmd(dev, SR_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
-+      if (ret < 0)
-+              netdev_err(dev->net,
-+                         "Failed to write Medium Mode mode to 0x%04x:%02x\n",
-+                         mode, ret);
-+      return ret;
-+}
-+
-+static int sr_write_gpio(struct usbnet *dev, u16 value, int sleep)
-+{
-+      int ret;
-+
-+      netdev_dbg(dev->net, "%s : value = 0x%04x\n", __func__, value);
-+      ret = sr_write_cmd(dev, SR_CMD_WRITE_GPIOS, value, 0, 0, NULL);
-+      if (ret < 0)
-+              netdev_err(dev->net, "Failed to write GPIO value 0x%04x:%02x\n",
-+                         value, ret);
-+      if (sleep)
-+              msleep(sleep);
-+
-+      return ret;
-+}
-+
-+/* SR9800 have a 16-bit RX_CTL value */
-+static void sr_set_multicast(struct net_device *net)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct sr_data *data = (struct sr_data *)&dev->data;
-+      u16 rx_ctl = SR_DEFAULT_RX_CTL;
-+
-+      if (net->flags & IFF_PROMISC) {
-+              rx_ctl |= SR_RX_CTL_PRO;
-+      } else if (net->flags & IFF_ALLMULTI ||
-+                 netdev_mc_count(net) > SR_MAX_MCAST) {
-+              rx_ctl |= SR_RX_CTL_AMALL;
-+      } else if (netdev_mc_empty(net)) {
-+              /* just broadcast and directed */
-+      } else {
-+              /* We use the 20 byte dev->data
-+               * for our 8 byte filter buffer
-+               * to avoid allocating memory that
-+               * is tricky to free later
-+               */
-+              struct netdev_hw_addr *ha;
-+              u32 crc_bits;
-+
-+              memset(data->multi_filter, 0, SR_MCAST_FILTER_SIZE);
-+
-+              /* Build the multicast hash filter. */
-+              netdev_for_each_mc_addr(ha, net) {
-+                      crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
-+                      data->multi_filter[crc_bits >> 3] |=
-+                          1 << (crc_bits & 7);
-+              }
-+
-+              sr_write_cmd_async(dev, SR_CMD_WRITE_MULTI_FILTER, 0, 0,
-+                                 SR_MCAST_FILTER_SIZE, data->multi_filter);
-+
-+              rx_ctl |= SR_RX_CTL_AM;
-+      }
-+
-+      sr_write_cmd_async(dev, SR_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
-+}
-+
-+static int sr_mdio_read(struct net_device *net, int phy_id, int loc)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      __le16 res;
-+
-+      mutex_lock(&dev->phy_mutex);
-+      sr_set_sw_mii(dev);
-+      sr_read_cmd(dev, SR_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, &res);
-+      sr_set_hw_mii(dev);
-+      mutex_unlock(&dev->phy_mutex);
-+
-+      netdev_dbg(dev->net,
-+                 "%s : phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", __func__,
-+                 phy_id, loc, le16_to_cpu(res));
-+
-+      return le16_to_cpu(res);
-+}
-+
-+static void
-+sr_mdio_write(struct net_device *net, int phy_id, int loc, int val)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      __le16 res = cpu_to_le16(val);
-+
-+      netdev_dbg(dev->net,
-+                 "%s : phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", __func__,
-+                 phy_id, loc, val);
-+      mutex_lock(&dev->phy_mutex);
-+      sr_set_sw_mii(dev);
-+      sr_write_cmd(dev, SR_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res);
-+      sr_set_hw_mii(dev);
-+      mutex_unlock(&dev->phy_mutex);
-+}
-+
-+/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
-+static u32 sr_get_phyid(struct usbnet *dev)
-+{
-+      int phy_reg;
-+      u32 phy_id;
-+      int i;
-+
-+      /* Poll for the rare case the FW or phy isn't ready yet.  */
-+      for (i = 0; i < 100; i++) {
-+              phy_reg = sr_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;
-+
-+      phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2);
-+      if (phy_reg < 0)
-+              return 0;
-+
-+      phy_id |= (phy_reg & 0xffff);
-+
-+      return phy_id;
-+}
-+
-+static void
-+sr_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      u8 opt;
-+
-+      if (sr_read_cmd(dev, SR_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
-+              wolinfo->supported = 0;
-+              wolinfo->wolopts = 0;
-+              return;
-+      }
-+      wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
-+      wolinfo->wolopts = 0;
-+      if (opt & SR_MONITOR_LINK)
-+              wolinfo->wolopts |= WAKE_PHY;
-+      if (opt & SR_MONITOR_MAGIC)
-+              wolinfo->wolopts |= WAKE_MAGIC;
-+}
-+
-+static int
-+sr_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      u8 opt = 0;
-+
-+      if (wolinfo->wolopts & WAKE_PHY)
-+              opt |= SR_MONITOR_LINK;
-+      if (wolinfo->wolopts & WAKE_MAGIC)
-+              opt |= SR_MONITOR_MAGIC;
-+
-+      if (sr_write_cmd(dev, SR_CMD_WRITE_MONITOR_MODE,
-+                       opt, 0, 0, NULL) < 0)
-+              return -EINVAL;
-+
-+      return 0;
-+}
-+
-+static int sr_get_eeprom_len(struct net_device *net)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct sr_data *data = (struct sr_data *)&dev->data;
-+
-+      return data->eeprom_len;
-+}
-+
-+static int sr_get_eeprom(struct net_device *net,
-+                            struct ethtool_eeprom *eeprom, u8 *data)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      __le16 *ebuf = (__le16 *)data;
-+      int ret;
-+      int i;
-+
-+      /* Crude hack to ensure that we don't overwrite memory
-+       * if an odd length is supplied
-+       */
-+      if (eeprom->len % 2)
-+              return -EINVAL;
-+
-+      eeprom->magic = SR_EEPROM_MAGIC;
-+
-+      /* sr9800 returns 2 bytes from eeprom on read */
-+      for (i = 0; i < eeprom->len / 2; i++) {
-+              ret = sr_read_cmd(dev, SR_CMD_READ_EEPROM, eeprom->offset + i,
-+                                0, 2, &ebuf[i]);
-+              if (ret < 0)
-+                      return -EINVAL;
-+      }
-+      return 0;
-+}
-+
-+static void sr_get_drvinfo(struct net_device *net,
-+                               struct ethtool_drvinfo *info)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct sr_data *data = (struct sr_data *)&dev->data;
-+
-+      /* Inherit standard device info */
-+      usbnet_get_drvinfo(net, info);
-+      strncpy(info->driver, DRIVER_NAME, sizeof(info->driver));
-+      strncpy(info->version, DRIVER_VERSION, sizeof(info->version));
-+      info->eedump_len = data->eeprom_len;
-+}
-+
-+static u32 sr_get_link(struct net_device *net)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+
-+      return mii_link_ok(&dev->mii);
-+}
-+
-+static int sr_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+
-+      return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
-+}
-+
-+static int sr_set_mac_address(struct net_device *net, void *p)
-+{
-+      struct usbnet *dev = netdev_priv(net);
-+      struct sr_data *data = (struct sr_data *)&dev->data;
-+      struct sockaddr *addr = p;
-+
-+      if (netif_running(net))
-+              return -EBUSY;
-+      if (!is_valid_ether_addr(addr->sa_data))
-+              return -EADDRNOTAVAIL;
-+
-+      memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
-+
-+      /* We use the 20 byte dev->data
-+       * for our 6 byte mac buffer
-+       * to avoid allocating memory that
-+       * is tricky to free later
-+       */
-+      memcpy(data->mac_addr, addr->sa_data, ETH_ALEN);
-+      sr_write_cmd_async(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
-+                         data->mac_addr);
-+
-+      return 0;
-+}
-+
-+static const struct ethtool_ops sr9800_ethtool_ops = {
-+      .get_drvinfo    = sr_get_drvinfo,
-+      .get_link       = sr_get_link,
-+      .get_msglevel   = usbnet_get_msglevel,
-+      .set_msglevel   = usbnet_set_msglevel,
-+      .get_wol        = sr_get_wol,
-+      .set_wol        = sr_set_wol,
-+      .get_eeprom_len = sr_get_eeprom_len,
-+      .get_eeprom     = sr_get_eeprom,
-+      .get_settings   = usbnet_get_settings,
-+      .set_settings   = usbnet_set_settings,
-+      .nway_reset     = usbnet_nway_reset,
-+};
-+
-+static int sr9800_link_reset(struct usbnet *dev)
-+{
-+      struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
-+      u16 mode;
-+
-+      mii_check_media(&dev->mii, 1, 1);
-+      mii_ethtool_gset(&dev->mii, &ecmd);
-+      mode = SR9800_MEDIUM_DEFAULT;
-+
-+      if (ethtool_cmd_speed(&ecmd) != SPEED_100)
-+              mode &= ~SR_MEDIUM_PS;
-+
-+      if (ecmd.duplex != DUPLEX_FULL)
-+              mode &= ~SR_MEDIUM_FD;
-+
-+      netdev_dbg(dev->net, "%s : speed: %u duplex: %d mode: 0x%04x\n",
-+                 __func__, ethtool_cmd_speed(&ecmd), ecmd.duplex, mode);
-+
-+      sr_write_medium_mode(dev, mode);
-+
-+      return 0;
-+}
-+
-+
-+static int sr9800_set_default_mode(struct usbnet *dev)
-+{
-+      u16 rx_ctl;
-+      int ret;
-+
-+      sr_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-+      sr_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
-+                    ADVERTISE_ALL | ADVERTISE_CSMA);
-+      mii_nway_restart(&dev->mii);
-+
-+      ret = sr_write_medium_mode(dev, SR9800_MEDIUM_DEFAULT);
-+      if (ret < 0)
-+              goto out;
-+
-+      ret = sr_write_cmd(dev, SR_CMD_WRITE_IPG012,
-+                              SR9800_IPG0_DEFAULT | SR9800_IPG1_DEFAULT,
-+                              SR9800_IPG2_DEFAULT, 0, NULL);
-+      if (ret < 0) {
-+              netdev_dbg(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret);
-+              goto out;
-+      }
-+
-+      /* Set RX_CTL to default values with 2k buffer, and enable cactus */
-+      ret = sr_write_rx_ctl(dev, SR_DEFAULT_RX_CTL);
-+      if (ret < 0)
-+              goto out;
-+
-+      rx_ctl = sr_read_rx_ctl(dev);
-+      netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n",
-+                 rx_ctl);
-+
-+      rx_ctl = sr_read_medium_status(dev);
-+      netdev_dbg(dev->net, "Medium Status:0x%04x after all initializations\n",
-+                 rx_ctl);
-+
-+      return 0;
-+out:
-+      return ret;
-+}
-+
-+static int sr9800_reset(struct usbnet *dev)
-+{
-+      struct sr_data *data = (struct sr_data *)&dev->data;
-+      int ret, embd_phy;
-+      u16 rx_ctl;
-+
-+      ret = sr_write_gpio(dev,
-+                      SR_GPIO_RSE | SR_GPIO_GPO_2 | SR_GPIO_GPO2EN, 5);
-+      if (ret < 0)
-+              goto out;
-+
-+      embd_phy = ((sr_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
-+
-+      ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
-+      if (ret < 0) {
-+              netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
-+              goto out;
-+      }
-+
-+      ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_PRL);
-+      if (ret < 0)
-+              goto out;
-+
-+      msleep(150);
-+
-+      ret = sr_sw_reset(dev, SR_SWRESET_CLEAR);
-+      if (ret < 0)
-+              goto out;
-+
-+      msleep(150);
-+
-+      if (embd_phy) {
-+              ret = sr_sw_reset(dev, SR_SWRESET_IPRL);
-+              if (ret < 0)
-+                      goto out;
-+      } else {
-+              ret = sr_sw_reset(dev, SR_SWRESET_PRTE);
-+              if (ret < 0)
-+                      goto out;
-+      }
-+
-+      msleep(150);
-+      rx_ctl = sr_read_rx_ctl(dev);
-+      netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl);
-+      ret = sr_write_rx_ctl(dev, 0x0000);
-+      if (ret < 0)
-+              goto out;
-+
-+      rx_ctl = sr_read_rx_ctl(dev);
-+      netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
-+
-+      ret = sr_sw_reset(dev, SR_SWRESET_PRL);
-+      if (ret < 0)
-+              goto out;
-+
-+      msleep(150);
-+
-+      ret = sr_sw_reset(dev, SR_SWRESET_IPRL | SR_SWRESET_PRL);
-+      if (ret < 0)
-+              goto out;
-+
-+      msleep(150);
-+
-+      ret = sr9800_set_default_mode(dev);
-+      if (ret < 0)
-+              goto out;
-+
-+      /* Rewrite MAC address */
-+      memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN);
-+      ret = sr_write_cmd(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
-+                                                      data->mac_addr);
-+      if (ret < 0)
-+              goto out;
-+
-+      return 0;
-+
-+out:
-+      return ret;
-+}
-+
-+static const struct net_device_ops sr9800_netdev_ops = {
-+      .ndo_open               = usbnet_open,
-+      .ndo_stop               = usbnet_stop,
-+      .ndo_start_xmit         = usbnet_start_xmit,
-+      .ndo_tx_timeout         = usbnet_tx_timeout,
-+      .ndo_change_mtu         = usbnet_change_mtu,
-+      .ndo_set_mac_address    = sr_set_mac_address,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_do_ioctl           = sr_ioctl,
-+      .ndo_set_rx_mode        = sr_set_multicast,
-+};
-+
-+static int sr9800_phy_powerup(struct usbnet *dev)
-+{
-+      int ret;
-+
-+      /* set the embedded Ethernet PHY in power-down state */
-+      ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_IPRL);
-+      if (ret < 0) {
-+              netdev_err(dev->net, "Failed to power down PHY : %d\n", ret);
-+              return ret;
-+      }
-+      msleep(20);
-+
-+      /* set the embedded Ethernet PHY in power-up state */
-+      ret = sr_sw_reset(dev, SR_SWRESET_IPRL);
-+      if (ret < 0) {
-+              netdev_err(dev->net, "Failed to reset PHY: %d\n", ret);
-+              return ret;
-+      }
-+      msleep(600);
-+
-+      /* set the embedded Ethernet PHY in reset state */
-+      ret = sr_sw_reset(dev, SR_SWRESET_CLEAR);
-+      if (ret < 0) {
-+              netdev_err(dev->net, "Failed to power up PHY: %d\n", ret);
-+              return ret;
-+      }
-+      msleep(20);
-+
-+      /* set the embedded Ethernet PHY in power-up state */
-+      ret = sr_sw_reset(dev, SR_SWRESET_IPRL);
-+      if (ret < 0) {
-+              netdev_err(dev->net, "Failed to reset PHY: %d\n", ret);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static int sr9800_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      struct sr_data *data = (struct sr_data *)&dev->data;
-+      u16 led01_mux, led23_mux;
-+      int ret, embd_phy;
-+      u32 phyid;
-+      u16 rx_ctl;
-+
-+      data->eeprom_len = SR9800_EEPROM_LEN;
-+
-+      usbnet_get_endpoints(dev, intf);
-+
-+      /* LED Setting Rule :
-+       * AABB:CCDD
-+       * AA : MFA0(LED0)
-+       * BB : MFA1(LED1)
-+       * CC : MFA2(LED2), Reserved for SR9800
-+       * DD : MFA3(LED3), Reserved for SR9800
-+       */
-+      led01_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_LINK;
-+      led23_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_TX_ACTIVE;
-+      ret = sr_write_cmd(dev, SR_CMD_LED_MUX, led01_mux, led23_mux, 0, NULL);
-+      if (ret < 0) {
-+                      netdev_err(dev->net, "set LINK LED failed : %d\n", ret);
-+                      goto out;
-+      }
-+
-+      /* Get the MAC address */
-+      ret = sr_read_cmd(dev, SR_CMD_READ_NODE_ID, 0, 0, ETH_ALEN,
-+                        dev->net->dev_addr);
-+      if (ret < 0) {
-+              netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
-+              return ret;
-+      }
-+      netdev_dbg(dev->net, "mac addr : %pM\n", dev->net->dev_addr);
-+
-+      /* Initialize MII structure */
-+      dev->mii.dev = dev->net;
-+      dev->mii.mdio_read = sr_mdio_read;
-+      dev->mii.mdio_write = sr_mdio_write;
-+      dev->mii.phy_id_mask = 0x1f;
-+      dev->mii.reg_num_mask = 0x1f;
-+      dev->mii.phy_id = sr_get_phy_addr(dev);
-+
-+      dev->net->netdev_ops = &sr9800_netdev_ops;
-+      dev->net->ethtool_ops = &sr9800_ethtool_ops;
-+
-+      embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0);
-+      /* Reset the PHY to normal operation mode */
-+      ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
-+      if (ret < 0) {
-+              netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
-+              return ret;
-+      }
-+
-+      /* Init PHY routine */
-+      ret = sr9800_phy_powerup(dev);
-+      if (ret < 0)
-+              goto out;
-+
-+      rx_ctl = sr_read_rx_ctl(dev);
-+      netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl);
-+      ret = sr_write_rx_ctl(dev, 0x0000);
-+      if (ret < 0)
-+              goto out;
-+
-+      rx_ctl = sr_read_rx_ctl(dev);
-+      netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
-+
-+      /* Read PHYID register *AFTER* the PHY was reset properly */
-+      phyid = sr_get_phyid(dev);
-+      netdev_dbg(dev->net, "PHYID=0x%08x\n", phyid);
-+
-+      /* medium mode setting */
-+      ret = sr9800_set_default_mode(dev);
-+      if (ret < 0)
-+              goto out;
-+
-+      if (dev->udev->speed == USB_SPEED_HIGH) {
-+              ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE,
-+                      SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].byte_cnt,
-+                      SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].threshold,
-+                      0, NULL);
-+              if (ret < 0) {
-+                      netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret);
-+                      goto out;
-+              }
-+              dev->rx_urb_size =
-+                      SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].size;
-+      } else {
-+              ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE,
-+                      SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].byte_cnt,
-+                      SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].threshold,
-+                      0, NULL);
-+              if (ret < 0) {
-+                      netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret);
-+                      goto out;
-+              }
-+              dev->rx_urb_size =
-+                      SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].size;
-+      }
-+      netdev_dbg(dev->net, "%s : setting rx_urb_size with : %zu\n", __func__,
-+                 dev->rx_urb_size);
-+      return 0;
-+
-+out:
-+      return ret;
-+}
-+
-+static const struct driver_info sr9800_driver_info = {
-+      .description    = "CoreChip SR9800 USB 2.0 Ethernet",
-+      .bind           = sr9800_bind,
-+      .status         = sr_status,
-+      .link_reset     = sr9800_link_reset,
-+      .reset          = sr9800_reset,
-+      .flags          = DRIVER_FLAG,
-+      .rx_fixup       = sr_rx_fixup,
-+      .tx_fixup       = sr_tx_fixup,
-+};
-+
-+static const struct usb_device_id     products[] = {
-+      {
-+              USB_DEVICE(0x0fe6, 0x9800),     /* SR9800 Device  */
-+              .driver_info = (unsigned long) &sr9800_driver_info,
-+      },
-+      {},             /* END */
-+};
-+
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver sr_driver = {
-+      .name           = DRIVER_NAME,
-+      .id_table       = products,
-+      .probe          = usbnet_probe,
-+      .suspend        = usbnet_suspend,
-+      .resume         = usbnet_resume,
-+      .disconnect     = usbnet_disconnect,
-+      .supports_autosuspend = 1,
-+};
-+
-+module_usb_driver(sr_driver);
-+
-+MODULE_AUTHOR("Liu Junliang <liujunliang_ljl@163.com");
-+MODULE_VERSION(DRIVER_VERSION);
-+MODULE_DESCRIPTION("SR9800 USB 2.0 USB2NET Dev : http://www.corechip-sz.com");
-+MODULE_LICENSE("GPL");
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/sr9800.h backports-4.2.6-1/drivers/net/usb/sr9800.h
---- backports-4.2.6-1.org/drivers/net/usb/sr9800.h     1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/sr9800.h 2016-06-28 14:35:18.015307217 +0200
-@@ -0,0 +1,202 @@
-+/* CoreChip-sz SR9800 one chip USB 2.0 Ethernet Devices
-+ *
-+ * Author : Liu Junliang <liujunliang_ljl@163.com>
-+ *
-+ * 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
-+ * kind, whether express or implied.
-+ */
-+
-+#ifndef       _SR9800_H
-+#define       _SR9800_H
-+
-+/* SR9800 spec. command table on Linux Platform */
-+
-+/* command : Software Station Management Control Reg */
-+#define SR_CMD_SET_SW_MII             0x06
-+/* command : PHY Read Reg */
-+#define SR_CMD_READ_MII_REG           0x07
-+/* command : PHY Write Reg */
-+#define SR_CMD_WRITE_MII_REG          0x08
-+/* command : Hardware Station Management Control Reg */
-+#define SR_CMD_SET_HW_MII             0x0a
-+/* command : SROM Read Reg */
-+#define SR_CMD_READ_EEPROM            0x0b
-+/* command : SROM Write Reg */
-+#define SR_CMD_WRITE_EEPROM           0x0c
-+/* command : SROM Write Enable Reg */
-+#define SR_CMD_WRITE_ENABLE           0x0d
-+/* command : SROM Write Disable Reg */
-+#define SR_CMD_WRITE_DISABLE          0x0e
-+/* command : RX Control Read Reg */
-+#define SR_CMD_READ_RX_CTL            0x0f
-+#define               SR_RX_CTL_PRO                   (1 << 0)
-+#define               SR_RX_CTL_AMALL                 (1 << 1)
-+#define               SR_RX_CTL_SEP                   (1 << 2)
-+#define               SR_RX_CTL_AB                    (1 << 3)
-+#define               SR_RX_CTL_AM                    (1 << 4)
-+#define               SR_RX_CTL_AP                    (1 << 5)
-+#define               SR_RX_CTL_ARP                   (1 << 6)
-+#define               SR_RX_CTL_SO                    (1 << 7)
-+#define               SR_RX_CTL_RH1M                  (1 << 8)
-+#define               SR_RX_CTL_RH2M                  (1 << 9)
-+#define               SR_RX_CTL_RH3M                  (1 << 10)
-+/* command : RX Control Write Reg */
-+#define SR_CMD_WRITE_RX_CTL           0x10
-+/* command : IPG0/IPG1/IPG2 Control Read Reg */
-+#define SR_CMD_READ_IPG012            0x11
-+/* command : IPG0/IPG1/IPG2 Control Write Reg */
-+#define SR_CMD_WRITE_IPG012           0x12
-+/* command : Node ID Read Reg */
-+#define SR_CMD_READ_NODE_ID           0x13
-+/* command : Node ID Write Reg */
-+#define SR_CMD_WRITE_NODE_ID          0x14
-+/* command : Multicast Filter Array Read Reg */
-+#define       SR_CMD_READ_MULTI_FILTER        0x15
-+/* command : Multicast Filter Array Write Reg */
-+#define SR_CMD_WRITE_MULTI_FILTER     0x16
-+/* command : Eth/HomePNA PHY Address Reg */
-+#define SR_CMD_READ_PHY_ID            0x19
-+/* command : Medium Status Read Reg */
-+#define SR_CMD_READ_MEDIUM_STATUS     0x1a
-+#define               SR_MONITOR_LINK                 (1 << 1)
-+#define               SR_MONITOR_MAGIC                (1 << 2)
-+#define               SR_MONITOR_HSFS                 (1 << 4)
-+/* command : Medium Status Write Reg */
-+#define SR_CMD_WRITE_MEDIUM_MODE      0x1b
-+#define               SR_MEDIUM_GM                    (1 << 0)
-+#define               SR_MEDIUM_FD                    (1 << 1)
-+#define               SR_MEDIUM_AC                    (1 << 2)
-+#define               SR_MEDIUM_ENCK                  (1 << 3)
-+#define               SR_MEDIUM_RFC                   (1 << 4)
-+#define               SR_MEDIUM_TFC                   (1 << 5)
-+#define               SR_MEDIUM_JFE                   (1 << 6)
-+#define               SR_MEDIUM_PF                    (1 << 7)
-+#define               SR_MEDIUM_RE                    (1 << 8)
-+#define               SR_MEDIUM_PS                    (1 << 9)
-+#define               SR_MEDIUM_RSV                   (1 << 10)
-+#define               SR_MEDIUM_SBP                   (1 << 11)
-+#define               SR_MEDIUM_SM                    (1 << 12)
-+/* command : Monitor Mode Status Read Reg */
-+#define SR_CMD_READ_MONITOR_MODE      0x1c
-+/* command : Monitor Mode Status Write Reg */
-+#define SR_CMD_WRITE_MONITOR_MODE     0x1d
-+/* command : GPIO Status Read Reg */
-+#define SR_CMD_READ_GPIOS             0x1e
-+#define               SR_GPIO_GPO0EN          (1 << 0) /* GPIO0 Output enable */
-+#define               SR_GPIO_GPO_0           (1 << 1) /* GPIO0 Output value */
-+#define               SR_GPIO_GPO1EN          (1 << 2) /* GPIO1 Output enable */
-+#define               SR_GPIO_GPO_1           (1 << 3) /* GPIO1 Output value */
-+#define               SR_GPIO_GPO2EN          (1 << 4) /* GPIO2 Output enable */
-+#define               SR_GPIO_GPO_2           (1 << 5) /* GPIO2 Output value */
-+#define               SR_GPIO_RESERVED        (1 << 6) /* Reserved */
-+#define               SR_GPIO_RSE             (1 << 7) /* Reload serial EEPROM */
-+/* command : GPIO Status Write Reg */
-+#define SR_CMD_WRITE_GPIOS            0x1f
-+/* command : Eth PHY Power and Reset Control Reg */
-+#define SR_CMD_SW_RESET                       0x20
-+#define               SR_SWRESET_CLEAR                0x00
-+#define               SR_SWRESET_RR                   (1 << 0)
-+#define               SR_SWRESET_RT                   (1 << 1)
-+#define               SR_SWRESET_PRTE                 (1 << 2)
-+#define               SR_SWRESET_PRL                  (1 << 3)
-+#define               SR_SWRESET_BZ                   (1 << 4)
-+#define               SR_SWRESET_IPRL                 (1 << 5)
-+#define               SR_SWRESET_IPPD                 (1 << 6)
-+/* command : Software Interface Selection Status Read Reg */
-+#define SR_CMD_SW_PHY_STATUS          0x21
-+/* command : Software Interface Selection Status Write Reg */
-+#define SR_CMD_SW_PHY_SELECT          0x22
-+/* command : BULK in Buffer Size Reg */
-+#define       SR_CMD_BULKIN_SIZE              0x2A
-+/* command : LED_MUX Control Reg */
-+#define       SR_CMD_LED_MUX                  0x70
-+#define               SR_LED_MUX_TX_ACTIVE            (1 << 0)
-+#define               SR_LED_MUX_RX_ACTIVE            (1 << 1)
-+#define               SR_LED_MUX_COLLISION            (1 << 2)
-+#define               SR_LED_MUX_DUP_COL              (1 << 3)
-+#define               SR_LED_MUX_DUP                  (1 << 4)
-+#define               SR_LED_MUX_SPEED                (1 << 5)
-+#define               SR_LED_MUX_LINK_ACTIVE          (1 << 6)
-+#define               SR_LED_MUX_LINK                 (1 << 7)
-+
-+/* Register Access Flags */
-+#define SR_REQ_RD_REG   (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
-+#define SR_REQ_WR_REG   (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
-+
-+/* Multicast Filter Array size & Max Number */
-+#define       SR_MCAST_FILTER_SIZE            8
-+#define       SR_MAX_MCAST                    64
-+
-+/* IPG0/1/2 Default Value */
-+#define       SR9800_IPG0_DEFAULT             0x15
-+#define       SR9800_IPG1_DEFAULT             0x0c
-+#define       SR9800_IPG2_DEFAULT             0x12
-+
-+/* Medium Status Default Mode */
-+#define SR9800_MEDIUM_DEFAULT \
-+      (SR_MEDIUM_FD | SR_MEDIUM_RFC | \
-+       SR_MEDIUM_TFC | SR_MEDIUM_PS | \
-+       SR_MEDIUM_AC | SR_MEDIUM_RE)
-+
-+/* RX Control Default Setting */
-+#define SR_DEFAULT_RX_CTL     \
-+      (SR_RX_CTL_SO | SR_RX_CTL_AB | SR_RX_CTL_RH1M)
-+
-+/* EEPROM Magic Number & EEPROM Size */
-+#define SR_EEPROM_MAGIC                       0xdeadbeef
-+#define SR9800_EEPROM_LEN             0xff
-+
-+/* SR9800 Driver Version and Driver Name */
-+#define DRIVER_VERSION                        "11-Nov-2013"
-+#define DRIVER_NAME                   "CoreChips"
-+#define       DRIVER_FLAG             \
-+      (FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |  FLAG_MULTI_PACKET)
-+
-+/* SR9800 BULKIN Buffer Size */
-+#define SR9800_MAX_BULKIN_2K          0
-+#define SR9800_MAX_BULKIN_4K          1
-+#define SR9800_MAX_BULKIN_6K          2
-+#define SR9800_MAX_BULKIN_8K          3
-+#define SR9800_MAX_BULKIN_16K         4
-+#define SR9800_MAX_BULKIN_20K         5
-+#define SR9800_MAX_BULKIN_24K         6
-+#define SR9800_MAX_BULKIN_32K         7
-+
-+struct {unsigned short size, byte_cnt, threshold; } SR9800_BULKIN_SIZE[] = {
-+      /* 2k */
-+      {2048, 0x8000, 0x8001},
-+      /* 4k */
-+      {4096, 0x8100, 0x8147},
-+      /* 6k */
-+      {6144, 0x8200, 0x81EB},
-+      /* 8k */
-+      {8192, 0x8300, 0x83D7},
-+      /* 16 */
-+      {16384, 0x8400, 0x851E},
-+      /* 20k */
-+      {20480, 0x8500, 0x8666},
-+      /* 24k */
-+      {24576, 0x8600, 0x87AE},
-+      /* 32k */
-+      {32768, 0x8700, 0x8A3D},
-+};
-+
-+/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
-+struct sr_data {
-+      u8 multi_filter[SR_MCAST_FILTER_SIZE];
-+      u8 mac_addr[ETH_ALEN];
-+      u8 phymode;
-+      u8 ledmode;
-+      u8 eeprom_len;
-+};
-+
-+struct sr9800_int_data {
-+      __le16 res1;
-+      u8 link;
-+      __le16 res2;
-+      u8 status;
-+      __le16 res3;
-+} __packed;
-+
-+#endif        /* _SR9800_H */
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/zaurus.c backports-4.2.6-1/drivers/net/usb/zaurus.c
---- backports-4.2.6-1.org/drivers/net/usb/zaurus.c     1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/zaurus.c 2016-06-28 14:35:18.015307217 +0200
-@@ -0,0 +1,385 @@
-+/*
-+ * Copyright (C) 2002 Pavel Machek <pavel@ucw.cz>
-+ * Copyright (C) 2002-2005 by David Brownell
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+// #define    DEBUG                   // error path messages, extra info
-+// #define    VERBOSE                 // more; success messages
-+
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/workqueue.h>
-+#include <linux/mii.h>
-+#include <linux/crc32.h>
-+#include <linux/usb.h>
-+#include <linux/usb/cdc.h>
-+#include <linux/usb/usbnet.h>
-+
-+
-+/*
-+ * All known Zaurii lie about their standards conformance.  At least
-+ * the earliest SA-1100 models lie by saying they support CDC Ethernet.
-+ * Some later models (especially PXA-25x and PXA-27x based ones) lie
-+ * and say they support CDC MDLM (for access to cell phone modems).
-+ *
-+ * There are non-Zaurus products that use these same protocols too.
-+ *
-+ * The annoying thing is that at the same time Sharp was developing
-+ * that annoying standards-breaking software, the Linux community had
-+ * a simple "CDC Subset" working reliably on the same SA-1100 hardware.
-+ * That is, the same functionality but not violating standards.
-+ *
-+ * The CDC Ethernet nonconformance points are troublesome to hosts
-+ * with a true CDC Ethernet implementation:
-+ *   - Framing appends a CRC, which the spec says drivers "must not" do;
-+ *   - Transfers data in altsetting zero, instead of altsetting 1;
-+ *   - All these peripherals use the same ethernet address.
-+ *
-+ * The CDC MDLM nonconformance is less immediately troublesome, since all
-+ * MDLM implementations are quasi-proprietary anyway.
-+ */
-+
-+static struct sk_buff *
-+zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
-+{
-+      int                     padlen;
-+      struct sk_buff          *skb2;
-+
-+      padlen = 2;
-+      if (!skb_cloned(skb)) {
-+              int     tailroom = skb_tailroom(skb);
-+              if ((padlen + 4) <= tailroom)
-+                      goto done;
-+      }
-+      skb2 = skb_copy_expand(skb, 0, 4 + padlen, flags);
-+      dev_kfree_skb_any(skb);
-+      skb = skb2;
-+      if (skb) {
-+              u32             fcs;
-+done:
-+              fcs = crc32_le(~0, skb->data, skb->len);
-+              fcs = ~fcs;
-+
-+              *skb_put (skb, 1) = fcs       & 0xff;
-+              *skb_put (skb, 1) = (fcs>> 8) & 0xff;
-+              *skb_put (skb, 1) = (fcs>>16) & 0xff;
-+              *skb_put (skb, 1) = (fcs>>24) & 0xff;
-+      }
-+      return skb;
-+}
-+
-+static int zaurus_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      /* Belcarra's funky framing has other options; mostly
-+       * TRAILERS (!) with 4 bytes CRC, and maybe 2 pad bytes.
-+       */
-+      dev->net->hard_header_len += 6;
-+      dev->rx_urb_size = dev->net->hard_header_len + dev->net->mtu;
-+      return usbnet_generic_cdc_bind(dev, intf);
-+}
-+
-+/* PDA style devices are always connected if present */
-+static int always_connected (struct usbnet *dev)
-+{
-+      return 0;
-+}
-+
-+static const struct driver_info       zaurus_sl5x00_info = {
-+      .description =  "Sharp Zaurus SL-5x00",
-+      .flags =        FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
-+      .check_connect = always_connected,
-+      .bind =         zaurus_bind,
-+      .unbind =       usbnet_cdc_unbind,
-+      .tx_fixup =     zaurus_tx_fixup,
-+};
-+#define       ZAURUS_STRONGARM_INFO   ((unsigned long)&zaurus_sl5x00_info)
-+
-+static const struct driver_info       zaurus_pxa_info = {
-+      .description =  "Sharp Zaurus, PXA-2xx based",
-+      .flags =        FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
-+      .check_connect = always_connected,
-+      .bind =         zaurus_bind,
-+      .unbind =       usbnet_cdc_unbind,
-+      .tx_fixup =     zaurus_tx_fixup,
-+};
-+#define       ZAURUS_PXA_INFO         ((unsigned long)&zaurus_pxa_info)
-+
-+static const struct driver_info       olympus_mxl_info = {
-+      .description =  "Olympus R1000",
-+      .flags =        FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
-+      .check_connect = always_connected,
-+      .bind =         zaurus_bind,
-+      .unbind =       usbnet_cdc_unbind,
-+      .tx_fixup =     zaurus_tx_fixup,
-+};
-+#define       OLYMPUS_MXL_INFO        ((unsigned long)&olympus_mxl_info)
-+
-+
-+/* Some more recent products using Lineo/Belcarra code will wrongly claim
-+ * CDC MDLM conformance.  They aren't conformant:  data endpoints live
-+ * in the control interface, there's no data interface, and it's not used
-+ * to talk to a cell phone radio.  But at least we can detect these two
-+ * pseudo-classes, rather than growing this product list with entries for
-+ * each new nonconformant product (sigh).
-+ */
-+static const u8 safe_guid[16] = {
-+      0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
-+      0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
-+};
-+static const u8 blan_guid[16] = {
-+      0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70,
-+      0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37,
-+};
-+
-+static int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf)
-+{
-+      u8                              *buf = intf->cur_altsetting->extra;
-+      int                             len = intf->cur_altsetting->extralen;
-+      struct usb_cdc_mdlm_desc        *desc = NULL;
-+      struct usb_cdc_mdlm_detail_desc *detail = NULL;
-+
-+      while (len > 3) {
-+              if (buf [1] != USB_DT_CS_INTERFACE)
-+                      goto next_desc;
-+
-+              /* use bDescriptorSubType, and just verify that we get a
-+               * "BLAN" (or "SAFE") descriptor.
-+               */
-+              switch (buf [2]) {
-+              case USB_CDC_MDLM_TYPE:
-+                      if (desc) {
-+                              dev_dbg(&intf->dev, "extra MDLM\n");
-+                              goto bad_desc;
-+                      }
-+                      desc = (void *) buf;
-+                      if (desc->bLength != sizeof *desc) {
-+                              dev_dbg(&intf->dev, "MDLM len %u\n",
-+                                      desc->bLength);
-+                              goto bad_desc;
-+                      }
-+                      /* expect bcdVersion 1.0, ignore */
-+                      if (memcmp(&desc->bGUID, blan_guid, 16) &&
-+                          memcmp(&desc->bGUID, safe_guid, 16)) {
-+                              /* hey, this one might _really_ be MDLM! */
-+                              dev_dbg(&intf->dev, "MDLM guid\n");
-+                              goto bad_desc;
-+                      }
-+                      break;
-+              case USB_CDC_MDLM_DETAIL_TYPE:
-+                      if (detail) {
-+                              dev_dbg(&intf->dev, "extra MDLM detail\n");
-+                              goto bad_desc;
-+                      }
-+                      detail = (void *) buf;
-+                      switch (detail->bGuidDescriptorType) {
-+                      case 0:                 /* "SAFE" */
-+                              if (detail->bLength != (sizeof *detail + 2))
-+                                      goto bad_detail;
-+                              break;
-+                      case 1:                 /* "BLAN" */
-+                              if (detail->bLength != (sizeof *detail + 3))
-+                                      goto bad_detail;
-+                              break;
-+                      default:
-+                              goto bad_detail;
-+                      }
-+
-+                      /* assuming we either noticed BLAN already, or will
-+                       * find it soon, there are some data bytes here:
-+                       *  - bmNetworkCapabilities (unused)
-+                       *  - bmDataCapabilities (bits, see below)
-+                       *  - bPad (ignored, for PADAFTER -- BLAN-only)
-+                       * bits are:
-+                       *  - 0x01 -- Zaurus framing (add CRC)
-+                       *  - 0x02 -- PADBEFORE (CRC includes some padding)
-+                       *  - 0x04 -- PADAFTER (some padding after CRC)
-+                       *  - 0x08 -- "fermat" packet mangling (for hw bugs)
-+                       * the PADBEFORE appears not to matter; we interop
-+                       * with devices that use it and those that don't.
-+                       */
-+                      if ((detail->bDetailData[1] & ~0x02) != 0x01) {
-+                              /* bmDataCapabilities == 0 would be fine too,
-+                               * but framing is minidriver-coupled for now.
-+                               */
-+bad_detail:
-+                              dev_dbg(&intf->dev,
-+                                              "bad MDLM detail, %d %d %d\n",
-+                                              detail->bLength,
-+                                              detail->bDetailData[0],
-+                                              detail->bDetailData[2]);
-+                              goto bad_desc;
-+                      }
-+
-+                      /* same extra framing as for non-BLAN mode */
-+                      dev->net->hard_header_len += 6;
-+                      dev->rx_urb_size = dev->net->hard_header_len
-+                                      + dev->net->mtu;
-+                      break;
-+              }
-+next_desc:
-+              len -= buf [0]; /* bLength */
-+              buf += buf [0];
-+      }
-+
-+      if (!desc || !detail) {
-+              dev_dbg(&intf->dev, "missing cdc mdlm %s%sdescriptor\n",
-+                      desc ? "" : "func ",
-+                      detail ? "" : "detail ");
-+              goto bad_desc;
-+      }
-+
-+      /* There's probably a CDC Ethernet descriptor there, but we can't
-+       * rely on the Ethernet address it provides since not all vendors
-+       * bother to make it unique.  Likewise there's no point in tracking
-+       * of the CDC event notifications.
-+       */
-+      return usbnet_get_endpoints(dev, intf);
-+
-+bad_desc:
-+      dev_info(&dev->udev->dev, "unsupported MDLM descriptors\n");
-+      return -ENODEV;
-+}
-+
-+static const struct driver_info       bogus_mdlm_info = {
-+      .description =  "pseudo-MDLM (BLAN) device",
-+      .flags =        FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
-+      .check_connect = always_connected,
-+      .tx_fixup =     zaurus_tx_fixup,
-+      .bind =         blan_mdlm_bind,
-+};
-+
-+static const struct usb_device_id     products [] = {
-+#define       ZAURUS_MASTER_INTERFACE \
-+      .bInterfaceClass        = USB_CLASS_COMM, \
-+      .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET, \
-+      .bInterfaceProtocol     = USB_CDC_PROTO_NONE
-+
-+/* SA-1100 based Sharp Zaurus ("collie"), or compatible. */
-+{
-+      .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-+                        | USB_DEVICE_ID_MATCH_DEVICE,
-+      .idVendor               = 0x04DD,
-+      .idProduct              = 0x8004,
-+      ZAURUS_MASTER_INTERFACE,
-+      .driver_info = ZAURUS_STRONGARM_INFO,
-+},
-+
-+/* PXA-2xx based models are also lying-about-cdc.  If you add any
-+ * more devices that claim to be CDC Ethernet, make sure they get
-+ * added to the blacklist in cdc_ether too.
-+ *
-+ * NOTE:  OpenZaurus versions with 2.6 kernels won't use these entries,
-+ * unlike the older ones with 2.4 "embedix" kernels.
-+ */
-+{
-+      .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-+                        | USB_DEVICE_ID_MATCH_DEVICE,
-+      .idVendor               = 0x04DD,
-+      .idProduct              = 0x8005,       /* A-300 */
-+      ZAURUS_MASTER_INTERFACE,
-+      .driver_info = ZAURUS_PXA_INFO,
-+}, {
-+      .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-+                        | USB_DEVICE_ID_MATCH_DEVICE,
-+      .idVendor               = 0x04DD,
-+      .idProduct              = 0x8006,       /* B-500/SL-5600 */
-+      ZAURUS_MASTER_INTERFACE,
-+      .driver_info = ZAURUS_PXA_INFO,
-+}, {
-+      .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-+                | USB_DEVICE_ID_MATCH_DEVICE,
-+      .idVendor               = 0x04DD,
-+      .idProduct              = 0x8007,       /* C-700 */
-+      ZAURUS_MASTER_INTERFACE,
-+      .driver_info = ZAURUS_PXA_INFO,
-+}, {
-+      .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-+               | USB_DEVICE_ID_MATCH_DEVICE,
-+      .idVendor               = 0x04DD,
-+      .idProduct              = 0x9031,       /* C-750 C-760 */
-+      ZAURUS_MASTER_INTERFACE,
-+      .driver_info = ZAURUS_PXA_INFO,
-+}, {
-+      /* C-750/C-760/C-860/SL-C3000 PDA in MDLM mode */
-+      USB_DEVICE_AND_INTERFACE_INFO(0x04DD, 0x9031, USB_CLASS_COMM,
-+                      USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-+      .driver_info = (unsigned long) &bogus_mdlm_info,
-+}, {
-+      .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-+               | USB_DEVICE_ID_MATCH_DEVICE,
-+      .idVendor               = 0x04DD,
-+      .idProduct              = 0x9032,       /* SL-6000 */
-+      ZAURUS_MASTER_INTERFACE,
-+      .driver_info = ZAURUS_PXA_INFO,
-+}, {
-+      .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-+               | USB_DEVICE_ID_MATCH_DEVICE,
-+      .idVendor               = 0x04DD,
-+      /* reported with some C860 units */
-+      .idProduct              = 0x9050,       /* C-860 */
-+      ZAURUS_MASTER_INTERFACE,
-+      .driver_info = ZAURUS_PXA_INFO,
-+},
-+{
-+      /* Motorola Rokr E6 */
-+      USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6027, USB_CLASS_COMM,
-+                      USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-+      .driver_info = (unsigned long) &bogus_mdlm_info,
-+}, {
-+      /* Motorola MOTOMAGX phones */
-+      USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM,
-+                      USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-+      .driver_info = (unsigned long) &bogus_mdlm_info,
-+},
-+
-+/* Olympus has some models with a Zaurus-compatible option.
-+ * R-1000 uses a FreeScale i.MXL cpu (ARMv4T)
-+ */
-+{
-+      .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-+               | USB_DEVICE_ID_MATCH_DEVICE,
-+      .idVendor               = 0x07B4,
-+      .idProduct              = 0x0F02,       /* R-1000 */
-+      ZAURUS_MASTER_INTERFACE,
-+      .driver_info = OLYMPUS_MXL_INFO,
-+},
-+
-+/* Logitech Harmony 900 - uses the pseudo-MDLM (BLAN) driver */
-+{
-+      USB_DEVICE_AND_INTERFACE_INFO(0x046d, 0xc11f, USB_CLASS_COMM,
-+                      USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
-+      .driver_info = (unsigned long) &bogus_mdlm_info,
-+},
-+      { },            // END
-+};
-+MODULE_DEVICE_TABLE(usb, products);
-+
-+static struct usb_driver zaurus_driver = {
-+      .name =         "zaurus",
-+      .id_table =     products,
-+      .probe =        usbnet_probe,
-+      .disconnect =   usbnet_disconnect,
-+      .suspend =      usbnet_suspend,
-+      .resume =       usbnet_resume,
-+      .disable_hub_initiated_lpm = 1,
-+};
-+
-+module_usb_driver(zaurus_driver);
-+
-+MODULE_AUTHOR("Pavel Machek, David Brownell");
-+MODULE_DESCRIPTION("Sharp Zaurus PDA, and compatible products");
-+MODULE_LICENSE("GPL");
diff --git a/src/patches/backports-4.2.6-1-ath9k_add_missing_mask_init.patch b/src/patches/backports-4.2.6-1-ath9k_add_missing_mask_init.patch
deleted file mode 100644 (file)
index 01aee6d..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-by moving common code to ar5008_hw_cmn_spur_mitigate i forgot to move
-mask_m & mask_p initialisation. This coused a performance regression
-on ar9281.
-
-
-Fixes: f911085ffa88 ("ath9k: split ar5008_hw_spur_mitigate and reuse common 
-code in ar9002_hw_spur_mitigate.")
-Reported-by: Gustav Frederiksen <lkml2...@openmailbox.org>
-Tested-by: Gustav Frederiksen <lkml2...@openmailbox.org>
-Signed-off-by: Oleksij Rempel <li...@rempel-privat.de>
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/ar5008_phy.c backports-4.2.6-1/drivers/net/wireless/ath/ath9k/ar5008_phy.c
---- backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/ar5008_phy.c  2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ath/ath9k/ar5008_phy.c      2016-04-25 09:37:58.765112541 +0200
-@@ -274,6 +274,9 @@
-       };
-       static const int inc[4] = { 0, 100, 0, 0 };
-+      memset(&mask_m, 0, sizeof(int8_t) * 123);
-+      memset(&mask_p, 0, sizeof(int8_t) * 123);
-+
-       cur_bin = -6000;
-       upper = bin + 100;
-       lower = bin - 100;
-@@ -424,14 +427,9 @@
-       int tmp, new;
-       int i;
--      int8_t mask_m[123];
--      int8_t mask_p[123];
-       int cur_bb_spur;
-       bool is2GHz = IS_CHAN_2GHZ(chan);
--      memset(&mask_m, 0, sizeof(int8_t) * 123);
--      memset(&mask_p, 0, sizeof(int8_t) * 123);
--
-       for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
-               cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
-               if (AR_NO_SPUR == cur_bb_spur)
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/ar9002_phy.c backports-4.2.6-1/drivers/net/wireless/ath/ath9k/ar9002_phy.c
---- backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/ar9002_phy.c  2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ath/ath9k/ar9002_phy.c      2016-04-25 09:38:57.729109148 +0200
-@@ -178,14 +178,9 @@
-       int i;
-       struct chan_centers centers;
--      int8_t mask_m[123];
--      int8_t mask_p[123];
-       int cur_bb_spur;
-       bool is2GHz = IS_CHAN_2GHZ(chan);
--      memset(&mask_m, 0, sizeof(int8_t) * 123);
--      memset(&mask_p, 0, sizeof(int8_t) * 123);
--
-       ath9k_hw_get_channel_centers(ah, chan, &centers);
-       freq = centers.synth_center;
diff --git a/src/patches/backports-4.2.6-1-grsecurity.patch b/src/patches/backports-4.2.6-1-grsecurity.patch
deleted file mode 100644 (file)
index 1a44409..0000000
+++ /dev/null
@@ -1,3995 +0,0 @@
-diff -Naur backports-4.2.6-1.org/drivers/bluetooth/btwilink.c backports-4.2.6-1/drivers/bluetooth/btwilink.c
---- backports-4.2.6-1.org/drivers/bluetooth/btwilink.c 2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/drivers/bluetooth/btwilink.c     2016-01-27 12:26:16.319959957 +0100
-@@ -288,7 +288,7 @@
- static int bt_ti_probe(struct platform_device *pdev)
- {
--      static struct ti_st *hst;
-+      struct ti_st *hst;
-       struct hci_dev *hdev;
-       int err;
-diff -Naur backports-4.2.6-1.org/drivers/media/dvb-core/dvbdev.c backports-4.2.6-1/drivers/media/dvb-core/dvbdev.c
---- backports-4.2.6-1.org/drivers/media/dvb-core/dvbdev.c      2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/dvb-core/dvbdev.c  2016-01-27 12:26:21.266626324 +0100
-@@ -272,7 +272,7 @@
-                       const struct dvb_device *template, void *priv, int type)
- {
-       struct dvb_device *dvbdev;
--      struct file_operations *dvbdevfops;
-+      file_operations_no_const *dvbdevfops;
-       struct device *clsdev;
-       int minor;
-       int id;
-diff -Naur backports-4.2.6-1.org/drivers/media/dvb-frontends/af9033.h backports-4.2.6-1/drivers/media/dvb-frontends/af9033.h
---- backports-4.2.6-1.org/drivers/media/dvb-frontends/af9033.h 2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/dvb-frontends/af9033.h     2016-01-27 12:26:21.266626324 +0100
-@@ -96,6 +96,6 @@
-       int (*pid_filter_ctrl)(struct dvb_frontend *fe, int onoff);
-       int (*pid_filter)(struct dvb_frontend *fe, int index, u16 pid,
-                         int onoff);
--};
-+} __no_const;
- #endif /* AF9033_H */
-diff -Naur backports-4.2.6-1.org/drivers/media/dvb-frontends/dib3000.h backports-4.2.6-1/drivers/media/dvb-frontends/dib3000.h
---- backports-4.2.6-1.org/drivers/media/dvb-frontends/dib3000.h        2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/dvb-frontends/dib3000.h    2016-01-27 12:26:21.266626324 +0100
-@@ -39,7 +39,7 @@
-       int (*fifo_ctrl)(struct dvb_frontend *fe, int onoff);
-       int (*pid_ctrl)(struct dvb_frontend *fe, int index, int pid, int onoff);
-       int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl);
--};
-+} __no_const;
- #if IS_REACHABLE(CPTCFG_DVB_DIB3000MB)
- extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
-diff -Naur backports-4.2.6-1.org/drivers/media/dvb-frontends/dib7000p.h backports-4.2.6-1/drivers/media/dvb-frontends/dib7000p.h
---- backports-4.2.6-1.org/drivers/media/dvb-frontends/dib7000p.h       2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/dvb-frontends/dib7000p.h   2016-01-27 12:26:21.266626324 +0100
-@@ -64,7 +64,7 @@
-       int (*get_adc_power)(struct dvb_frontend *fe);
-       int (*slave_reset)(struct dvb_frontend *fe);
-       struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
--};
-+} __no_const;
- #if IS_REACHABLE(CPTCFG_DVB_DIB7000P)
- void *dib7000p_attach(struct dib7000p_ops *ops);
-diff -Naur backports-4.2.6-1.org/drivers/media/dvb-frontends/dib8000.h backports-4.2.6-1/drivers/media/dvb-frontends/dib8000.h
---- backports-4.2.6-1.org/drivers/media/dvb-frontends/dib8000.h        2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/dvb-frontends/dib8000.h    2016-01-27 12:26:21.266626324 +0100
-@@ -61,7 +61,7 @@
-       int (*pid_filter_ctrl)(struct dvb_frontend *fe, u8 onoff);
-       int (*pid_filter)(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
-       struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
--};
-+} __no_const;
- #if IS_REACHABLE(CPTCFG_DVB_DIB8000)
- void *dib8000_attach(struct dib8000_ops *ops);
-diff -Naur backports-4.2.6-1.org/drivers/media/pci/cx88/cx88-video.c backports-4.2.6-1/drivers/media/pci/cx88/cx88-video.c
---- backports-4.2.6-1.org/drivers/media/pci/cx88/cx88-video.c  2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/pci/cx88/cx88-video.c      2016-01-27 12:26:21.266626324 +0100
-@@ -50,9 +50,9 @@
- /* ------------------------------------------------------------------ */
--static unsigned int video_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
--static unsigned int vbi_nr[]   = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
--static unsigned int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
-+static int video_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
-+static int vbi_nr[]   = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
-+static int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
- module_param_array(video_nr, int, NULL, 0444);
- module_param_array(vbi_nr,   int, NULL, 0444);
-diff -Naur backports-4.2.6-1.org/drivers/media/pci/ivtv/ivtv-driver.c backports-4.2.6-1/drivers/media/pci/ivtv/ivtv-driver.c
---- backports-4.2.6-1.org/drivers/media/pci/ivtv/ivtv-driver.c 2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/pci/ivtv/ivtv-driver.c     2016-01-27 12:26:21.266626324 +0100
-@@ -83,7 +83,7 @@
- MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl);
- /* ivtv instance counter */
--static atomic_t ivtv_instance = ATOMIC_INIT(0);
-+static atomic_unchecked_t ivtv_instance = ATOMIC_INIT(0);
- /* Parameter declarations */
- static int cardtype[IVTV_MAX_CARDS];
-diff -Naur backports-4.2.6-1.org/drivers/media/pci/solo6x10/solo6x10-core.c backports-4.2.6-1/drivers/media/pci/solo6x10/solo6x10-core.c
---- backports-4.2.6-1.org/drivers/media/pci/solo6x10/solo6x10-core.c   2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/pci/solo6x10/solo6x10-core.c       2016-01-27 12:26:21.266626324 +0100
-@@ -424,7 +424,7 @@
- static int solo_sysfs_init(struct solo_dev *solo_dev)
- {
--      struct bin_attribute *sdram_attr = &solo_dev->sdram_attr;
-+      bin_attribute_no_const *sdram_attr = &solo_dev->sdram_attr;
-       struct device *dev = &solo_dev->dev;
-       const char *driver;
-       int i;
-diff -Naur backports-4.2.6-1.org/drivers/media/pci/solo6x10/solo6x10-g723.c backports-4.2.6-1/drivers/media/pci/solo6x10/solo6x10-g723.c
---- backports-4.2.6-1.org/drivers/media/pci/solo6x10/solo6x10-g723.c   2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/pci/solo6x10/solo6x10-g723.c       2016-01-27 12:26:21.266626324 +0100
-@@ -351,7 +351,7 @@
- int solo_g723_init(struct solo_dev *solo_dev)
- {
--      static struct snd_device_ops ops = { NULL };
-+      static struct snd_device_ops ops = { };
-       struct snd_card *card;
-       struct snd_kcontrol_new kctl;
-       char name[32];
-diff -Naur backports-4.2.6-1.org/drivers/media/pci/solo6x10/solo6x10.h backports-4.2.6-1/drivers/media/pci/solo6x10/solo6x10.h
---- backports-4.2.6-1.org/drivers/media/pci/solo6x10/solo6x10.h        2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/pci/solo6x10/solo6x10.h    2016-01-27 12:26:21.266626324 +0100
-@@ -218,7 +218,7 @@
-       /* P2M DMA Engine */
-       struct solo_p2m_dev     p2m_dev[SOLO_NR_P2M];
--      atomic_t                p2m_count;
-+      atomic_unchecked_t      p2m_count;
-       int                     p2m_jiffies;
-       unsigned int            p2m_timeouts;
-diff -Naur backports-4.2.6-1.org/drivers/media/pci/solo6x10/solo6x10-p2m.c backports-4.2.6-1/drivers/media/pci/solo6x10/solo6x10-p2m.c
---- backports-4.2.6-1.org/drivers/media/pci/solo6x10/solo6x10-p2m.c    2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/pci/solo6x10/solo6x10-p2m.c        2016-01-27 12:26:21.266626324 +0100
-@@ -73,7 +73,7 @@
-       /* Get next ID. According to Softlogic, 6110 has problems on !=0 P2M */
-       if (solo_dev->type != SOLO_DEV_6110 && multi_p2m) {
--              p2m_id = atomic_inc_return(&solo_dev->p2m_count) % SOLO_NR_P2M;
-+              p2m_id = atomic_inc_return_unchecked(&solo_dev->p2m_count) % SOLO_NR_P2M;
-               if (p2m_id < 0)
-                       p2m_id = -p2m_id;
-       }
-diff -Naur backports-4.2.6-1.org/drivers/media/pci/tw68/tw68-core.c backports-4.2.6-1/drivers/media/pci/tw68/tw68-core.c
---- backports-4.2.6-1.org/drivers/media/pci/tw68/tw68-core.c   2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/pci/tw68/tw68-core.c       2016-01-27 12:26:21.266626324 +0100
-@@ -60,7 +60,7 @@
- module_param_array(card, int, NULL, 0444);
- MODULE_PARM_DESC(card, "card type");
--static atomic_t tw68_instance = ATOMIC_INIT(0);
-+static atomic_unchecked_t tw68_instance = ATOMIC_INIT(0);
- /* ------------------------------------------------------------------ */
-diff -Naur backports-4.2.6-1.org/drivers/media/platform/omap/omap_vout.c backports-4.2.6-1/drivers/media/platform/omap/omap_vout.c
---- backports-4.2.6-1.org/drivers/media/platform/omap/omap_vout.c      2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/platform/omap/omap_vout.c  2016-01-27 12:26:21.266626324 +0100
-@@ -63,7 +63,6 @@
-       OMAP_VIDEO2,
- };
--static struct videobuf_queue_ops video_vbq_ops;
- /* Variables configurable through module params*/
- static u32 video1_numbuffers = 3;
- static u32 video2_numbuffers = 3;
-@@ -1008,6 +1007,12 @@
- {
-       struct videobuf_queue *q;
-       struct omap_vout_device *vout = NULL;
-+      static struct videobuf_queue_ops video_vbq_ops = {
-+              .buf_setup = omap_vout_buffer_setup,
-+              .buf_prepare = omap_vout_buffer_prepare,
-+              .buf_release = omap_vout_buffer_release,
-+              .buf_queue = omap_vout_buffer_queue,
-+      };
-       vout = video_drvdata(file);
-       v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__);
-@@ -1025,10 +1030,6 @@
-       vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-       q = &vout->vbq;
--      video_vbq_ops.buf_setup = omap_vout_buffer_setup;
--      video_vbq_ops.buf_prepare = omap_vout_buffer_prepare;
--      video_vbq_ops.buf_release = omap_vout_buffer_release;
--      video_vbq_ops.buf_queue = omap_vout_buffer_queue;
-       spin_lock_init(&vout->vbq_lock);
-       videobuf_queue_dma_contig_init(q, &video_vbq_ops, q->dev,
-diff -Naur backports-4.2.6-1.org/drivers/media/platform/s5p-tv/mixer_grp_layer.c backports-4.2.6-1/drivers/media/platform/s5p-tv/mixer_grp_layer.c
---- backports-4.2.6-1.org/drivers/media/platform/s5p-tv/mixer_grp_layer.c      2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/platform/s5p-tv/mixer_grp_layer.c  2016-01-27 12:26:21.266626324 +0100
-@@ -235,7 +235,7 @@
- {
-       struct mxr_layer *layer;
-       int ret;
--      struct mxr_layer_ops ops = {
-+      static struct mxr_layer_ops ops = {
-               .release = mxr_graph_layer_release,
-               .buffer_set = mxr_graph_buffer_set,
-               .stream_set = mxr_graph_stream_set,
-diff -Naur backports-4.2.6-1.org/drivers/media/platform/s5p-tv/mixer.h backports-4.2.6-1/drivers/media/platform/s5p-tv/mixer.h
---- backports-4.2.6-1.org/drivers/media/platform/s5p-tv/mixer.h        2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/platform/s5p-tv/mixer.h    2016-01-27 12:26:21.266626324 +0100
-@@ -156,7 +156,7 @@
-       /** layer index (unique identifier) */
-       int idx;
-       /** callbacks for layer methods */
--      struct mxr_layer_ops ops;
-+      struct mxr_layer_ops *ops;
-       /** format array */
-       const struct mxr_format **fmt_array;
-       /** size of format array */
-diff -Naur backports-4.2.6-1.org/drivers/media/platform/s5p-tv/mixer_reg.c backports-4.2.6-1/drivers/media/platform/s5p-tv/mixer_reg.c
---- backports-4.2.6-1.org/drivers/media/platform/s5p-tv/mixer_reg.c    2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/platform/s5p-tv/mixer_reg.c        2016-01-27 12:26:21.266626324 +0100
-@@ -276,7 +276,7 @@
-               layer->update_buf = next;
-       }
--      layer->ops.buffer_set(layer, layer->update_buf);
-+      layer->ops->buffer_set(layer, layer->update_buf);
-       if (done && done != layer->shadow_buf)
-               vb2_buffer_done(&done->vb, VB2_BUF_STATE_DONE);
-diff -Naur backports-4.2.6-1.org/drivers/media/platform/s5p-tv/mixer_video.c backports-4.2.6-1/drivers/media/platform/s5p-tv/mixer_video.c
---- backports-4.2.6-1.org/drivers/media/platform/s5p-tv/mixer_video.c  2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/platform/s5p-tv/mixer_video.c      2016-01-27 12:26:21.266626324 +0100
-@@ -210,7 +210,7 @@
-       layer->geo.src.height = layer->geo.src.full_height;
-       mxr_geometry_dump(mdev, &layer->geo);
--      layer->ops.fix_geometry(layer, MXR_GEOMETRY_SINK, 0);
-+      layer->ops->fix_geometry(layer, MXR_GEOMETRY_SINK, 0);
-       mxr_geometry_dump(mdev, &layer->geo);
- }
-@@ -228,7 +228,7 @@
-       layer->geo.dst.full_width = mbus_fmt.width;
-       layer->geo.dst.full_height = mbus_fmt.height;
-       layer->geo.dst.field = mbus_fmt.field;
--      layer->ops.fix_geometry(layer, MXR_GEOMETRY_SINK, 0);
-+      layer->ops->fix_geometry(layer, MXR_GEOMETRY_SINK, 0);
-       mxr_geometry_dump(mdev, &layer->geo);
- }
-@@ -334,7 +334,7 @@
-       /* set source size to highest accepted value */
-       geo->src.full_width = max(geo->dst.full_width, pix->width);
-       geo->src.full_height = max(geo->dst.full_height, pix->height);
--      layer->ops.fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0);
-+      layer->ops->fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0);
-       mxr_geometry_dump(mdev, &layer->geo);
-       /* set cropping to total visible screen */
-       geo->src.width = pix->width;
-@@ -342,12 +342,12 @@
-       geo->src.x_offset = 0;
-       geo->src.y_offset = 0;
-       /* assure consistency of geometry */
--      layer->ops.fix_geometry(layer, MXR_GEOMETRY_CROP, MXR_NO_OFFSET);
-+      layer->ops->fix_geometry(layer, MXR_GEOMETRY_CROP, MXR_NO_OFFSET);
-       mxr_geometry_dump(mdev, &layer->geo);
-       /* set full size to lowest possible value */
-       geo->src.full_width = 0;
-       geo->src.full_height = 0;
--      layer->ops.fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0);
-+      layer->ops->fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0);
-       mxr_geometry_dump(mdev, &layer->geo);
-       /* returning results */
-@@ -474,7 +474,7 @@
-               target->width = s->r.width;
-               target->height = s->r.height;
--              layer->ops.fix_geometry(layer, stage, s->flags);
-+              layer->ops->fix_geometry(layer, stage, s->flags);
-               /* retrieve update selection rectangle */
-               res.left = target->x_offset;
-@@ -938,13 +938,13 @@
-       mxr_output_get(mdev);
-       mxr_layer_update_output(layer);
--      layer->ops.format_set(layer);
-+      layer->ops->format_set(layer);
-       /* enabling layer in hardware */
-       spin_lock_irqsave(&layer->enq_slock, flags);
-       layer->state = MXR_LAYER_STREAMING;
-       spin_unlock_irqrestore(&layer->enq_slock, flags);
--      layer->ops.stream_set(layer, MXR_ENABLE);
-+      layer->ops->stream_set(layer, MXR_ENABLE);
-       mxr_streamer_get(mdev);
-       return 0;
-@@ -1014,7 +1014,7 @@
-       spin_unlock_irqrestore(&layer->enq_slock, flags);
-       /* disabling layer in hardware */
--      layer->ops.stream_set(layer, MXR_DISABLE);
-+      layer->ops->stream_set(layer, MXR_DISABLE);
-       /* remove one streamer */
-       mxr_streamer_put(mdev);
-       /* allow changes in output configuration */
-@@ -1052,8 +1052,8 @@
- void mxr_layer_release(struct mxr_layer *layer)
- {
--      if (layer->ops.release)
--              layer->ops.release(layer);
-+      if (layer->ops->release)
-+              layer->ops->release(layer);
- }
- void mxr_base_layer_release(struct mxr_layer *layer)
-@@ -1079,7 +1079,7 @@
-       layer->mdev = mdev;
-       layer->idx = idx;
--      layer->ops = *ops;
-+      layer->ops = ops;
-       spin_lock_init(&layer->enq_slock);
-       INIT_LIST_HEAD(&layer->enq_list);
-diff -Naur backports-4.2.6-1.org/drivers/media/platform/s5p-tv/mixer_vp_layer.c backports-4.2.6-1/drivers/media/platform/s5p-tv/mixer_vp_layer.c
---- backports-4.2.6-1.org/drivers/media/platform/s5p-tv/mixer_vp_layer.c       2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/platform/s5p-tv/mixer_vp_layer.c   2016-01-27 12:26:21.266626324 +0100
-@@ -206,7 +206,7 @@
- {
-       struct mxr_layer *layer;
-       int ret;
--      struct mxr_layer_ops ops = {
-+      static struct mxr_layer_ops ops = {
-               .release = mxr_vp_layer_release,
-               .buffer_set = mxr_vp_buffer_set,
-               .stream_set = mxr_vp_stream_set,
-diff -Naur backports-4.2.6-1.org/drivers/media/platform/vivid/vivid-osd.c backports-4.2.6-1/drivers/media/platform/vivid/vivid-osd.c
---- backports-4.2.6-1.org/drivers/media/platform/vivid/vivid-osd.c     2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/platform/vivid/vivid-osd.c 2016-01-27 12:26:21.269959657 +0100
-@@ -85,6 +85,7 @@
-       case FBIOGET_VBLANK: {
-               struct fb_vblank vblank;
-+              memset(&vblank, 0, sizeof(vblank));
-               vblank.flags = FB_VBLANK_HAVE_COUNT | FB_VBLANK_HAVE_VCOUNT |
-                       FB_VBLANK_HAVE_VSYNC;
-               vblank.count = 0;
-diff -Naur backports-4.2.6-1.org/drivers/media/radio/radio-cadet.c backports-4.2.6-1/drivers/media/radio/radio-cadet.c
---- backports-4.2.6-1.org/drivers/media/radio/radio-cadet.c    2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/radio/radio-cadet.c        2016-01-27 12:26:21.269959657 +0100
-@@ -333,6 +333,8 @@
-       unsigned char readbuf[RDS_BUFFER];
-       int i = 0;
-+      if (count > RDS_BUFFER)
-+              return -EFAULT;
-       mutex_lock(&dev->lock);
-       if (dev->rdsstat == 0)
-               cadet_start_rds(dev);
-@@ -349,8 +351,9 @@
-               readbuf[i++] = dev->rdsbuf[dev->rdsout++];
-       mutex_unlock(&dev->lock);
--      if (i && copy_to_user(data, readbuf, i))
--              return -EFAULT;
-+      if (i > sizeof(readbuf) || (i && copy_to_user(data, readbuf, i)))
-+              i = -EFAULT;
-+
-       return i;
- }
-diff -Naur backports-4.2.6-1.org/drivers/media/radio/radio-maxiradio.c backports-4.2.6-1/drivers/media/radio/radio-maxiradio.c
---- backports-4.2.6-1.org/drivers/media/radio/radio-maxiradio.c        2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/radio/radio-maxiradio.c    2016-01-27 12:26:21.269959657 +0100
-@@ -61,7 +61,7 @@
- /* TEA5757 pin mappings */
- static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16;
--static atomic_t maxiradio_instance = ATOMIC_INIT(0);
-+static atomic_unchecked_t maxiradio_instance = ATOMIC_INIT(0);
- #define PCI_VENDOR_ID_GUILLEMOT 0x5046
- #define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001
-diff -Naur backports-4.2.6-1.org/drivers/media/radio/radio-shark2.c backports-4.2.6-1/drivers/media/radio/radio-shark2.c
---- backports-4.2.6-1.org/drivers/media/radio/radio-shark2.c   2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/radio/radio-shark2.c       2016-01-27 12:26:21.269959657 +0100
-@@ -74,7 +74,7 @@
-       u8 *transfer_buffer;
- };
--static atomic_t shark_instance = ATOMIC_INIT(0);
-+static atomic_unchecked_t shark_instance = ATOMIC_INIT(0);
- static int shark_write_reg(struct radio_tea5777 *tea, u64 reg)
- {
-diff -Naur backports-4.2.6-1.org/drivers/media/radio/radio-shark.c backports-4.2.6-1/drivers/media/radio/radio-shark.c
---- backports-4.2.6-1.org/drivers/media/radio/radio-shark.c    2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/radio/radio-shark.c        2016-01-27 12:26:21.269959657 +0100
-@@ -79,7 +79,7 @@
-       u32 last_val;
- };
--static atomic_t shark_instance = ATOMIC_INIT(0);
-+static atomic_unchecked_t shark_instance = ATOMIC_INIT(0);
- static void shark_write_val(struct snd_tea575x *tea, u32 val)
- {
-diff -Naur backports-4.2.6-1.org/drivers/media/radio/radio-si476x.c backports-4.2.6-1/drivers/media/radio/radio-si476x.c
---- backports-4.2.6-1.org/drivers/media/radio/radio-si476x.c   2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/radio/radio-si476x.c       2016-01-27 12:26:21.269959657 +0100
-@@ -1445,7 +1445,7 @@
-       struct si476x_radio *radio;
-       struct v4l2_ctrl *ctrl;
--      static atomic_t instance = ATOMIC_INIT(0);
-+      static atomic_unchecked_t instance = ATOMIC_INIT(0);
-       radio = devm_kzalloc(&pdev->dev, sizeof(*radio), GFP_KERNEL);
-       if (!radio)
-diff -Naur backports-4.2.6-1.org/drivers/media/radio/wl128x/fmdrv_common.c backports-4.2.6-1/drivers/media/radio/wl128x/fmdrv_common.c
---- backports-4.2.6-1.org/drivers/media/radio/wl128x/fmdrv_common.c    2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/radio/wl128x/fmdrv_common.c        2016-01-27 12:26:21.269959657 +0100
-@@ -71,7 +71,7 @@
- MODULE_PARM_DESC(rds_buf, "RDS buffer entries");
- /* Radio Nr */
--static u32 radio_nr = -1;
-+static int radio_nr = -1;
- module_param(radio_nr, int, 0444);
- MODULE_PARM_DESC(radio_nr, "Radio Nr");
-diff -Naur backports-4.2.6-1.org/drivers/media/usb/dvb-usb/cinergyT2-core.c backports-4.2.6-1/drivers/media/usb/dvb-usb/cinergyT2-core.c
---- backports-4.2.6-1.org/drivers/media/usb/dvb-usb/cinergyT2-core.c   2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/usb/dvb-usb/cinergyT2-core.c       2016-01-27 12:26:21.269959657 +0100
-@@ -50,29 +50,73 @@
- static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)
- {
--      char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 };
--      char result[64];
--      return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result,
--                              sizeof(result), 0);
-+      char *buf;
-+      char *result;
-+      int retval;
-+
-+      buf = kmalloc(2, GFP_KERNEL);
-+      if (buf == NULL)
-+              return -ENOMEM;
-+      result = kmalloc(64, GFP_KERNEL);
-+      if (result == NULL) {
-+              kfree(buf);
-+              return -ENOMEM;
-+      }
-+
-+      buf[0] = CINERGYT2_EP1_CONTROL_STREAM_TRANSFER;
-+      buf[1] = enable ? 1 : 0;
-+
-+      retval = dvb_usb_generic_rw(adap->dev, buf, 2, result, 64, 0);
-+
-+      kfree(buf);
-+      kfree(result);
-+      return retval;
- }
- static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable)
- {
--      char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 };
--      char state[3];
--      return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0);
-+      char *buf;
-+      char *state;
-+      int retval;
-+
-+      buf = kmalloc(2, GFP_KERNEL);
-+      if (buf == NULL)
-+              return -ENOMEM;
-+      state = kmalloc(3, GFP_KERNEL);
-+      if (state == NULL) {
-+              kfree(buf);
-+              return -ENOMEM;
-+      }
-+
-+      buf[0] = CINERGYT2_EP1_SLEEP_MODE;
-+      buf[1] = enable ? 1 : 0;
-+
-+      retval = dvb_usb_generic_rw(d, buf, 2, state, 3, 0);
-+
-+      kfree(buf);
-+      kfree(state);
-+      return retval;
- }
- static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
- {
--      char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION };
--      char state[3];
-+      char *query;
-+      char *state;
-       int ret;
-+      query = kmalloc(1, GFP_KERNEL);
-+      if (query == NULL)
-+              return -ENOMEM;
-+      state = kmalloc(3, GFP_KERNEL);
-+      if (state == NULL) {
-+              kfree(query);
-+              return -ENOMEM;
-+      }
-+
-+      query[0] = CINERGYT2_EP1_GET_FIRMWARE_VERSION;
-       adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
--      ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state,
--                              sizeof(state), 0);
-+      ret = dvb_usb_generic_rw(adap->dev, query, 1, state, 3, 0);
-       if (ret < 0) {
-               deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep "
-                       "state info\n");
-@@ -80,7 +124,8 @@
-       /* Copy this pointer as we are gonna need it in the release phase */
-       cinergyt2_usb_device = adap->dev;
--
-+      kfree(query);
-+      kfree(state);
-       return 0;
- }
-@@ -141,12 +186,23 @@
- static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
- {
-       struct cinergyt2_state *st = d->priv;
--      u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS;
-+      u8 *key, *cmd;
-       int i;
-+      cmd = kmalloc(1, GFP_KERNEL);
-+      if (cmd == NULL)
-+              return -EINVAL;
-+      key = kzalloc(5, GFP_KERNEL);
-+      if (key == NULL) {
-+              kfree(cmd);
-+              return -EINVAL;
-+      }
-+
-+      cmd[0] = CINERGYT2_EP1_GET_RC_EVENTS;
-+
-       *state = REMOTE_NO_KEY_PRESSED;
--      dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0);
-+      dvb_usb_generic_rw(d, cmd, 1, key, 5, 0);
-       if (key[4] == 0xff) {
-               /* key repeat */
-               st->rc_counter++;
-@@ -157,12 +213,12 @@
-                                       *event = d->last_event;
-                                       deb_rc("repeat key, event %x\n",
-                                                  *event);
--                                      return 0;
-+                                      goto out;
-                               }
-                       }
-                       deb_rc("repeated key (non repeatable)\n");
-               }
--              return 0;
-+              goto out;
-       }
-       /* hack to pass checksum on the custom field */
-@@ -174,6 +230,9 @@
-               deb_rc("key: %*ph\n", 5, key);
-       }
-+out:
-+      kfree(cmd);
-+      kfree(key);
-       return 0;
- }
-diff -Naur backports-4.2.6-1.org/drivers/media/usb/dvb-usb/cinergyT2-fe.c backports-4.2.6-1/drivers/media/usb/dvb-usb/cinergyT2-fe.c
---- backports-4.2.6-1.org/drivers/media/usb/dvb-usb/cinergyT2-fe.c     2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/usb/dvb-usb/cinergyT2-fe.c 2016-01-27 12:26:21.269959657 +0100
-@@ -145,103 +145,176 @@
-                                   enum fe_status *status)
- {
-       struct cinergyt2_fe_state *state = fe->demodulator_priv;
--      struct dvbt_get_status_msg result;
--      u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-+      struct dvbt_get_status_msg *result;
-+      u8 *cmd;
-       int ret;
--      ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result,
--                      sizeof(result), 0);
-+      cmd = kmalloc(1, GFP_KERNEL);
-+      if (cmd == NULL)
-+              return -ENOMEM;
-+      result = kmalloc(sizeof(*result), GFP_KERNEL);
-+      if (result == NULL) {
-+              kfree(cmd);
-+              return -ENOMEM;
-+      }
-+
-+      cmd[0] = CINERGYT2_EP1_GET_TUNER_STATUS;
-+
-+      ret = dvb_usb_generic_rw(state->d, cmd, 1, (u8 *)result,
-+                      sizeof(*result), 0);
-       if (ret < 0)
--              return ret;
-+              goto out;
-       *status = 0;
--      if (0xffff - le16_to_cpu(result.gain) > 30)
-+      if (0xffff - le16_to_cpu(result->gain) > 30)
-               *status |= FE_HAS_SIGNAL;
--      if (result.lock_bits & (1 << 6))
-+      if (result->lock_bits & (1 << 6))
-               *status |= FE_HAS_LOCK;
--      if (result.lock_bits & (1 << 5))
-+      if (result->lock_bits & (1 << 5))
-               *status |= FE_HAS_SYNC;
--      if (result.lock_bits & (1 << 4))
-+      if (result->lock_bits & (1 << 4))
-               *status |= FE_HAS_CARRIER;
--      if (result.lock_bits & (1 << 1))
-+      if (result->lock_bits & (1 << 1))
-               *status |= FE_HAS_VITERBI;
-       if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
-                       (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
-               *status &= ~FE_HAS_LOCK;
--      return 0;
-+out:
-+      kfree(cmd);
-+      kfree(result);
-+      return ret;
- }
- static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
- {
-       struct cinergyt2_fe_state *state = fe->demodulator_priv;
--      struct dvbt_get_status_msg status;
--      char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-+      struct dvbt_get_status_msg *status;
-+      char *cmd;
-       int ret;
--      ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
--                              sizeof(status), 0);
-+      cmd = kmalloc(1, GFP_KERNEL);
-+      if (cmd == NULL)
-+              return -ENOMEM;
-+      status = kmalloc(sizeof(*status), GFP_KERNEL);
-+      if (status == NULL) {
-+              kfree(cmd);
-+              return -ENOMEM;
-+      }
-+
-+      cmd[0] = CINERGYT2_EP1_GET_TUNER_STATUS;
-+
-+      ret = dvb_usb_generic_rw(state->d, cmd, 1, (char *)status,
-+                              sizeof(*status), 0);
-       if (ret < 0)
--              return ret;
-+              goto out;
--      *ber = le32_to_cpu(status.viterbi_error_rate);
-+      *ber = le32_to_cpu(status->viterbi_error_rate);
-+out:
-+      kfree(cmd);
-+      kfree(status);
-       return 0;
- }
- static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
- {
-       struct cinergyt2_fe_state *state = fe->demodulator_priv;
--      struct dvbt_get_status_msg status;
--      u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-+      struct dvbt_get_status_msg *status;
-+      u8 *cmd;
-       int ret;
--      ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status,
--                              sizeof(status), 0);
-+      cmd = kmalloc(1, GFP_KERNEL);
-+      if (cmd == NULL)
-+              return -ENOMEM;
-+      status = kmalloc(sizeof(*status), GFP_KERNEL);
-+      if (status == NULL) {
-+              kfree(cmd);
-+              return -ENOMEM;
-+      }
-+
-+      cmd[0] = CINERGYT2_EP1_GET_TUNER_STATUS;
-+
-+      ret = dvb_usb_generic_rw(state->d, cmd, 1, (u8 *)status,
-+                              sizeof(*status), 0);
-       if (ret < 0) {
-               err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n",
-                       ret);
--              return ret;
-+              goto out;
-       }
--      *unc = le32_to_cpu(status.uncorrected_block_count);
--      return 0;
-+      *unc = le32_to_cpu(status->uncorrected_block_count);
-+
-+out:
-+      kfree(cmd);
-+      kfree(status);
-+      return ret;
- }
- static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe,
-                                               u16 *strength)
- {
-       struct cinergyt2_fe_state *state = fe->demodulator_priv;
--      struct dvbt_get_status_msg status;
--      char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-+      struct dvbt_get_status_msg *status;
-+      char *cmd;
-       int ret;
--      ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
--                              sizeof(status), 0);
-+      cmd = kmalloc(1, GFP_KERNEL);
-+      if (cmd == NULL)
-+              return -ENOMEM;
-+      status = kmalloc(sizeof(*status), GFP_KERNEL);
-+      if (status == NULL) {
-+              kfree(cmd);
-+              return -ENOMEM;
-+      }
-+
-+      cmd[0] = CINERGYT2_EP1_GET_TUNER_STATUS;
-+
-+      ret = dvb_usb_generic_rw(state->d, cmd, 1, (char *)status,
-+                              sizeof(*status), 0);
-       if (ret < 0) {
-               err("cinergyt2_fe_read_signal_strength() Failed!"
-                       " (Error=%d)\n", ret);
--              return ret;
-+              goto out;
-       }
--      *strength = (0xffff - le16_to_cpu(status.gain));
-+      *strength = (0xffff - le16_to_cpu(status->gain));
-+
-+out:
-+      kfree(cmd);
-+      kfree(status);
-       return 0;
- }
- static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
- {
-       struct cinergyt2_fe_state *state = fe->demodulator_priv;
--      struct dvbt_get_status_msg status;
--      char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-+      struct dvbt_get_status_msg *status;
-+      char *cmd;
-       int ret;
--      ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
--                              sizeof(status), 0);
-+      cmd = kmalloc(1, GFP_KERNEL);
-+      if (cmd == NULL)
-+              return -ENOMEM;
-+      status = kmalloc(sizeof(*status), GFP_KERNEL);
-+      if (status == NULL) {
-+              kfree(cmd);
-+              return -ENOMEM;
-+      }
-+
-+      cmd[0] = CINERGYT2_EP1_GET_TUNER_STATUS;
-+
-+      ret = dvb_usb_generic_rw(state->d, cmd, 1, (char *)status,
-+                              sizeof(*status), 0);
-       if (ret < 0) {
-               err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret);
--              return ret;
-+              goto out;
-       }
--      *snr = (status.snr << 8) | status.snr;
--      return 0;
-+      *snr = (status->snr << 8) | status->snr;
-+
-+out:
-+      kfree(cmd);
-+      kfree(status);
-+      return ret;
- }
- static int cinergyt2_fe_init(struct dvb_frontend *fe)
-@@ -266,35 +339,46 @@
- {
-       struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-       struct cinergyt2_fe_state *state = fe->demodulator_priv;
--      struct dvbt_set_parameters_msg param;
--      char result[2];
-+      struct dvbt_set_parameters_msg *param;
-+      char *result;
-       int err;
--      param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
--      param.tps = cpu_to_le16(compute_tps(fep));
--      param.freq = cpu_to_le32(fep->frequency / 1000);
--      param.flags = 0;
-+      result = kmalloc(2, GFP_KERNEL);
-+      if (result == NULL)
-+              return -ENOMEM;
-+      param = kmalloc(sizeof(*param), GFP_KERNEL);
-+      if (param == NULL) {
-+              kfree(result);
-+              return -ENOMEM;
-+      }
-+
-+      param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
-+      param->tps = cpu_to_le16(compute_tps(fep));
-+      param->freq = cpu_to_le32(fep->frequency / 1000);
-+      param->flags = 0;
-       switch (fep->bandwidth_hz) {
-       default:
-       case 8000000:
--              param.bandwidth = 8;
-+              param->bandwidth = 8;
-               break;
-       case 7000000:
--              param.bandwidth = 7;
-+              param->bandwidth = 7;
-               break;
-       case 6000000:
--              param.bandwidth = 6;
-+              param->bandwidth = 6;
-               break;
-       }
-       err = dvb_usb_generic_rw(state->d,
--                      (char *)&param, sizeof(param),
--                      result, sizeof(result), 0);
-+                      (char *)param, sizeof(*param),
-+                      result, 2, 0);
-       if (err < 0)
-               err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err);
--      return (err < 0) ? err : 0;
-+      kfree(result);
-+      kfree(param);
-+      return err;
- }
- static void cinergyt2_fe_release(struct dvb_frontend *fe)
-diff -Naur backports-4.2.6-1.org/drivers/media/usb/dvb-usb/dvb-usb-firmware.c backports-4.2.6-1/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
---- backports-4.2.6-1.org/drivers/media/usb/dvb-usb/dvb-usb-firmware.c 2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/usb/dvb-usb/dvb-usb-firmware.c     2016-01-27 12:26:21.269959657 +0100
-@@ -35,42 +35,57 @@
- int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type)
- {
--      struct hexline hx;
--      u8 reset;
-+      struct hexline *hx;
-+      u8 *reset;
-       int ret,pos=0;
-+      reset = kmalloc(1, GFP_KERNEL);
-+      if (reset == NULL)
-+              return -ENOMEM;
-+
-+      hx = kmalloc(sizeof(struct hexline), GFP_KERNEL);
-+      if (hx == NULL) {
-+              kfree(reset);
-+              return -ENOMEM;
-+      }
-+
-       /* stop the CPU */
--      reset = 1;
--      if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
-+      reset[0] = 1;
-+      if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,reset,1)) != 1)
-               err("could not stop the USB controller CPU.");
--      while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) {
--              deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk);
--              ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len);
-+      while ((ret = dvb_usb_get_hexline(fw,hx,&pos)) > 0) {
-+              deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx->addr,hx->len,hx->chk);
-+              ret = usb_cypress_writemem(udev,hx->addr,hx->data,hx->len);
--              if (ret != hx.len) {
-+              if (ret != hx->len) {
-                       err("error while transferring firmware "
-                               "(transferred size: %d, block size: %d)",
--                              ret,hx.len);
-+                              ret,hx->len);
-                       ret = -EINVAL;
-                       break;
-               }
-       }
-       if (ret < 0) {
-               err("firmware download failed at %d with %d",pos,ret);
-+              kfree(reset);
-+              kfree(hx);
-               return ret;
-       }
-       if (ret == 0) {
-               /* restart the CPU */
--              reset = 0;
--              if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
-+              reset[0] = 0;
-+              if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,reset,1) != 1) {
-                       err("could not restart the USB controller CPU.");
-                       ret = -EINVAL;
-               }
-       } else
-               ret = -EIO;
-+      kfree(reset);
-+      kfree(hx);
-+
-       return ret;
- }
- EXPORT_SYMBOL(usb_cypress_load_firmware);
-diff -Naur backports-4.2.6-1.org/drivers/media/usb/dvb-usb/technisat-usb2.c backports-4.2.6-1/drivers/media/usb/dvb-usb/technisat-usb2.c
---- backports-4.2.6-1.org/drivers/media/usb/dvb-usb/technisat-usb2.c   2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/usb/dvb-usb/technisat-usb2.c       2016-01-27 12:26:21.269959657 +0100
-@@ -87,8 +87,11 @@
- static int technisat_usb2_i2c_access(struct usb_device *udev,
-               u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
- {
--      u8 b[64];
--      int ret, actual_length;
-+      u8 *b = kmalloc(64, GFP_KERNEL);
-+      int ret, actual_length, error = 0;
-+
-+      if (b == NULL)
-+              return -ENOMEM;
-       deb_i2c("i2c-access: %02x, tx: ", device_addr);
-       debug_dump(tx, txlen, deb_i2c);
-@@ -121,7 +124,8 @@
-       if (ret < 0) {
-               err("i2c-error: out failed %02x = %d", device_addr, ret);
--              return -ENODEV;
-+              error = -ENODEV;
-+              goto out;
-       }
-       ret = usb_bulk_msg(udev,
-@@ -129,7 +133,8 @@
-                       b, 64, &actual_length, 1000);
-       if (ret < 0) {
-               err("i2c-error: in failed %02x = %d", device_addr, ret);
--              return -ENODEV;
-+              error = -ENODEV;
-+              goto out;
-       }
-       if (b[0] != I2C_STATUS_OK) {
-@@ -137,8 +142,10 @@
-               /* handle tuner-i2c-nak */
-               if (!(b[0] == I2C_STATUS_NAK &&
-                               device_addr == 0x60
--                              /* && device_is_technisat_usb2 */))
--                      return -ENODEV;
-+                              /* && device_is_technisat_usb2 */)) {
-+                      error = -ENODEV;
-+                      goto out;
-+              }
-       }
-       deb_i2c("status: %d, ", b[0]);
-@@ -152,7 +159,9 @@
-       deb_i2c("\n");
--      return 0;
-+out:
-+      kfree(b);
-+      return error;
- }
- static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
-@@ -224,14 +233,16 @@
- {
-       int ret;
--      u8 led[8] = {
--              red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
--              0
--      };
-+      u8 *led = kzalloc(8, GFP_KERNEL);
-+
-+      if (led == NULL)
-+              return -ENOMEM;
-       if (disable_led_control && state != TECH_LED_OFF)
-               return 0;
-+      led[0] = red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST;
-+
-       switch (state) {
-       case TECH_LED_ON:
-               led[1] = 0x82;
-@@ -263,16 +274,22 @@
-               red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
-               USB_TYPE_VENDOR | USB_DIR_OUT,
-               0, 0,
--              led, sizeof(led), 500);
-+              led, 8, 500);
-       mutex_unlock(&d->i2c_mutex);
-+
-+      kfree(led);
-+
-       return ret;
- }
- static int technisat_usb2_set_led_timer(struct dvb_usb_device *d, u8 red, u8 green)
- {
-       int ret;
--      u8 b = 0;
-+      u8 *b = kzalloc(1, GFP_KERNEL);
-+
-+      if (b == NULL)
-+              return -ENOMEM;
-       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-               return -EAGAIN;
-@@ -281,10 +298,12 @@
-               SET_LED_TIMER_DIVIDER_VENDOR_REQUEST,
-               USB_TYPE_VENDOR | USB_DIR_OUT,
-               (red << 8) | green, 0,
--              &b, 1, 500);
-+              b, 1, 500);
-       mutex_unlock(&d->i2c_mutex);
-+      kfree(b);
-+
-       return ret;
- }
-@@ -328,7 +347,7 @@
-               struct dvb_usb_device_description **desc, int *cold)
- {
-       int ret;
--      u8 version[3];
-+      u8 *version = kmalloc(3, GFP_KERNEL);
-       /* first select the interface */
-       if (usb_set_interface(udev, 0, 1) != 0)
-@@ -338,11 +357,14 @@
-       *cold = 0; /* by default do not download a firmware - just in case something is wrong */
-+      if (version == NULL)
-+              return 0;
-+
-       ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-               GET_VERSION_INFO_VENDOR_REQUEST,
-               USB_TYPE_VENDOR | USB_DIR_IN,
-               0, 0,
--              version, sizeof(version), 500);
-+              version, 3, 500);
-       if (ret < 0)
-               *cold = 1;
-@@ -351,6 +373,8 @@
-               *cold = 0;
-       }
-+      kfree(version);
-+
-       return 0;
- }
-@@ -594,10 +618,15 @@
- static int technisat_usb2_get_ir(struct dvb_usb_device *d)
- {
--      u8 buf[62], *b;
-+      u8 *buf, *b;
-       int ret;
-       struct ir_raw_event ev;
-+      buf = kmalloc(62, GFP_KERNEL);
-+
-+      if (buf == NULL)
-+              return -ENOMEM;
-+
-       buf[0] = GET_IR_DATA_VENDOR_REQUEST;
-       buf[1] = 0x08;
-       buf[2] = 0x8f;
-@@ -620,16 +649,20 @@
-                       GET_IR_DATA_VENDOR_REQUEST,
-                       USB_TYPE_VENDOR | USB_DIR_IN,
-                       0x8080, 0,
--                      buf, sizeof(buf), 500);
-+                      buf, 62, 500);
- unlock:
-       mutex_unlock(&d->i2c_mutex);
--      if (ret < 0)
-+      if (ret < 0) {
-+              kfree(buf);
-               return ret;
-+      }
--      if (ret == 1)
-+      if (ret == 1) {
-+              kfree(buf);
-               return 0; /* no key pressed */
-+      }
-       /* decoding */
-       b = buf+1;
-@@ -656,6 +689,8 @@
-       ir_raw_event_handle(d->rc_dev);
-+      kfree(buf);
-+
-       return 1;
- }
-diff -Naur backports-4.2.6-1.org/drivers/media/v4l2-core/v4l2-compat-ioctl32.c backports-4.2.6-1/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
---- backports-4.2.6-1.org/drivers/media/v4l2-core/v4l2-compat-ioctl32.c        2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/v4l2-core/v4l2-compat-ioctl32.c    2016-01-27 12:26:21.269959657 +0100
-@@ -429,7 +429,7 @@
-                * by passing a very big num_planes value */
-               uplane = compat_alloc_user_space(num_planes *
-                                               sizeof(struct v4l2_plane));
--              kp->m.planes = (__force struct v4l2_plane *)uplane;
-+              kp->m.planes = (__force_kernel struct v4l2_plane *)uplane;
-               while (--num_planes >= 0) {
-                       ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
-@@ -500,7 +500,7 @@
-               if (num_planes == 0)
-                       return 0;
--              uplane = (__force struct v4l2_plane __user *)kp->m.planes;
-+              uplane = (struct v4l2_plane __force_user *)kp->m.planes;
-               if (get_user(p, &up->m.planes))
-                       return -EFAULT;
-               uplane32 = compat_ptr(p);
-@@ -564,7 +564,7 @@
-               get_user(kp->flags, &up->flags) ||
-               copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
-                       return -EFAULT;
--      kp->base = (__force void *)compat_ptr(tmp);
-+      kp->base = (__force_kernel void *)compat_ptr(tmp);
-       return 0;
- }
-@@ -669,7 +669,7 @@
-                       n * sizeof(struct v4l2_ext_control32)))
-               return -EFAULT;
-       kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
--      kp->controls = (__force struct v4l2_ext_control *)kcontrols;
-+      kp->controls = (__force_kernel struct v4l2_ext_control *)kcontrols;
-       while (--n >= 0) {
-               u32 id;
-@@ -696,7 +696,7 @@
- {
-       struct v4l2_ext_control32 __user *ucontrols;
-       struct v4l2_ext_control __user *kcontrols =
--              (__force struct v4l2_ext_control __user *)kp->controls;
-+              (struct v4l2_ext_control __force_user *)kp->controls;
-       int n = kp->count;
-       compat_caddr_t p;
-@@ -780,7 +780,7 @@
-               get_user(tmp, &up->edid) ||
-               copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
-                       return -EFAULT;
--      kp->edid = (__force u8 *)compat_ptr(tmp);
-+      kp->edid = (__force_kernel u8 *)compat_ptr(tmp);
-       return 0;
- }
-diff -Naur backports-4.2.6-1.org/drivers/media/v4l2-core/v4l2-device.c backports-4.2.6-1/drivers/media/v4l2-core/v4l2-device.c
---- backports-4.2.6-1.org/drivers/media/v4l2-core/v4l2-device.c        2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/v4l2-core/v4l2-device.c    2016-01-27 12:26:21.269959657 +0100
-@@ -74,9 +74,9 @@
- EXPORT_SYMBOL_GPL(v4l2_device_put);
- int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
--                                              atomic_t *instance)
-+                                              atomic_unchecked_t *instance)
- {
--      int num = atomic_inc_return(instance) - 1;
-+      int num = atomic_inc_return_unchecked(instance) - 1;
-       int len = strlen(basename);
-       if (basename[len - 1] >= '0' && basename[len - 1] <= '9')
-diff -Naur backports-4.2.6-1.org/drivers/media/v4l2-core/v4l2-ioctl.c backports-4.2.6-1/drivers/media/v4l2-core/v4l2-ioctl.c
---- backports-4.2.6-1.org/drivers/media/v4l2-core/v4l2-ioctl.c 2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/drivers/media/v4l2-core/v4l2-ioctl.c     2016-01-27 12:26:21.269959657 +0100
-@@ -2341,7 +2341,8 @@
-                               struct file *file, void *fh, void *p);
-       } u;
-       void (*debug)(const void *arg, bool write_only);
--};
-+} __do_const;
-+typedef struct v4l2_ioctl_info __no_const v4l2_ioctl_info_no_const;
- /* This control needs a priority check */
- #define INFO_FL_PRIO  (1 << 0)
-@@ -2525,7 +2526,7 @@
-       struct video_device *vfd = video_devdata(file);
-       const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
-       bool write_only = false;
--      struct v4l2_ioctl_info default_info;
-+      v4l2_ioctl_info_no_const default_info;
-       const struct v4l2_ioctl_info *info;
-       void *fh = file->private_data;
-       struct v4l2_fh *vfh = NULL;
-@@ -2616,7 +2617,7 @@
-                               ret = -EINVAL;
-                               break;
-                       }
--                      *user_ptr = (void __user *)buf->m.planes;
-+                      *user_ptr = (void __force_user *)buf->m.planes;
-                       *kernel_ptr = (void **)&buf->m.planes;
-                       *array_size = sizeof(struct v4l2_plane) * buf->length;
-                       ret = 1;
-@@ -2633,7 +2634,7 @@
-                               ret = -EINVAL;
-                               break;
-                       }
--                      *user_ptr = (void __user *)edid->edid;
-+                      *user_ptr = (void __force_user *)edid->edid;
-                       *kernel_ptr = (void **)&edid->edid;
-                       *array_size = edid->blocks * 128;
-                       ret = 1;
-@@ -2651,7 +2652,7 @@
-                               ret = -EINVAL;
-                               break;
-                       }
--                      *user_ptr = (void __user *)ctrls->controls;
-+                      *user_ptr = (void __force_user *)ctrls->controls;
-                       *kernel_ptr = (void **)&ctrls->controls;
-                       *array_size = sizeof(struct v4l2_ext_control)
-                                   * ctrls->count;
-@@ -2752,7 +2753,7 @@
-       }
-       if (has_array_args) {
--              *kernel_ptr = (void __force *)user_ptr;
-+              *kernel_ptr = (void __force_kernel *)user_ptr;
-               if (copy_to_user(user_ptr, mbuf, array_size))
-                       err = -EFAULT;
-               goto out_array_args;
-diff -Naur backports-4.2.6-1.org/drivers/net/usb/sierra_net.c backports-4.2.6-1/drivers/net/usb/sierra_net.c
---- backports-4.2.6-1.org/drivers/net/usb/sierra_net.c 2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/usb/sierra_net.c     2016-01-27 12:26:21.283292990 +0100
-@@ -51,7 +51,7 @@
- /* atomic counter partially included in MAC address to make sure 2 devices
-  * do not end up with the same MAC - concept breaks in case of > 255 ifaces
-  */
--static        atomic_t iface_counter = ATOMIC_INIT(0);
-+static        atomic_unchecked_t iface_counter = ATOMIC_INIT(0);
- /*
-  * SYNC Timer Delay definition used to set the expiry time
-@@ -697,7 +697,7 @@
-       dev->net->netdev_ops = &sierra_net_device_ops;
-       /* change MAC addr to include, ifacenum, and to be unique */
--      dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter);
-+      dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return_unchecked(&iface_counter);
-       dev->net->dev_addr[ETH_ALEN-1] = ifacenum;
-       /* we will have to manufacture ethernet headers, prepare template */
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/airo.c backports-4.2.6-1/drivers/net/wireless/airo.c
---- backports-4.2.6-1.org/drivers/net/wireless/airo.c  2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/airo.c      2016-01-27 12:26:21.286626323 +0100
-@@ -7846,7 +7846,7 @@
-       struct airo_info *ai = dev->ml_priv;
-       int  ridcode;
-         int  enabled;
--      static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
-+      int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
-       unsigned char *iobuf;
-       /* Only super-user can write RIDs */
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/at76c50x-usb.c backports-4.2.6-1/drivers/net/wireless/at76c50x-usb.c
---- backports-4.2.6-1.org/drivers/net/wireless/at76c50x-usb.c  2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/at76c50x-usb.c      2016-01-27 12:26:21.286626323 +0100
-@@ -353,7 +353,7 @@
- }
- /* Convert timeout from the DFU status to jiffies */
--static inline unsigned long at76_get_timeout(struct dfu_status *s)
-+static inline unsigned long __intentional_overflow(-1) at76_get_timeout(struct dfu_status *s)
- {
-       return msecs_to_jiffies((s->poll_timeout[2] << 16)
-                               | (s->poll_timeout[1] << 8)
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath10k/ce.c backports-4.2.6-1/drivers/net/wireless/ath/ath10k/ce.c
---- backports-4.2.6-1.org/drivers/net/wireless/ath/ath10k/ce.c 2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ath/ath10k/ce.c     2016-01-27 12:26:21.286626323 +0100
-@@ -896,12 +896,12 @@
-       return 0;
- }
--static struct ath10k_ce_ring *
-+static struct ath10k_ce_ring * __intentional_overflow(-1)
- ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id,
-                        const struct ce_attr *attr)
- {
-       struct ath10k_ce_ring *src_ring;
--      u32 nentries = attr->src_nentries;
-+      unsigned long nentries = attr->src_nentries;
-       dma_addr_t base_addr;
-       nentries = roundup_pow_of_two(nentries);
-@@ -968,7 +968,7 @@
-                         const struct ce_attr *attr)
- {
-       struct ath10k_ce_ring *dest_ring;
--      u32 nentries;
-+      unsigned long nentries;
-       dma_addr_t base_addr;
-       nentries = roundup_pow_of_two(attr->dest_nentries);
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath10k/htc.c backports-4.2.6-1/drivers/net/wireless/ath/ath10k/htc.c
---- backports-4.2.6-1.org/drivers/net/wireless/ath/ath10k/htc.c        2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ath/ath10k/htc.c    2016-01-27 12:26:21.286626323 +0100
-@@ -841,7 +841,10 @@
- /* registered target arrival callback from the HIF layer */
- int ath10k_htc_init(struct ath10k *ar)
- {
--      struct ath10k_hif_cb htc_callbacks;
-+      static struct ath10k_hif_cb htc_callbacks = {
-+              .rx_completion = ath10k_htc_rx_completion_handler,
-+              .tx_completion = ath10k_htc_tx_completion_handler,
-+      };
-       struct ath10k_htc_ep *ep = NULL;
-       struct ath10k_htc *htc = &ar->htc;
-@@ -850,8 +853,6 @@
-       ath10k_htc_reset_endpoint_states(htc);
-       /* setup HIF layer callbacks */
--      htc_callbacks.rx_completion = ath10k_htc_rx_completion_handler;
--      htc_callbacks.tx_completion = ath10k_htc_tx_completion_handler;
-       htc->ar = ar;
-       /* Get HIF default pipe for HTC message exchange */
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath10k/htc.h backports-4.2.6-1/drivers/net/wireless/ath/ath10k/htc.h
---- backports-4.2.6-1.org/drivers/net/wireless/ath/ath10k/htc.h        2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ath/ath10k/htc.h    2016-01-27 12:26:21.286626323 +0100
-@@ -270,13 +270,13 @@
- struct ath10k_htc_ops {
-       void (*target_send_suspend_complete)(struct ath10k *ar);
--};
-+} __no_const;
- struct ath10k_htc_ep_ops {
-       void (*ep_tx_complete)(struct ath10k *, struct sk_buff *);
-       void (*ep_rx_complete)(struct ath10k *, struct sk_buff *);
-       void (*ep_tx_credits)(struct ath10k *);
--};
-+} __no_const;
- /* service connection information */
- struct ath10k_htc_svc_conn_req {
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/ar9002_mac.c backports-4.2.6-1/drivers/net/wireless/ath/ath9k/ar9002_mac.c
---- backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/ar9002_mac.c  2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ath/ath9k/ar9002_mac.c      2016-01-27 12:26:21.286626323 +0100
-@@ -220,8 +220,8 @@
-       ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
-       ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
--      ACCESS_ONCE(ads->ds_link) = i->link;
--      ACCESS_ONCE(ads->ds_data) = i->buf_addr[0];
-+      ACCESS_ONCE_RW(ads->ds_link) = i->link;
-+      ACCESS_ONCE_RW(ads->ds_data) = i->buf_addr[0];
-       ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore);
-       ctl6 = SM(i->keytype, AR_EncrType);
-@@ -235,26 +235,26 @@
-       if ((i->is_first || i->is_last) &&
-           i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) {
--              ACCESS_ONCE(ads->ds_ctl2) = set11nTries(i->rates, 0)
-+              ACCESS_ONCE_RW(ads->ds_ctl2) = set11nTries(i->rates, 0)
-                       | set11nTries(i->rates, 1)
-                       | set11nTries(i->rates, 2)
-                       | set11nTries(i->rates, 3)
-                       | (i->dur_update ? AR_DurUpdateEna : 0)
-                       | SM(0, AR_BurstDur);
--              ACCESS_ONCE(ads->ds_ctl3) = set11nRate(i->rates, 0)
-+              ACCESS_ONCE_RW(ads->ds_ctl3) = set11nRate(i->rates, 0)
-                       | set11nRate(i->rates, 1)
-                       | set11nRate(i->rates, 2)
-                       | set11nRate(i->rates, 3);
-       } else {
--              ACCESS_ONCE(ads->ds_ctl2) = 0;
--              ACCESS_ONCE(ads->ds_ctl3) = 0;
-+              ACCESS_ONCE_RW(ads->ds_ctl2) = 0;
-+              ACCESS_ONCE_RW(ads->ds_ctl3) = 0;
-       }
-       if (!i->is_first) {
--              ACCESS_ONCE(ads->ds_ctl0) = 0;
--              ACCESS_ONCE(ads->ds_ctl1) = ctl1;
--              ACCESS_ONCE(ads->ds_ctl6) = ctl6;
-+              ACCESS_ONCE_RW(ads->ds_ctl0) = 0;
-+              ACCESS_ONCE_RW(ads->ds_ctl1) = ctl1;
-+              ACCESS_ONCE_RW(ads->ds_ctl6) = ctl6;
-               return;
-       }
-@@ -279,7 +279,7 @@
-               break;
-       }
--      ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
-+      ACCESS_ONCE_RW(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
-               | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-               | SM(i->txpower[0], AR_XmitPower0)
-               | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
-@@ -289,27 +289,27 @@
-               | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
-                  (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
--      ACCESS_ONCE(ads->ds_ctl1) = ctl1;
--      ACCESS_ONCE(ads->ds_ctl6) = ctl6;
-+      ACCESS_ONCE_RW(ads->ds_ctl1) = ctl1;
-+      ACCESS_ONCE_RW(ads->ds_ctl6) = ctl6;
-       if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST)
-               return;
--      ACCESS_ONCE(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0)
-+      ACCESS_ONCE_RW(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0)
-               | set11nPktDurRTSCTS(i->rates, 1);
--      ACCESS_ONCE(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2)
-+      ACCESS_ONCE_RW(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2)
-               | set11nPktDurRTSCTS(i->rates, 3);
--      ACCESS_ONCE(ads->ds_ctl7) = set11nRateFlags(i->rates, 0)
-+      ACCESS_ONCE_RW(ads->ds_ctl7) = set11nRateFlags(i->rates, 0)
-               | set11nRateFlags(i->rates, 1)
-               | set11nRateFlags(i->rates, 2)
-               | set11nRateFlags(i->rates, 3)
-               | SM(i->rtscts_rate, AR_RTSCTSRate);
--      ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower[1], AR_XmitPower1);
--      ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower[2], AR_XmitPower2);
--      ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower[3], AR_XmitPower3);
-+      ACCESS_ONCE_RW(ads->ds_ctl9) = SM(i->txpower[1], AR_XmitPower1);
-+      ACCESS_ONCE_RW(ads->ds_ctl10) = SM(i->txpower[2], AR_XmitPower2);
-+      ACCESS_ONCE_RW(ads->ds_ctl11) = SM(i->txpower[3], AR_XmitPower3);
- }
- static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/ar9003_mac.c backports-4.2.6-1/drivers/net/wireless/ath/ath9k/ar9003_mac.c
---- backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/ar9003_mac.c  2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ath/ath9k/ar9003_mac.c      2016-01-27 12:26:21.286626323 +0100
-@@ -39,47 +39,47 @@
-             (i->qcu << AR_TxQcuNum_S) | desc_len;
-       checksum += val;
--      ACCESS_ONCE(ads->info) = val;
-+      ACCESS_ONCE_RW(ads->info) = val;
-       checksum += i->link;
--      ACCESS_ONCE(ads->link) = i->link;
-+      ACCESS_ONCE_RW(ads->link) = i->link;
-       checksum += i->buf_addr[0];
--      ACCESS_ONCE(ads->data0) = i->buf_addr[0];
-+      ACCESS_ONCE_RW(ads->data0) = i->buf_addr[0];
-       checksum += i->buf_addr[1];
--      ACCESS_ONCE(ads->data1) = i->buf_addr[1];
-+      ACCESS_ONCE_RW(ads->data1) = i->buf_addr[1];
-       checksum += i->buf_addr[2];
--      ACCESS_ONCE(ads->data2) = i->buf_addr[2];
-+      ACCESS_ONCE_RW(ads->data2) = i->buf_addr[2];
-       checksum += i->buf_addr[3];
--      ACCESS_ONCE(ads->data3) = i->buf_addr[3];
-+      ACCESS_ONCE_RW(ads->data3) = i->buf_addr[3];
-       checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen);
--      ACCESS_ONCE(ads->ctl3) = val;
-+      ACCESS_ONCE_RW(ads->ctl3) = val;
-       checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen);
--      ACCESS_ONCE(ads->ctl5) = val;
-+      ACCESS_ONCE_RW(ads->ctl5) = val;
-       checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen);
--      ACCESS_ONCE(ads->ctl7) = val;
-+      ACCESS_ONCE_RW(ads->ctl7) = val;
-       checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen);
--      ACCESS_ONCE(ads->ctl9) = val;
-+      ACCESS_ONCE_RW(ads->ctl9) = val;
-       checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff);
--      ACCESS_ONCE(ads->ctl10) = checksum;
-+      ACCESS_ONCE_RW(ads->ctl10) = checksum;
-       if (i->is_first || i->is_last) {
--              ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0)
-+              ACCESS_ONCE_RW(ads->ctl13) = set11nTries(i->rates, 0)
-                       | set11nTries(i->rates, 1)
-                       | set11nTries(i->rates, 2)
-                       | set11nTries(i->rates, 3)
-                       | (i->dur_update ? AR_DurUpdateEna : 0)
-                       | SM(0, AR_BurstDur);
--              ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0)
-+              ACCESS_ONCE_RW(ads->ctl14) = set11nRate(i->rates, 0)
-                       | set11nRate(i->rates, 1)
-                       | set11nRate(i->rates, 2)
-                       | set11nRate(i->rates, 3);
-       } else {
--              ACCESS_ONCE(ads->ctl13) = 0;
--              ACCESS_ONCE(ads->ctl14) = 0;
-+              ACCESS_ONCE_RW(ads->ctl13) = 0;
-+              ACCESS_ONCE_RW(ads->ctl14) = 0;
-       }
-       ads->ctl20 = 0;
-@@ -89,17 +89,17 @@
-       ctl17 = SM(i->keytype, AR_EncrType);
-       if (!i->is_first) {
--              ACCESS_ONCE(ads->ctl11) = 0;
--              ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore;
--              ACCESS_ONCE(ads->ctl15) = 0;
--              ACCESS_ONCE(ads->ctl16) = 0;
--              ACCESS_ONCE(ads->ctl17) = ctl17;
--              ACCESS_ONCE(ads->ctl18) = 0;
--              ACCESS_ONCE(ads->ctl19) = 0;
-+              ACCESS_ONCE_RW(ads->ctl11) = 0;
-+              ACCESS_ONCE_RW(ads->ctl12) = i->is_last ? 0 : AR_TxMore;
-+              ACCESS_ONCE_RW(ads->ctl15) = 0;
-+              ACCESS_ONCE_RW(ads->ctl16) = 0;
-+              ACCESS_ONCE_RW(ads->ctl17) = ctl17;
-+              ACCESS_ONCE_RW(ads->ctl18) = 0;
-+              ACCESS_ONCE_RW(ads->ctl19) = 0;
-               return;
-       }
--      ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
-+      ACCESS_ONCE_RW(ads->ctl11) = (i->pkt_len & AR_FrameLen)
-               | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-               | SM(i->txpower[0], AR_XmitPower0)
-               | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
-@@ -135,26 +135,26 @@
-       val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S;
-       ctl12 |= SM(val, AR_PAPRDChainMask);
--      ACCESS_ONCE(ads->ctl12) = ctl12;
--      ACCESS_ONCE(ads->ctl17) = ctl17;
-+      ACCESS_ONCE_RW(ads->ctl12) = ctl12;
-+      ACCESS_ONCE_RW(ads->ctl17) = ctl17;
--      ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0)
-+      ACCESS_ONCE_RW(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0)
-               | set11nPktDurRTSCTS(i->rates, 1);
--      ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2)
-+      ACCESS_ONCE_RW(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2)
-               | set11nPktDurRTSCTS(i->rates, 3);
--      ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0)
-+      ACCESS_ONCE_RW(ads->ctl18) = set11nRateFlags(i->rates, 0)
-               | set11nRateFlags(i->rates, 1)
-               | set11nRateFlags(i->rates, 2)
-               | set11nRateFlags(i->rates, 3)
-               | SM(i->rtscts_rate, AR_RTSCTSRate);
--      ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
-+      ACCESS_ONCE_RW(ads->ctl19) = AR_Not_Sounding;
--      ACCESS_ONCE(ads->ctl20) = SM(i->txpower[1], AR_XmitPower1);
--      ACCESS_ONCE(ads->ctl21) = SM(i->txpower[2], AR_XmitPower2);
--      ACCESS_ONCE(ads->ctl22) = SM(i->txpower[3], AR_XmitPower3);
-+      ACCESS_ONCE_RW(ads->ctl20) = SM(i->txpower[1], AR_XmitPower1);
-+      ACCESS_ONCE_RW(ads->ctl21) = SM(i->txpower[2], AR_XmitPower2);
-+      ACCESS_ONCE_RW(ads->ctl22) = SM(i->txpower[3], AR_XmitPower3);
- }
- static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/hw.h backports-4.2.6-1/drivers/net/wireless/ath/ath9k/hw.h
---- backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/hw.h  2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ath/ath9k/hw.h      2016-01-27 12:33:44.649931973 +0100
-@@ -671,7 +671,7 @@
- #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
-       bool (*is_aic_enabled)(struct ath_hw *ah);
- #endif /* CPTCFG_ATH9K_BTCOEX_SUPPORT */
--};
-+} __no_const;
- /**
-  * struct ath_spec_scan - parameters for Atheros spectral scan
-@@ -747,7 +747,7 @@
- #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
-       void (*set_bt_ant_diversity)(struct ath_hw *hw, bool enable);
- #endif
--};
-+} __no_const;
- struct ath_nf_limits {
-       s16 max;
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/Kconfig backports-4.2.6-1/drivers/net/wireless/ath/ath9k/Kconfig
---- backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/Kconfig       2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ath/ath9k/Kconfig   2016-01-27 12:34:48.923262299 +0100
-@@ -5,7 +5,6 @@
-       tristate
-       depends on m
-       select ATH_COMMON
--      depends on DEBUG_FS
-       depends on RELAY
- config ATH9K_DFS_DEBUGFS
-       def_bool y
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/main.c backports-4.2.6-1/drivers/net/wireless/ath/ath9k/main.c
---- backports-4.2.6-1.org/drivers/net/wireless/ath/ath9k/main.c        2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ath/ath9k/main.c    2016-01-27 12:26:21.289959656 +0100
-@@ -2574,16 +2574,18 @@
-       if (!ath9k_is_chanctx_enabled())
-               return;
--      ath9k_ops.hw_scan                  = ath9k_hw_scan;
--      ath9k_ops.cancel_hw_scan           = ath9k_cancel_hw_scan;
--      ath9k_ops.remain_on_channel        = ath9k_remain_on_channel;
--      ath9k_ops.cancel_remain_on_channel = ath9k_cancel_remain_on_channel;
--      ath9k_ops.add_chanctx              = ath9k_add_chanctx;
--      ath9k_ops.remove_chanctx           = ath9k_remove_chanctx;
--      ath9k_ops.change_chanctx           = ath9k_change_chanctx;
--      ath9k_ops.assign_vif_chanctx       = ath9k_assign_vif_chanctx;
--      ath9k_ops.unassign_vif_chanctx     = ath9k_unassign_vif_chanctx;
--      ath9k_ops.mgd_prepare_tx           = ath9k_mgd_prepare_tx;
-+      pax_open_kernel();
-+      *(void **)&ath9k_ops.hw_scan                  = ath9k_hw_scan;
-+      *(void **)&ath9k_ops.cancel_hw_scan           = ath9k_cancel_hw_scan;
-+      *(void **)&ath9k_ops.remain_on_channel        = ath9k_remain_on_channel;
-+      *(void **)&ath9k_ops.cancel_remain_on_channel = ath9k_cancel_remain_on_channel;
-+      *(void **)&ath9k_ops.add_chanctx              = ath9k_add_chanctx;
-+      *(void **)&ath9k_ops.remove_chanctx           = ath9k_remove_chanctx;
-+      *(void **)&ath9k_ops.change_chanctx           = ath9k_change_chanctx;
-+      *(void **)&ath9k_ops.assign_vif_chanctx       = ath9k_assign_vif_chanctx;
-+      *(void **)&ath9k_ops.unassign_vif_chanctx     = ath9k_unassign_vif_chanctx;
-+      *(void **)&ath9k_ops.mgd_prepare_tx           = ath9k_mgd_prepare_tx;
-+      pax_close_kernel();
- }
- #endif
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/b43/phy_lp.c backports-4.2.6-1/drivers/net/wireless/b43/phy_lp.c
---- backports-4.2.6-1.org/drivers/net/wireless/b43/phy_lp.c    2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/b43/phy_lp.c        2016-01-27 12:26:21.289959656 +0100
-@@ -2502,7 +2502,7 @@
- {
-       struct ssb_bus *bus = dev->dev->sdev->bus;
--      static const struct b206x_channel *chandata = NULL;
-+      const struct b206x_channel *chandata = NULL;
-       u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
-       u32 freqref, vco_freq, val1, val2, val3, timeout, timeoutref, count;
-       u16 old_comm15, scale;
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/iwlegacy/3945-mac.c backports-4.2.6-1/drivers/net/wireless/iwlegacy/3945-mac.c
---- backports-4.2.6-1.org/drivers/net/wireless/iwlegacy/3945-mac.c     2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/iwlegacy/3945-mac.c 2016-01-27 12:26:21.289959656 +0100
-@@ -3633,7 +3633,9 @@
-        */
-       if (il3945_mod_params.disable_hw_scan) {
-               D_INFO("Disabling hw_scan\n");
--              il3945_mac_ops.hw_scan = NULL;
-+              pax_open_kernel();
-+              *(void **)&il3945_mac_ops.hw_scan = NULL;
-+              pax_close_kernel();
-       }
-       D_INFO("*** LOAD DRIVER ***\n");
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/iwlwifi/dvm/debugfs.c backports-4.2.6-1/drivers/net/wireless/iwlwifi/dvm/debugfs.c
---- backports-4.2.6-1.org/drivers/net/wireless/iwlwifi/dvm/debugfs.c   2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/iwlwifi/dvm/debugfs.c       2016-01-27 12:26:21.289959656 +0100
-@@ -188,7 +188,7 @@
- {
-       struct iwl_priv *priv = file->private_data;
-       char buf[64];
--      int buf_size;
-+      size_t buf_size;
-       u32 offset, len;
-       memset(buf, 0, sizeof(buf));
-@@ -458,7 +458,7 @@
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       u32 reset_flag;
-       memset(buf, 0, sizeof(buf));
-@@ -539,7 +539,7 @@
- {
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       int ht40;
-       memset(buf, 0, sizeof(buf));
-@@ -591,7 +591,7 @@
- {
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       int value;
-       memset(buf, 0, sizeof(buf));
-@@ -683,10 +683,10 @@
- DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
- DEBUGFS_READ_FILE_OPS(current_sleep_command);
--static const char *fmt_value = "  %-30s %10u\n";
--static const char *fmt_hex   = "  %-30s       0x%02X\n";
--static const char *fmt_table = "  %-30s %10u  %10u  %10u  %10u\n";
--static const char *fmt_header =
-+static const char fmt_value[] = "  %-30s %10u\n";
-+static const char fmt_hex[]   = "  %-30s       0x%02X\n";
-+static const char fmt_table[] = "  %-30s %10u  %10u  %10u  %10u\n";
-+static const char fmt_header[] =
-       "%-32s    current  cumulative       delta         max\n";
- static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
-@@ -1856,7 +1856,7 @@
- {
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       int clear;
-       memset(buf, 0, sizeof(buf));
-@@ -1901,7 +1901,7 @@
- {
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       int trace;
-       memset(buf, 0, sizeof(buf));
-@@ -1972,7 +1972,7 @@
- {
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       int missed;
-       memset(buf, 0, sizeof(buf));
-@@ -2013,7 +2013,7 @@
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       int plcp;
-       memset(buf, 0, sizeof(buf));
-@@ -2073,7 +2073,7 @@
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       int flush;
-       memset(buf, 0, sizeof(buf));
-@@ -2163,7 +2163,7 @@
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       int rts;
-       if (!priv->cfg->ht_params)
-@@ -2204,7 +2204,7 @@
- {
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-@@ -2238,7 +2238,7 @@
-       struct iwl_priv *priv = file->private_data;
-       u32 event_log_flag;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       /* check that the interface is up */
-       if (!iwl_is_ready(priv))
-@@ -2292,7 +2292,7 @@
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
-       u32 calib_disabled;
--      int buf_size;
-+      size_t buf_size;
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) - 1);
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/iwlwifi/pcie/trans.c backports-4.2.6-1/drivers/net/wireless/iwlwifi/pcie/trans.c
---- backports-4.2.6-1.org/drivers/net/wireless/iwlwifi/pcie/trans.c    2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/iwlwifi/pcie/trans.c        2016-01-27 12:26:21.289959656 +0100
-@@ -1950,7 +1950,7 @@
-       struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       u32 reset_flag;
-       memset(buf, 0, sizeof(buf));
-@@ -1971,7 +1971,7 @@
- {
-       struct iwl_trans *trans = file->private_data;
-       char buf[8];
--      int buf_size;
-+      size_t buf_size;
-       int csr;
-       memset(buf, 0, sizeof(buf));
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/mac80211_hwsim.c backports-4.2.6-1/drivers/net/wireless/mac80211_hwsim.c
---- backports-4.2.6-1.org/drivers/net/wireless/mac80211_hwsim.c        2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/mac80211_hwsim.c    2016-01-27 12:26:21.289959656 +0100
-@@ -3150,20 +3150,20 @@
-       if (channels < 1)
-               return -EINVAL;
--      mac80211_hwsim_mchan_ops = mac80211_hwsim_ops;
--      mac80211_hwsim_mchan_ops.hw_scan = mac80211_hwsim_hw_scan;
--      mac80211_hwsim_mchan_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan;
--      mac80211_hwsim_mchan_ops.sw_scan_start = NULL;
--      mac80211_hwsim_mchan_ops.sw_scan_complete = NULL;
--      mac80211_hwsim_mchan_ops.remain_on_channel = mac80211_hwsim_roc;
--      mac80211_hwsim_mchan_ops.cancel_remain_on_channel = mac80211_hwsim_croc;
--      mac80211_hwsim_mchan_ops.add_chanctx = mac80211_hwsim_add_chanctx;
--      mac80211_hwsim_mchan_ops.remove_chanctx = mac80211_hwsim_remove_chanctx;
--      mac80211_hwsim_mchan_ops.change_chanctx = mac80211_hwsim_change_chanctx;
--      mac80211_hwsim_mchan_ops.assign_vif_chanctx =
--              mac80211_hwsim_assign_vif_chanctx;
--      mac80211_hwsim_mchan_ops.unassign_vif_chanctx =
--              mac80211_hwsim_unassign_vif_chanctx;
-+      pax_open_kernel();
-+      memcpy((void *)&mac80211_hwsim_mchan_ops, &mac80211_hwsim_ops, sizeof mac80211_hwsim_mchan_ops);
-+      *(void **)&mac80211_hwsim_mchan_ops.hw_scan = mac80211_hwsim_hw_scan;
-+      *(void **)&mac80211_hwsim_mchan_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan;
-+      *(void **)&mac80211_hwsim_mchan_ops.sw_scan_start = NULL;
-+      *(void **)&mac80211_hwsim_mchan_ops.sw_scan_complete = NULL;
-+      *(void **)&mac80211_hwsim_mchan_ops.remain_on_channel = mac80211_hwsim_roc;
-+      *(void **)&mac80211_hwsim_mchan_ops.cancel_remain_on_channel = mac80211_hwsim_croc;
-+      *(void **)&mac80211_hwsim_mchan_ops.add_chanctx = mac80211_hwsim_add_chanctx;
-+      *(void **)&mac80211_hwsim_mchan_ops.remove_chanctx = mac80211_hwsim_remove_chanctx;
-+      *(void **)&mac80211_hwsim_mchan_ops.change_chanctx = mac80211_hwsim_change_chanctx;
-+      *(void **)&mac80211_hwsim_mchan_ops.assign_vif_chanctx = mac80211_hwsim_assign_vif_chanctx;
-+      *(void **)&mac80211_hwsim_mchan_ops.unassign_vif_chanctx = mac80211_hwsim_unassign_vif_chanctx;
-+      pax_close_kernel();
-       spin_lock_init(&hwsim_radio_lock);
-       INIT_LIST_HEAD(&hwsim_radios);
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/rndis_wlan.c backports-4.2.6-1/drivers/net/wireless/rndis_wlan.c
---- backports-4.2.6-1.org/drivers/net/wireless/rndis_wlan.c    2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/rndis_wlan.c        2016-01-27 12:26:21.293292990 +0100
-@@ -1236,7 +1236,7 @@
-       netdev_dbg(usbdev->net, "%s(): %i\n", __func__, rts_threshold);
--      if (rts_threshold < 0 || rts_threshold > 2347)
-+      if (rts_threshold > 2347)
-               rts_threshold = 2347;
-       tmp = cpu_to_le32(rts_threshold);
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/rt2x00/rt2x00.h backports-4.2.6-1/drivers/net/wireless/rt2x00/rt2x00.h
---- backports-4.2.6-1.org/drivers/net/wireless/rt2x00/rt2x00.h 2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/rt2x00/rt2x00.h     2016-01-27 12:26:21.293292990 +0100
-@@ -375,7 +375,7 @@
-        * for hardware which doesn't support hardware
-        * sequence counting.
-        */
--      atomic_t seqno;
-+      atomic_unchecked_t seqno;
- };
- static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/rt2x00/rt2x00queue.c backports-4.2.6-1/drivers/net/wireless/rt2x00/rt2x00queue.c
---- backports-4.2.6-1.org/drivers/net/wireless/rt2x00/rt2x00queue.c    2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/rt2x00/rt2x00queue.c        2016-01-27 12:26:21.293292990 +0100
-@@ -224,9 +224,9 @@
-        * sequence counter given by mac80211.
-        */
-       if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
--              seqno = atomic_add_return(0x10, &intf->seqno);
-+              seqno = atomic_add_return_unchecked(0x10, &intf->seqno);
-       else
--              seqno = atomic_read(&intf->seqno);
-+              seqno = atomic_read_unchecked(&intf->seqno);
-       hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
-       hdr->seq_ctrl |= cpu_to_le16(seqno);
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ti/wl1251/sdio.c backports-4.2.6-1/drivers/net/wireless/ti/wl1251/sdio.c
---- backports-4.2.6-1.org/drivers/net/wireless/ti/wl1251/sdio.c        2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ti/wl1251/sdio.c    2016-01-27 12:26:21.293292990 +0100
-@@ -282,13 +282,17 @@
-               irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
--              wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
--              wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;
-+              pax_open_kernel();
-+              *(void **)&wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
-+              *(void **)&wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;
-+              pax_close_kernel();
-               wl1251_info("using dedicated interrupt line");
-       } else {
--              wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq;
--              wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq;
-+              pax_open_kernel();
-+              *(void **)&wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq;
-+              *(void **)&wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq;
-+              pax_close_kernel();
-               wl1251_info("using SDIO interrupt");
-       }
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ti/wl12xx/main.c backports-4.2.6-1/drivers/net/wireless/ti/wl12xx/main.c
---- backports-4.2.6-1.org/drivers/net/wireless/ti/wl12xx/main.c        2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ti/wl12xx/main.c    2016-01-27 12:26:21.293292990 +0100
-@@ -655,7 +655,9 @@
-                      sizeof(wl->conf.mem));
-               /* read data preparation is only needed by wl127x */
--              wl->ops->prepare_read = wl127x_prepare_read;
-+              pax_open_kernel();
-+              *(void **)&wl->ops->prepare_read = wl127x_prepare_read;
-+              pax_close_kernel();
-               wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER,
-                             WL127X_IFTYPE_SR_VER,  WL127X_MAJOR_SR_VER,
-@@ -680,7 +682,9 @@
-                      sizeof(wl->conf.mem));
-               /* read data preparation is only needed by wl127x */
--              wl->ops->prepare_read = wl127x_prepare_read;
-+              pax_open_kernel();
-+              *(void **)&wl->ops->prepare_read = wl127x_prepare_read;
-+              pax_close_kernel();
-               wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER,
-                             WL127X_IFTYPE_SR_VER,  WL127X_MAJOR_SR_VER,
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ti/wl18xx/main.c backports-4.2.6-1/drivers/net/wireless/ti/wl18xx/main.c
---- backports-4.2.6-1.org/drivers/net/wireless/ti/wl18xx/main.c        2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ti/wl18xx/main.c    2016-01-27 12:26:21.293292990 +0100
-@@ -1952,8 +1952,10 @@
-       }
-       if (!checksum_param) {
--              wl18xx_ops.set_rx_csum = NULL;
--              wl18xx_ops.init_vif = NULL;
-+              pax_open_kernel();
-+              *(void **)&wl18xx_ops.set_rx_csum = NULL;
-+              *(void **)&wl18xx_ops.init_vif = NULL;
-+              pax_close_kernel();
-       }
-       /* Enable 11a Band only if we have 5G antennas */
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/zd1211rw/zd_usb.c backports-4.2.6-1/drivers/net/wireless/zd1211rw/zd_usb.c
---- backports-4.2.6-1.org/drivers/net/wireless/zd1211rw/zd_usb.c       2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/zd1211rw/zd_usb.c   2016-01-27 12:26:21.293292990 +0100
-@@ -385,7 +385,7 @@
- {
-       struct zd_usb *usb = urb->context;
-       struct zd_usb_interrupt *intr = &usb->intr;
--      int len;
-+      unsigned int len;
-       u16 int_num;
-       ZD_ASSERT(in_interrupt());
-diff -Naur backports-4.2.6-1.org/drivers/nfc/nfcwilink.c backports-4.2.6-1/drivers/nfc/nfcwilink.c
---- backports-4.2.6-1.org/drivers/nfc/nfcwilink.c      2015-11-15 22:19:39.000000000 +0100
-+++ backports-4.2.6-1/drivers/nfc/nfcwilink.c  2016-01-27 12:26:21.293292990 +0100
-@@ -497,7 +497,7 @@
- static int nfcwilink_probe(struct platform_device *pdev)
- {
--      static struct nfcwilink *drv;
-+      struct nfcwilink *drv;
-       int rc;
-       __u32 protocols;
-diff -Naur backports-4.2.6-1.org/include/linux/gracl_compat.h backports-4.2.6-1/include/linux/gracl_compat.h
---- backports-4.2.6-1.org/include/linux/gracl_compat.h 1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/include/linux/gracl_compat.h     2016-01-27 12:26:26.289959354 +0100
-@@ -0,0 +1,156 @@
-+#ifndef GR_ACL_COMPAT_H
-+#define GR_ACL_COMPAT_H
-+
-+#include <linux/resource.h>
-+#include <asm/resource.h>
-+
-+struct sprole_pw_compat {
-+      compat_uptr_t rolename;
-+      unsigned char salt[GR_SALT_LEN];
-+      unsigned char sum[GR_SHA_LEN];
-+};
-+
-+struct gr_hash_struct_compat {
-+      compat_uptr_t table;
-+      compat_uptr_t nametable;
-+      compat_uptr_t first;
-+      __u32 table_size;
-+      __u32 used_size;
-+      int type;
-+};
-+
-+struct acl_subject_label_compat {
-+      compat_uptr_t filename;
-+      compat_u64 inode;
-+      __u32 device;
-+      __u32 mode;
-+      kernel_cap_t cap_mask;
-+      kernel_cap_t cap_lower;
-+      kernel_cap_t cap_invert_audit;
-+
-+      struct compat_rlimit res[GR_NLIMITS];
-+      __u32 resmask;
-+
-+      __u8 user_trans_type;
-+      __u8 group_trans_type;
-+      compat_uptr_t user_transitions;
-+      compat_uptr_t group_transitions;
-+      __u16 user_trans_num;
-+      __u16 group_trans_num;
-+
-+      __u32 sock_families[2];
-+      __u32 ip_proto[8];
-+      __u32 ip_type;
-+      compat_uptr_t ips;
-+      __u32 ip_num;
-+      __u32 inaddr_any_override;
-+
-+      __u32 crashes;
-+      compat_ulong_t expires;
-+
-+      compat_uptr_t parent_subject;
-+      compat_uptr_t hash;
-+      compat_uptr_t prev;
-+      compat_uptr_t next;
-+
-+      compat_uptr_t obj_hash;
-+      __u32 obj_hash_size;
-+      __u16 pax_flags;
-+};
-+
-+struct role_allowed_ip_compat {
-+      __u32 addr;
-+      __u32 netmask;
-+
-+      compat_uptr_t prev;
-+      compat_uptr_t next;
-+};
-+
-+struct role_transition_compat {
-+      compat_uptr_t rolename;
-+
-+      compat_uptr_t prev;
-+      compat_uptr_t next;
-+};
-+
-+struct acl_role_label_compat {
-+      compat_uptr_t rolename;
-+      uid_t uidgid;
-+      __u16 roletype;
-+
-+      __u16 auth_attempts;
-+      compat_ulong_t expires;
-+
-+      compat_uptr_t root_label;
-+      compat_uptr_t hash;
-+
-+      compat_uptr_t prev;
-+      compat_uptr_t next;
-+
-+      compat_uptr_t transitions;
-+      compat_uptr_t allowed_ips;
-+      compat_uptr_t domain_children;
-+      __u16 domain_child_num;
-+
-+      umode_t umask;
-+
-+      compat_uptr_t subj_hash;
-+      __u32 subj_hash_size;
-+};
-+
-+struct user_acl_role_db_compat {
-+      compat_uptr_t r_table;
-+      __u32 num_pointers;
-+      __u32 num_roles;
-+      __u32 num_domain_children;
-+      __u32 num_subjects;
-+      __u32 num_objects;
-+};
-+
-+struct acl_object_label_compat {
-+      compat_uptr_t filename;
-+      compat_u64 inode;
-+      __u32 device;
-+      __u32 mode;
-+
-+      compat_uptr_t nested;
-+      compat_uptr_t globbed;
-+
-+      compat_uptr_t prev;
-+      compat_uptr_t next;
-+};
-+
-+struct acl_ip_label_compat {
-+      compat_uptr_t iface;
-+      __u32 addr;
-+      __u32 netmask;
-+      __u16 low, high;
-+      __u8 mode;
-+      __u32 type;
-+      __u32 proto[8];
-+
-+      compat_uptr_t prev;
-+      compat_uptr_t next;
-+};
-+
-+struct gr_arg_compat {
-+      struct user_acl_role_db_compat role_db;
-+      unsigned char pw[GR_PW_LEN];
-+      unsigned char salt[GR_SALT_LEN];
-+      unsigned char sum[GR_SHA_LEN];
-+      unsigned char sp_role[GR_SPROLE_LEN];
-+      compat_uptr_t sprole_pws;
-+      __u32 segv_device;
-+      compat_u64 segv_inode;
-+      uid_t segv_uid;
-+      __u16 num_sprole_pws;
-+      __u16 mode;
-+};
-+
-+struct gr_arg_wrapper_compat {
-+      compat_uptr_t arg;
-+      __u32 version;
-+      __u32 size;
-+};
-+
-+#endif
-diff -Naur backports-4.2.6-1.org/include/linux/gracl.h backports-4.2.6-1/include/linux/gracl.h
---- backports-4.2.6-1.org/include/linux/gracl.h        1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/include/linux/gracl.h    2016-01-27 12:26:26.289959354 +0100
-@@ -0,0 +1,342 @@
-+#ifndef GR_ACL_H
-+#define GR_ACL_H
-+
-+#include <linux/grdefs.h>
-+#include <linux/resource.h>
-+#include <linux/capability.h>
-+#include <linux/dcache.h>
-+#include <asm/resource.h>
-+
-+/* Major status information */
-+
-+#define GR_VERSION  "grsecurity 3.1"
-+#define GRSECURITY_VERSION 0x3100
-+
-+enum {
-+      GR_SHUTDOWN = 0,
-+      GR_ENABLE = 1,
-+      GR_SPROLE = 2,
-+      GR_OLDRELOAD = 3,
-+      GR_SEGVMOD = 4,
-+      GR_STATUS = 5,
-+      GR_UNSPROLE = 6,
-+      GR_PASSSET = 7,
-+      GR_SPROLEPAM = 8,
-+      GR_RELOAD = 9,
-+};
-+
-+/* Password setup definitions
-+ * kernel/grhash.c */
-+enum {
-+      GR_PW_LEN = 128,
-+      GR_SALT_LEN = 16,
-+      GR_SHA_LEN = 32,
-+};
-+
-+enum {
-+      GR_SPROLE_LEN = 64,
-+};
-+
-+enum {
-+      GR_NO_GLOB = 0,
-+      GR_REG_GLOB,
-+      GR_CREATE_GLOB
-+};
-+
-+#define GR_NLIMITS 32
-+
-+/* Begin Data Structures */
-+
-+struct sprole_pw {
-+      unsigned char *rolename;
-+      unsigned char salt[GR_SALT_LEN];
-+      unsigned char sum[GR_SHA_LEN];  /* 256-bit SHA hash of the password */
-+};
-+
-+struct name_entry {
-+      __u32 key;
-+      u64 inode;
-+      dev_t device;
-+      char *name;
-+      __u16 len;
-+      __u8 deleted;
-+      struct name_entry *prev;
-+      struct name_entry *next;
-+};
-+
-+struct inodev_entry {
-+      struct name_entry *nentry;
-+      struct inodev_entry *prev;
-+      struct inodev_entry *next;
-+};
-+
-+struct acl_role_db {
-+      struct acl_role_label **r_hash;
-+      __u32 r_size;
-+};
-+
-+struct inodev_db {
-+      struct inodev_entry **i_hash;
-+      __u32 i_size;
-+};
-+
-+struct name_db {
-+      struct name_entry **n_hash;
-+      __u32 n_size;
-+};
-+
-+struct crash_uid {
-+      uid_t uid;
-+      unsigned long expires;
-+};
-+
-+struct gr_hash_struct {
-+      void **table;
-+      void **nametable;
-+      void *first;
-+      __u32 table_size;
-+      __u32 used_size;
-+      int type;
-+};
-+
-+/* Userspace Grsecurity ACL data structures */
-+
-+struct acl_subject_label {
-+      char *filename;
-+      u64 inode;
-+      dev_t device;
-+      __u32 mode;
-+      kernel_cap_t cap_mask;
-+      kernel_cap_t cap_lower;
-+      kernel_cap_t cap_invert_audit;
-+
-+      struct rlimit res[GR_NLIMITS];
-+      __u32 resmask;
-+
-+      __u8 user_trans_type;
-+      __u8 group_trans_type;
-+      uid_t *user_transitions;
-+      gid_t *group_transitions;
-+      __u16 user_trans_num;
-+      __u16 group_trans_num;
-+
-+      __u32 sock_families[2];
-+      __u32 ip_proto[8];
-+      __u32 ip_type;
-+      struct acl_ip_label **ips;
-+      __u32 ip_num;
-+      __u32 inaddr_any_override;
-+
-+      __u32 crashes;
-+      unsigned long expires;
-+
-+      struct acl_subject_label *parent_subject;
-+      struct gr_hash_struct *hash;
-+      struct acl_subject_label *prev;
-+      struct acl_subject_label *next;
-+
-+      struct acl_object_label **obj_hash;
-+      __u32 obj_hash_size;
-+      __u16 pax_flags;
-+};
-+
-+struct role_allowed_ip {
-+      __u32 addr;
-+      __u32 netmask;
-+
-+      struct role_allowed_ip *prev;
-+      struct role_allowed_ip *next;
-+};
-+
-+struct role_transition {
-+      char *rolename;
-+
-+      struct role_transition *prev;
-+      struct role_transition *next;
-+};
-+
-+struct acl_role_label {
-+      char *rolename;
-+      uid_t uidgid;
-+      __u16 roletype;
-+
-+      __u16 auth_attempts;
-+      unsigned long expires;
-+
-+      struct acl_subject_label *root_label;
-+      struct gr_hash_struct *hash;
-+
-+      struct acl_role_label *prev;
-+      struct acl_role_label *next;
-+
-+      struct role_transition *transitions;
-+      struct role_allowed_ip *allowed_ips;
-+      uid_t *domain_children;
-+      __u16 domain_child_num;
-+
-+      umode_t umask;
-+
-+      struct acl_subject_label **subj_hash;
-+      __u32 subj_hash_size;
-+};
-+
-+struct user_acl_role_db {
-+      struct acl_role_label **r_table;
-+      __u32 num_pointers;             /* Number of allocations to track */
-+      __u32 num_roles;                /* Number of roles */
-+      __u32 num_domain_children;      /* Number of domain children */
-+      __u32 num_subjects;             /* Number of subjects */
-+      __u32 num_objects;              /* Number of objects */
-+};
-+
-+struct acl_object_label {
-+      char *filename;
-+      u64 inode;
-+      dev_t device;
-+      __u32 mode;
-+
-+      struct acl_subject_label *nested;
-+      struct acl_object_label *globbed;
-+
-+      /* next two structures not used */
-+
-+      struct acl_object_label *prev;
-+      struct acl_object_label *next;
-+};
-+
-+struct acl_ip_label {
-+      char *iface;
-+      __u32 addr;
-+      __u32 netmask;
-+      __u16 low, high;
-+      __u8 mode;
-+      __u32 type;
-+      __u32 proto[8];
-+
-+      /* next two structures not used */
-+
-+      struct acl_ip_label *prev;
-+      struct acl_ip_label *next;
-+};
-+
-+struct gr_arg {
-+      struct user_acl_role_db role_db;
-+      unsigned char pw[GR_PW_LEN];
-+      unsigned char salt[GR_SALT_LEN];
-+      unsigned char sum[GR_SHA_LEN];
-+      unsigned char sp_role[GR_SPROLE_LEN];
-+      struct sprole_pw *sprole_pws;
-+      dev_t segv_device;
-+      u64 segv_inode;
-+      uid_t segv_uid;
-+      __u16 num_sprole_pws;
-+      __u16 mode;
-+};
-+
-+struct gr_arg_wrapper {
-+      struct gr_arg *arg;
-+      __u32 version;
-+      __u32 size;
-+};
-+
-+struct subject_map {
-+      struct acl_subject_label *user;
-+      struct acl_subject_label *kernel;
-+      struct subject_map *prev;
-+      struct subject_map *next;
-+};
-+
-+struct acl_subj_map_db {
-+      struct subject_map **s_hash;
-+      __u32 s_size;
-+};
-+
-+struct gr_policy_state {
-+      struct sprole_pw **acl_special_roles;
-+      __u16 num_sprole_pws;
-+      struct acl_role_label *kernel_role;
-+      struct acl_role_label *role_list;
-+      struct acl_role_label *default_role;
-+      struct acl_role_db acl_role_set;
-+      struct acl_subj_map_db subj_map_set;
-+      struct name_db name_set;
-+      struct inodev_db inodev_set;
-+};
-+
-+struct gr_alloc_state {
-+      unsigned long alloc_stack_next;
-+      unsigned long alloc_stack_size;
-+      void **alloc_stack;
-+};
-+
-+struct gr_reload_state {
-+      struct gr_policy_state oldpolicy;
-+      struct gr_alloc_state oldalloc;
-+      struct gr_policy_state newpolicy;
-+      struct gr_alloc_state newalloc;
-+      struct gr_policy_state *oldpolicy_ptr;
-+      struct gr_alloc_state *oldalloc_ptr;
-+      unsigned char oldmode;
-+};
-+
-+/* End Data Structures Section */
-+
-+/* Hash functions generated by empirical testing by Brad Spengler
-+   Makes good use of the low bits of the inode.  Generally 0-1 times
-+   in loop for successful match.  0-3 for unsuccessful match.
-+   Shift/add algorithm with modulus of table size and an XOR*/
-+
-+static __inline__ unsigned int
-+gr_rhash(const uid_t uid, const __u16 type, const unsigned int sz)
-+{
-+      return ((((uid + type) << (16 + type)) ^ uid) % sz);
-+}
-+
-+ static __inline__ unsigned int
-+gr_shash(const struct acl_subject_label *userp, const unsigned int sz)
-+{
-+      return ((const unsigned long)userp % sz);
-+}
-+
-+static __inline__ unsigned int
-+gr_fhash(const u64 ino, const dev_t dev, const unsigned int sz)
-+{
-+      unsigned int rem;
-+      div_u64_rem((ino + dev) ^ ((ino << 13) + (ino << 23) + (dev << 9)), sz, &rem);
-+      return rem;
-+}
-+
-+static __inline__ unsigned int
-+gr_nhash(const char *name, const __u16 len, const unsigned int sz)
-+{
-+      return full_name_hash((const unsigned char *)name, len) % sz;
-+}
-+
-+#define FOR_EACH_SUBJECT_START(role,subj,iter) \
-+      subj = NULL; \
-+      iter = 0; \
-+      while (iter < role->subj_hash_size) { \
-+              if (subj == NULL) \
-+                      subj = role->subj_hash[iter]; \
-+              if (subj == NULL) { \
-+                      iter++; \
-+                      continue; \
-+              }
-+
-+#define FOR_EACH_SUBJECT_END(subj,iter) \
-+              subj = subj->next; \
-+              if (subj == NULL) \
-+                      iter++; \
-+      }
-+
-+
-+#define FOR_EACH_NESTED_SUBJECT_START(role,subj) \
-+      subj = role->hash->first; \
-+      while (subj != NULL) {
-+
-+#define FOR_EACH_NESTED_SUBJECT_END(subj) \
-+              subj = subj->next; \
-+      }
-+
-+#endif
-+
-diff -Naur backports-4.2.6-1.org/include/linux/gralloc.h backports-4.2.6-1/include/linux/gralloc.h
---- backports-4.2.6-1.org/include/linux/gralloc.h      1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/include/linux/gralloc.h  2016-01-27 12:26:26.289959354 +0100
-@@ -0,0 +1,9 @@
-+#ifndef __GRALLOC_H
-+#define __GRALLOC_H
-+
-+void acl_free_all(void);
-+int acl_alloc_stack_init(unsigned long size);
-+void *acl_alloc(unsigned long len);
-+void *acl_alloc_num(unsigned long num, unsigned long len);
-+
-+#endif
-diff -Naur backports-4.2.6-1.org/include/linux/grdefs.h backports-4.2.6-1/include/linux/grdefs.h
---- backports-4.2.6-1.org/include/linux/grdefs.h       1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/include/linux/grdefs.h   2016-01-27 12:26:26.289959354 +0100
-@@ -0,0 +1,140 @@
-+#ifndef GRDEFS_H
-+#define GRDEFS_H
-+
-+/* Begin grsecurity status declarations */
-+
-+enum {
-+      GR_READY = 0x01,
-+      GR_STATUS_INIT = 0x00   // disabled state
-+};
-+
-+/* Begin  ACL declarations */
-+
-+/* Role flags */
-+
-+enum {
-+      GR_ROLE_USER = 0x0001,
-+      GR_ROLE_GROUP = 0x0002,
-+      GR_ROLE_DEFAULT = 0x0004,
-+      GR_ROLE_SPECIAL = 0x0008,
-+      GR_ROLE_AUTH = 0x0010,
-+      GR_ROLE_NOPW = 0x0020,
-+      GR_ROLE_GOD = 0x0040,
-+      GR_ROLE_LEARN = 0x0080,
-+      GR_ROLE_TPE = 0x0100,
-+      GR_ROLE_DOMAIN = 0x0200,
-+      GR_ROLE_PAM = 0x0400,
-+      GR_ROLE_PERSIST = 0x0800
-+};
-+
-+/* ACL Subject and Object mode flags */
-+enum {
-+      GR_DELETED = 0x80000000
-+};
-+
-+/* ACL Object-only mode flags */
-+enum {
-+      GR_READ         = 0x00000001,
-+      GR_APPEND       = 0x00000002,
-+      GR_WRITE        = 0x00000004,
-+      GR_EXEC         = 0x00000008,
-+      GR_FIND         = 0x00000010,
-+      GR_INHERIT      = 0x00000020,
-+      GR_SETID        = 0x00000040,
-+      GR_CREATE       = 0x00000080,
-+      GR_DELETE       = 0x00000100,
-+      GR_LINK         = 0x00000200,
-+      GR_AUDIT_READ   = 0x00000400,
-+      GR_AUDIT_APPEND = 0x00000800,
-+      GR_AUDIT_WRITE  = 0x00001000,
-+      GR_AUDIT_EXEC   = 0x00002000,
-+      GR_AUDIT_FIND   = 0x00004000,
-+      GR_AUDIT_INHERIT= 0x00008000,
-+      GR_AUDIT_SETID  = 0x00010000,
-+      GR_AUDIT_CREATE = 0x00020000,
-+      GR_AUDIT_DELETE = 0x00040000,
-+      GR_AUDIT_LINK   = 0x00080000,
-+      GR_PTRACERD     = 0x00100000,
-+      GR_NOPTRACE     = 0x00200000,
-+      GR_SUPPRESS     = 0x00400000,
-+      GR_NOLEARN      = 0x00800000,
-+      GR_INIT_TRANSFER= 0x01000000
-+};
-+
-+#define GR_AUDITS (GR_AUDIT_READ | GR_AUDIT_WRITE | GR_AUDIT_APPEND | GR_AUDIT_EXEC | \
-+                 GR_AUDIT_FIND | GR_AUDIT_INHERIT | GR_AUDIT_SETID | \
-+                 GR_AUDIT_CREATE | GR_AUDIT_DELETE | GR_AUDIT_LINK)
-+
-+/* ACL subject-only mode flags */
-+enum {
-+      GR_KILL         = 0x00000001,
-+      GR_VIEW         = 0x00000002,
-+      GR_PROTECTED    = 0x00000004,
-+      GR_LEARN        = 0x00000008,
-+      GR_OVERRIDE     = 0x00000010,
-+      /* just a placeholder, this mode is only used in userspace */
-+      GR_DUMMY        = 0x00000020,
-+      GR_PROTSHM      = 0x00000040,
-+      GR_KILLPROC     = 0x00000080,
-+      GR_KILLIPPROC   = 0x00000100,
-+      /* just a placeholder, this mode is only used in userspace */
-+      GR_NOTROJAN     = 0x00000200,
-+      GR_PROTPROCFD   = 0x00000400,
-+      GR_PROCACCT     = 0x00000800,
-+      GR_RELAXPTRACE  = 0x00001000,
-+      //GR_NESTED     = 0x00002000,
-+      GR_INHERITLEARN = 0x00004000,
-+      GR_PROCFIND     = 0x00008000,
-+      GR_POVERRIDE    = 0x00010000,
-+      GR_KERNELAUTH   = 0x00020000,
-+      GR_ATSECURE     = 0x00040000,
-+      GR_SHMEXEC      = 0x00080000
-+};
-+
-+enum {
-+      GR_PAX_ENABLE_SEGMEXEC  = 0x0001,
-+      GR_PAX_ENABLE_PAGEEXEC  = 0x0002,
-+      GR_PAX_ENABLE_MPROTECT  = 0x0004,
-+      GR_PAX_ENABLE_RANDMMAP  = 0x0008,
-+      GR_PAX_ENABLE_EMUTRAMP  = 0x0010,
-+      GR_PAX_DISABLE_SEGMEXEC = 0x0100,
-+      GR_PAX_DISABLE_PAGEEXEC = 0x0200,
-+      GR_PAX_DISABLE_MPROTECT = 0x0400,
-+      GR_PAX_DISABLE_RANDMMAP = 0x0800,
-+      GR_PAX_DISABLE_EMUTRAMP = 0x1000,
-+};
-+
-+enum {
-+      GR_ID_USER      = 0x01,
-+      GR_ID_GROUP     = 0x02,
-+};
-+
-+enum {
-+      GR_ID_ALLOW     = 0x01,
-+      GR_ID_DENY      = 0x02,
-+};
-+
-+#define GR_CRASH_RES  31
-+#define GR_UIDTABLE_MAX 500
-+
-+/* begin resource learning section */
-+enum {
-+      GR_RLIM_CPU_BUMP = 60,
-+      GR_RLIM_FSIZE_BUMP = 50000,
-+      GR_RLIM_DATA_BUMP = 10000,
-+      GR_RLIM_STACK_BUMP = 1000,
-+      GR_RLIM_CORE_BUMP = 10000,
-+      GR_RLIM_RSS_BUMP = 500000,
-+      GR_RLIM_NPROC_BUMP = 1,
-+      GR_RLIM_NOFILE_BUMP = 5,
-+      GR_RLIM_MEMLOCK_BUMP = 50000,
-+      GR_RLIM_AS_BUMP = 500000,
-+      GR_RLIM_LOCKS_BUMP = 2,
-+      GR_RLIM_SIGPENDING_BUMP = 5,
-+      GR_RLIM_MSGQUEUE_BUMP = 10000,
-+      GR_RLIM_NICE_BUMP = 1,
-+      GR_RLIM_RTPRIO_BUMP = 1,
-+      GR_RLIM_RTTIME_BUMP = 1000000
-+};
-+
-+#endif
-diff -Naur backports-4.2.6-1.org/include/linux/grinternal.h backports-4.2.6-1/include/linux/grinternal.h
---- backports-4.2.6-1.org/include/linux/grinternal.h   1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/include/linux/grinternal.h       2016-01-27 12:26:26.289959354 +0100
-@@ -0,0 +1,230 @@
-+#ifndef __GRINTERNAL_H
-+#define __GRINTERNAL_H
-+
-+#ifdef CONFIG_GRKERNSEC
-+
-+#include <linux/fs.h>
-+#include <linux/mnt_namespace.h>
-+#include <linux/nsproxy.h>
-+#include <linux/gracl.h>
-+#include <linux/grdefs.h>
-+#include <linux/grmsg.h>
-+
-+void gr_add_learn_entry(const char *fmt, ...)
-+      __attribute__ ((format (printf, 1, 2)));
-+__u32 gr_search_file(const struct dentry *dentry, const __u32 mode,
-+                          const struct vfsmount *mnt);
-+__u32 gr_check_create(const struct dentry *new_dentry,
-+                           const struct dentry *parent,
-+                           const struct vfsmount *mnt, const __u32 mode);
-+int gr_check_protected_task(const struct task_struct *task);
-+__u32 to_gr_audit(const __u32 reqmode);
-+int gr_set_acls(const int type);
-+int gr_acl_is_enabled(void);
-+char gr_roletype_to_char(void);
-+
-+void gr_handle_alertkill(struct task_struct *task);
-+char *gr_to_filename(const struct dentry *dentry,
-+                          const struct vfsmount *mnt);
-+char *gr_to_filename1(const struct dentry *dentry,
-+                          const struct vfsmount *mnt);
-+char *gr_to_filename2(const struct dentry *dentry,
-+                          const struct vfsmount *mnt);
-+char *gr_to_filename3(const struct dentry *dentry,
-+                          const struct vfsmount *mnt);
-+
-+extern int grsec_enable_ptrace_readexec;
-+extern int grsec_enable_harden_ptrace;
-+extern int grsec_enable_link;
-+extern int grsec_enable_fifo;
-+extern int grsec_enable_execve;
-+extern int grsec_enable_shm;
-+extern int grsec_enable_execlog;
-+extern int grsec_enable_signal;
-+extern int grsec_enable_audit_ptrace;
-+extern int grsec_enable_forkfail;
-+extern int grsec_enable_time;
-+extern int grsec_enable_rofs;
-+extern int grsec_deny_new_usb;
-+extern int grsec_enable_chroot_shmat;
-+extern int grsec_enable_chroot_mount;
-+extern int grsec_enable_chroot_double;
-+extern int grsec_enable_chroot_pivot;
-+extern int grsec_enable_chroot_chdir;
-+extern int grsec_enable_chroot_chmod;
-+extern int grsec_enable_chroot_mknod;
-+extern int grsec_enable_chroot_fchdir;
-+extern int grsec_enable_chroot_nice;
-+extern int grsec_enable_chroot_execlog;
-+extern int grsec_enable_chroot_caps;
-+extern int grsec_enable_chroot_rename;
-+extern int grsec_enable_chroot_sysctl;
-+extern int grsec_enable_chroot_unix;
-+extern int grsec_enable_symlinkown;
-+extern kgid_t grsec_symlinkown_gid;
-+extern int grsec_enable_tpe;
-+extern kgid_t grsec_tpe_gid;
-+extern int grsec_enable_tpe_all;
-+extern int grsec_enable_tpe_invert;
-+extern int grsec_enable_socket_all;
-+extern kgid_t grsec_socket_all_gid;
-+extern int grsec_enable_socket_client;
-+extern kgid_t grsec_socket_client_gid;
-+extern int grsec_enable_socket_server;
-+extern kgid_t grsec_socket_server_gid;
-+extern kgid_t grsec_audit_gid;
-+extern int grsec_enable_group;
-+extern int grsec_enable_log_rwxmaps;
-+extern int grsec_enable_mount;
-+extern int grsec_enable_chdir;
-+extern int grsec_resource_logging;
-+extern int grsec_enable_blackhole;
-+extern int grsec_lastack_retries;
-+extern int grsec_enable_brute;
-+extern int grsec_enable_harden_ipc;
-+extern int grsec_lock;
-+
-+extern spinlock_t grsec_alert_lock;
-+extern unsigned long grsec_alert_wtime;
-+extern unsigned long grsec_alert_fyet;
-+
-+extern spinlock_t grsec_audit_lock;
-+
-+extern rwlock_t grsec_exec_file_lock;
-+
-+#define gr_task_fullpath(tsk) ((tsk)->exec_file ? \
-+                      gr_to_filename2((tsk)->exec_file->f_path.dentry, \
-+                      (tsk)->exec_file->f_path.mnt) : "/")
-+
-+#define gr_parent_task_fullpath(tsk) ((tsk)->real_parent->exec_file ? \
-+                      gr_to_filename3((tsk)->real_parent->exec_file->f_path.dentry, \
-+                      (tsk)->real_parent->exec_file->f_path.mnt) : "/")
-+
-+#define gr_task_fullpath0(tsk) ((tsk)->exec_file ? \
-+                      gr_to_filename((tsk)->exec_file->f_path.dentry, \
-+                      (tsk)->exec_file->f_path.mnt) : "/")
-+
-+#define gr_parent_task_fullpath0(tsk) ((tsk)->real_parent->exec_file ? \
-+                      gr_to_filename1((tsk)->real_parent->exec_file->f_path.dentry, \
-+                      (tsk)->real_parent->exec_file->f_path.mnt) : "/")
-+
-+#define proc_is_chrooted(tsk_a)  ((tsk_a)->gr_is_chrooted)
-+
-+#define have_same_root(tsk_a,tsk_b) ((tsk_a)->gr_chroot_dentry == (tsk_b)->gr_chroot_dentry)
-+
-+static inline bool gr_is_same_file(const struct file *file1, const struct file *file2)
-+{
-+      if (file1 && file2) {
-+              const struct inode *inode1 = file1->f_path.dentry->d_inode;
-+              const struct inode *inode2 = file2->f_path.dentry->d_inode;
-+              if (inode1->i_ino == inode2->i_ino && inode1->i_sb->s_dev == inode2->i_sb->s_dev)
-+                      return true;
-+      }
-+
-+      return false;
-+}
-+
-+#define GR_CHROOT_CAPS {{ \
-+      CAP_TO_MASK(CAP_LINUX_IMMUTABLE) | CAP_TO_MASK(CAP_NET_ADMIN) | \
-+      CAP_TO_MASK(CAP_SYS_MODULE) | CAP_TO_MASK(CAP_SYS_RAWIO) | \
-+      CAP_TO_MASK(CAP_SYS_PACCT) | CAP_TO_MASK(CAP_SYS_ADMIN) | \
-+      CAP_TO_MASK(CAP_SYS_BOOT) | CAP_TO_MASK(CAP_SYS_TIME) | \
-+      CAP_TO_MASK(CAP_NET_RAW) | CAP_TO_MASK(CAP_SYS_TTY_CONFIG) | \
-+      CAP_TO_MASK(CAP_IPC_OWNER) | CAP_TO_MASK(CAP_SETFCAP), \
-+      CAP_TO_MASK(CAP_SYSLOG) | CAP_TO_MASK(CAP_MAC_ADMIN) }}
-+
-+#define security_learn(normal_msg,args...) \
-+({ \
-+      read_lock(&grsec_exec_file_lock); \
-+      gr_add_learn_entry(normal_msg "\n", ## args); \
-+      read_unlock(&grsec_exec_file_lock); \
-+})
-+
-+enum {
-+      GR_DO_AUDIT,
-+      GR_DONT_AUDIT,
-+      /* used for non-audit messages that we shouldn't kill the task on */
-+      GR_DONT_AUDIT_GOOD
-+};
-+
-+enum {
-+      GR_TTYSNIFF,
-+      GR_RBAC,
-+      GR_RBAC_STR,
-+      GR_STR_RBAC,
-+      GR_RBAC_MODE2,
-+      GR_RBAC_MODE3,
-+      GR_FILENAME,
-+      GR_SYSCTL_HIDDEN,
-+      GR_NOARGS,
-+      GR_ONE_INT,
-+      GR_ONE_INT_TWO_STR,
-+      GR_ONE_STR,
-+      GR_STR_INT,
-+      GR_TWO_STR_INT,
-+      GR_TWO_INT,
-+      GR_TWO_U64,
-+      GR_THREE_INT,
-+      GR_FIVE_INT_TWO_STR,
-+      GR_TWO_STR,
-+      GR_THREE_STR,
-+      GR_FOUR_STR,
-+      GR_STR_FILENAME,
-+      GR_FILENAME_STR,
-+      GR_FILENAME_TWO_INT,
-+      GR_FILENAME_TWO_INT_STR,
-+      GR_TEXTREL,
-+      GR_PTRACE,
-+      GR_RESOURCE,
-+      GR_CAP,
-+      GR_SIG,
-+      GR_SIG2,
-+      GR_CRASH1,
-+      GR_CRASH2,
-+      GR_PSACCT,
-+      GR_RWXMAP,
-+      GR_RWXMAPVMA
-+};
-+
-+#define gr_log_hidden_sysctl(audit, msg, str) gr_log_varargs(audit, msg, GR_SYSCTL_HIDDEN, str)
-+#define gr_log_ttysniff(audit, msg, task) gr_log_varargs(audit, msg, GR_TTYSNIFF, task)
-+#define gr_log_fs_rbac_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_RBAC, dentry, mnt)
-+#define gr_log_fs_rbac_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_RBAC_STR, dentry, mnt, str)
-+#define gr_log_fs_str_rbac(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_RBAC, str, dentry, mnt)
-+#define gr_log_fs_rbac_mode2(audit, msg, dentry, mnt, str1, str2) gr_log_varargs(audit, msg, GR_RBAC_MODE2, dentry, mnt, str1, str2)
-+#define gr_log_fs_rbac_mode3(audit, msg, dentry, mnt, str1, str2, str3) gr_log_varargs(audit, msg, GR_RBAC_MODE3, dentry, mnt, str1, str2, str3)
-+#define gr_log_fs_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_FILENAME, dentry, mnt)
-+#define gr_log_noargs(audit, msg) gr_log_varargs(audit, msg, GR_NOARGS)
-+#define gr_log_int(audit, msg, num) gr_log_varargs(audit, msg, GR_ONE_INT, num)
-+#define gr_log_int_str2(audit, msg, num, str1, str2) gr_log_varargs(audit, msg, GR_ONE_INT_TWO_STR, num, str1, str2)
-+#define gr_log_str(audit, msg, str) gr_log_varargs(audit, msg, GR_ONE_STR, str)
-+#define gr_log_str_int(audit, msg, str, num) gr_log_varargs(audit, msg, GR_STR_INT, str, num)
-+#define gr_log_int_int(audit, msg, num1, num2) gr_log_varargs(audit, msg, GR_TWO_INT, num1, num2)
-+#define gr_log_two_u64(audit, msg, num1, num2) gr_log_varargs(audit, msg, GR_TWO_U64, num1, num2)
-+#define gr_log_int3(audit, msg, num1, num2, num3) gr_log_varargs(audit, msg, GR_THREE_INT, num1, num2, num3)
-+#define gr_log_int5_str2(audit, msg, num1, num2, str1, str2) gr_log_varargs(audit, msg, GR_FIVE_INT_TWO_STR, num1, num2, str1, str2)
-+#define gr_log_str_str(audit, msg, str1, str2) gr_log_varargs(audit, msg, GR_TWO_STR, str1, str2)
-+#define gr_log_str2_int(audit, msg, str1, str2, num) gr_log_varargs(audit, msg, GR_TWO_STR_INT, str1, str2, num)
-+#define gr_log_str3(audit, msg, str1, str2, str3) gr_log_varargs(audit, msg, GR_THREE_STR, str1, str2, str3)
-+#define gr_log_str4(audit, msg, str1, str2, str3, str4) gr_log_varargs(audit, msg, GR_FOUR_STR, str1, str2, str3, str4)
-+#define gr_log_str_fs(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_FILENAME, str, dentry, mnt)
-+#define gr_log_fs_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_FILENAME_STR, dentry, mnt, str)
-+#define gr_log_fs_int2(audit, msg, dentry, mnt, num1, num2) gr_log_varargs(audit, msg, GR_FILENAME_TWO_INT, dentry, mnt, num1, num2)
-+#define gr_log_fs_int2_str(audit, msg, dentry, mnt, num1, num2, str) gr_log_varargs(audit, msg, GR_FILENAME_TWO_INT_STR, dentry, mnt, num1, num2, str)
-+#define gr_log_textrel_ulong_ulong(audit, msg, str, file, ulong1, ulong2) gr_log_varargs(audit, msg, GR_TEXTREL, str, file, ulong1, ulong2)
-+#define gr_log_ptrace(audit, msg, task) gr_log_varargs(audit, msg, GR_PTRACE, task)
-+#define gr_log_res_ulong2_str(audit, msg, task, ulong1, str, ulong2) gr_log_varargs(audit, msg, GR_RESOURCE, task, ulong1, str, ulong2)
-+#define gr_log_cap(audit, msg, task, str) gr_log_varargs(audit, msg, GR_CAP, task, str)
-+#define gr_log_sig_addr(audit, msg, str, addr) gr_log_varargs(audit, msg, GR_SIG, str, addr)
-+#define gr_log_sig_task(audit, msg, task, num) gr_log_varargs(audit, msg, GR_SIG2, task, num)
-+#define gr_log_crash1(audit, msg, task, ulong) gr_log_varargs(audit, msg, GR_CRASH1, task, ulong)
-+#define gr_log_crash2(audit, msg, task, ulong1) gr_log_varargs(audit, msg, GR_CRASH2, task, ulong1)
-+#define gr_log_procacct(audit, msg, task, num1, num2, num3, num4, num5, num6, num7, num8, num9) gr_log_varargs(audit, msg, GR_PSACCT, task, num1, num2, num3, num4, num5, num6, num7, num8, num9)
-+#define gr_log_rwxmap(audit, msg, str) gr_log_varargs(audit, msg, GR_RWXMAP, str)
-+#define gr_log_rwxmap_vma(audit, msg, str) gr_log_varargs(audit, msg, GR_RWXMAPVMA, str)
-+
-+void gr_log_varargs(int audit, const char *msg, int argtypes, ...);
-+
-+#endif
-+
-+#endif
-diff -Naur backports-4.2.6-1.org/include/linux/grmsg.h backports-4.2.6-1/include/linux/grmsg.h
---- backports-4.2.6-1.org/include/linux/grmsg.h        1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/include/linux/grmsg.h    2016-01-27 12:26:26.289959354 +0100
-@@ -0,0 +1,118 @@
-+#define DEFAULTSECMSG "%.256s[%.16s:%d] uid/euid:%u/%u gid/egid:%u/%u, parent %.256s[%.16s:%d] uid/euid:%u/%u gid/egid:%u/%u"
-+#define GR_ACL_PROCACCT_MSG "%.256s[%.16s:%d] IP:%pI4 TTY:%.64s uid/euid:%u/%u gid/egid:%u/%u run time:[%ud %uh %um %us] cpu time:[%ud %uh %um %us] %s with exit code %ld, parent %.256s[%.16s:%d] IP:%pI4 TTY:%.64s uid/euid:%u/%u gid/egid:%u/%u"
-+#define GR_PTRACE_ACL_MSG "denied ptrace of %.950s(%.16s:%d) by "
-+#define GR_STOPMOD_MSG "denied modification of module state by "
-+#define GR_ROFS_BLOCKWRITE_MSG "denied write to block device %.950s by "
-+#define GR_ROFS_MOUNT_MSG "denied writable mount of %.950s by "
-+#define GR_IOPERM_MSG "denied use of ioperm() by "
-+#define GR_IOPL_MSG "denied use of iopl() by "
-+#define GR_SHMAT_ACL_MSG "denied attach of shared memory of UID %u, PID %d, ID %u by "
-+#define GR_UNIX_CHROOT_MSG "denied connect() to abstract AF_UNIX socket outside of chroot by "
-+#define GR_SHMAT_CHROOT_MSG "denied attach of shared memory outside of chroot by "
-+#define GR_MEM_READWRITE_MSG "denied access of range %Lx -> %Lx in /dev/mem by "
-+#define GR_SYMLINK_MSG "not following symlink %.950s owned by %d.%d by "
-+#define GR_LEARN_AUDIT_MSG "%s\t%u\t%u\t%u\t%.4095s\t%.4095s\t%lu\t%lu\t%.4095s\t%lu\t%pI4"
-+#define GR_ID_LEARN_MSG "%s\t%u\t%u\t%u\t%.4095s\t%.4095s\t%c\t%d\t%d\t%d\t%pI4"
-+#define GR_HIDDEN_ACL_MSG "%s access to hidden file %.950s by "
-+#define GR_OPEN_ACL_MSG "%s open of %.950s for%s%s by "
-+#define GR_CREATE_ACL_MSG "%s create of %.950s for%s%s by "
-+#define GR_FIFO_MSG "denied writing FIFO %.950s of %d.%d by "
-+#define GR_MKNOD_CHROOT_MSG "denied mknod of %.950s from chroot by "
-+#define GR_MKNOD_ACL_MSG "%s mknod of %.950s by "
-+#define GR_UNIXCONNECT_ACL_MSG "%s connect() to the unix domain socket %.950s by "
-+#define GR_TTYSNIFF_ACL_MSG "terminal being sniffed by IP:%pI4 %.480s[%.16s:%d], parent %.480s[%.16s:%d] against "
-+#define GR_MKDIR_ACL_MSG "%s mkdir of %.950s by "
-+#define GR_RMDIR_ACL_MSG "%s rmdir of %.950s by "
-+#define GR_UNLINK_ACL_MSG "%s unlink of %.950s by "
-+#define GR_SYMLINK_ACL_MSG "%s symlink from %.480s to %.480s by "
-+#define GR_HARDLINK_MSG "denied hardlink of %.930s (owned by %d.%d) to %.30s for "
-+#define GR_LINK_ACL_MSG "%s link of %.480s to %.480s by "
-+#define GR_INHERIT_ACL_MSG "successful inherit of %.480s's ACL for %.480s by "
-+#define GR_RENAME_ACL_MSG "%s rename of %.480s to %.480s by "
-+#define GR_UNSAFESHARE_EXEC_ACL_MSG "denied exec with cloned fs of %.950s by "
-+#define GR_PTRACE_EXEC_ACL_MSG "denied ptrace of %.950s by "
-+#define GR_EXEC_ACL_MSG "%s execution of %.950s by "
-+#define GR_EXEC_TPE_MSG "denied untrusted exec (due to %.70s) of %.950s by "
-+#define GR_SEGVSTART_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning uid %u from login for %lu seconds"
-+#define GR_SEGVNOSUID_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning execution for %lu seconds"
-+#define GR_MOUNT_CHROOT_MSG "denied mount of %.256s as %.930s from chroot by "
-+#define GR_PIVOT_CHROOT_MSG "denied pivot_root from chroot by "
-+#define GR_TRUNCATE_ACL_MSG "%s truncate of %.950s by "
-+#define GR_ATIME_ACL_MSG "%s access time change of %.950s by "
-+#define GR_ACCESS_ACL_MSG "%s access of %.950s for%s%s%s by "
-+#define GR_CHROOT_CHROOT_MSG "denied double chroot to %.950s by "
-+#define GR_CHROOT_RENAME_MSG "denied bad rename of %.950s out of a chroot by "
-+#define GR_CHMOD_CHROOT_MSG "denied chmod +s of %.950s by "
-+#define GR_CHMOD_ACL_MSG "%s chmod of %.950s by "
-+#define GR_CHROOT_FCHDIR_MSG "denied fchdir outside of chroot to %.950s by "
-+#define GR_CHROOT_FHANDLE_MSG "denied use of file handles inside chroot by "
-+#define GR_CHOWN_ACL_MSG "%s chown of %.950s by "
-+#define GR_SETXATTR_ACL_MSG "%s setting extended attribute of %.950s by "
-+#define GR_REMOVEXATTR_ACL_MSG "%s removing extended attribute of %.950s by "
-+#define GR_WRITLIB_ACL_MSG "denied load of writable library %.950s by "
-+#define GR_INITF_ACL_MSG "init_variables() failed %s by "
-+#define GR_DISABLED_ACL_MSG "Error loading %s, trying to run kernel with acls disabled. To disable acls at startup use <kernel image name> gracl=off from your boot loader"
-+#define GR_DEV_ACL_MSG "/dev/grsec: %d bytes sent %d required, being fed garbage by "
-+#define GR_SHUTS_ACL_MSG "shutdown auth success for "
-+#define GR_SHUTF_ACL_MSG "shutdown auth failure for "
-+#define GR_SHUTI_ACL_MSG "ignoring shutdown for disabled RBAC system for "
-+#define GR_SEGVMODS_ACL_MSG "segvmod auth success for "
-+#define GR_SEGVMODF_ACL_MSG "segvmod auth failure for "
-+#define GR_SEGVMODI_ACL_MSG "ignoring segvmod for disabled RBAC system for "
-+#define GR_ENABLE_ACL_MSG "%s RBAC system loaded by "
-+#define GR_ENABLEF_ACL_MSG "unable to load %s for "
-+#define GR_RELOADI_ACL_MSG "ignoring reload request for disabled RBAC system"
-+#define GR_RELOAD_ACL_MSG "%s RBAC system reloaded by "
-+#define GR_RELOADF_ACL_MSG "failed reload of %s for "
-+#define GR_SPROLEI_ACL_MSG "ignoring change to special role for disabled RBAC system for "
-+#define GR_SPROLES_ACL_MSG "successful change to special role %s (id %d) by "
-+#define GR_SPROLEL_ACL_MSG "special role %s (id %d) exited by "
-+#define GR_SPROLEF_ACL_MSG "special role %s failure for "
-+#define GR_UNSPROLEI_ACL_MSG "ignoring unauth of special role for disabled RBAC system for "
-+#define GR_UNSPROLES_ACL_MSG "successful unauth of special role %s (id %d) by "
-+#define GR_INVMODE_ACL_MSG "invalid mode %d by "
-+#define GR_PRIORITY_CHROOT_MSG "denied priority change of process (%.16s:%d) by "
-+#define GR_FAILFORK_MSG "failed fork with errno %s by "
-+#define GR_NICE_CHROOT_MSG "denied priority change by "
-+#define GR_UNISIGLOG_MSG "%.32s occurred at %p in "
-+#define GR_DUALSIGLOG_MSG "signal %d sent to " DEFAULTSECMSG " by "
-+#define GR_SIG_ACL_MSG "denied send of signal %d to protected task " DEFAULTSECMSG " by "
-+#define GR_SYSCTL_MSG "denied modification of grsecurity sysctl value : %.32s by "
-+#define GR_SYSCTL_ACL_MSG "%s sysctl of %.950s for%s%s by "
-+#define GR_TIME_MSG "time set by "
-+#define GR_DEFACL_MSG "fatal: unable to find subject for (%.16s:%d), loaded by "
-+#define GR_MMAP_ACL_MSG "%s executable mmap of %.950s by "
-+#define GR_MPROTECT_ACL_MSG "%s executable mprotect of %.950s by "
-+#define GR_SOCK_MSG "denied socket(%.16s,%.16s,%.16s) by "
-+#define GR_SOCK_NOINET_MSG "denied socket(%.16s,%.16s,%d) by "
-+#define GR_BIND_MSG "denied bind() by "
-+#define GR_CONNECT_MSG "denied connect() by "
-+#define GR_BIND_ACL_MSG "denied bind() to %pI4 port %u sock type %.16s protocol %.16s by "
-+#define GR_CONNECT_ACL_MSG "denied connect() to %pI4 port %u sock type %.16s protocol %.16s by "
-+#define GR_IP_LEARN_MSG "%s\t%u\t%u\t%u\t%.4095s\t%.4095s\t%pI4\t%u\t%u\t%u\t%u\t%pI4"
-+#define GR_EXEC_CHROOT_MSG "exec of %.980s within chroot by process "
-+#define GR_CAP_ACL_MSG "use of %s denied for "
-+#define GR_CAP_CHROOT_MSG "use of %s in chroot denied for "
-+#define GR_CAP_ACL_MSG2 "use of %s permitted for "
-+#define GR_USRCHANGE_ACL_MSG "change to uid %u denied for "
-+#define GR_GRPCHANGE_ACL_MSG "change to gid %u denied for "
-+#define GR_REMOUNT_AUDIT_MSG "remount of %.256s by "
-+#define GR_UNMOUNT_AUDIT_MSG "unmount of %.256s by "
-+#define GR_MOUNT_AUDIT_MSG "mount of %.256s to %.256s by "
-+#define GR_CHDIR_AUDIT_MSG "chdir to %.980s by "
-+#define GR_EXEC_AUDIT_MSG "exec of %.930s (%.128s) by "
-+#define GR_RESOURCE_MSG "denied resource overstep by requesting %lu for %.16s against limit %lu for "
-+#define GR_RWXMMAP_MSG "denied RWX mmap of %.950s by "
-+#define GR_RWXMPROTECT_MSG "denied RWX mprotect of %.950s by "
-+#define GR_TEXTREL_AUDIT_MSG "allowed %s text relocation transition in %.950s, VMA:0x%08lx 0x%08lx by "
-+#define GR_PTGNUSTACK_MSG "denied marking stack executable as requested by PT_GNU_STACK marking in %.950s by "
-+#define GR_VM86_MSG "denied use of vm86 by "
-+#define GR_PTRACE_AUDIT_MSG "process %.950s(%.16s:%d) attached to via ptrace by "
-+#define GR_PTRACE_READEXEC_MSG "denied ptrace of unreadable binary %.950s by "
-+#define GR_INIT_TRANSFER_MSG "persistent special role transferred privilege to init by "
-+#define GR_BADPROCPID_MSG "denied read of sensitive /proc/pid/%s entry via fd passed across exec by "
-+#define GR_SYMLINKOWNER_MSG "denied following symlink %.950s since symlink owner %u does not match target owner %u, by "
-+#define GR_BRUTE_DAEMON_MSG "bruteforce prevention initiated for the next 30 minutes or until service restarted, stalling each fork 30 seconds.  Please investigate the crash report for "
-+#define GR_BRUTE_SUID_MSG "bruteforce prevention initiated due to crash of %.950s against uid %u, banning suid/sgid execs for %u minutes.  Please investigate the crash report for "
-+#define GR_IPC_DENIED_MSG "denied %s of overly-permissive IPC object with creator uid %u by "
-+#define GR_MSRWRITE_MSG "denied write to CPU MSR by "
-diff -Naur backports-4.2.6-1.org/include/linux/grsecurity.h backports-4.2.6-1/include/linux/grsecurity.h
---- backports-4.2.6-1.org/include/linux/grsecurity.h   1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/include/linux/grsecurity.h       2016-01-27 12:26:26.289959354 +0100
-@@ -0,0 +1,255 @@
-+#ifndef GR_SECURITY_H
-+#define GR_SECURITY_H
-+#include <linux/fs.h>
-+#include <linux/fs_struct.h>
-+#include <linux/binfmts.h>
-+#include <linux/gracl.h>
-+
-+/* notify of brain-dead configs */
-+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_GRKERNSEC_KMEM)
-+#error "CONFIG_DEBUG_FS being enabled is a security risk when CONFIG_GRKERNSEC_KMEM is enabled"
-+#endif
-+#if defined(CONFIG_PROC_PAGE_MONITOR) && defined(CONFIG_GRKERNSEC)
-+#error "CONFIG_PROC_PAGE_MONITOR is a security risk"
-+#endif
-+#if defined(CONFIG_GRKERNSEC_PROC_USER) && defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
-+#error "CONFIG_GRKERNSEC_PROC_USER and CONFIG_GRKERNSEC_PROC_USERGROUP cannot both be enabled."
-+#endif
-+#if defined(CONFIG_GRKERNSEC_PROC) && !defined(CONFIG_GRKERNSEC_PROC_USER) && !defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
-+#error "CONFIG_GRKERNSEC_PROC enabled, but neither CONFIG_GRKERNSEC_PROC_USER nor CONFIG_GRKERNSEC_PROC_USERGROUP enabled"
-+#endif
-+#if defined(CONFIG_PAX_NOEXEC) && !defined(CONFIG_PAX_PAGEEXEC) && !defined(CONFIG_PAX_SEGMEXEC) && !defined(CONFIG_PAX_KERNEXEC)
-+#error "CONFIG_PAX_NOEXEC enabled, but PAGEEXEC, SEGMEXEC, and KERNEXEC are disabled."
-+#endif
-+#if defined(CONFIG_PAX_ASLR) && !defined(CONFIG_PAX_RANDKSTACK) && !defined(CONFIG_PAX_RANDUSTACK) && !defined(CONFIG_PAX_RANDMMAP)
-+#error "CONFIG_PAX_ASLR enabled, but RANDKSTACK, RANDUSTACK, and RANDMMAP are disabled."
-+#endif
-+#if defined(CONFIG_PAX) && !defined(CONFIG_PAX_NOEXEC) && !defined(CONFIG_PAX_ASLR)
-+#error "CONFIG_PAX enabled, but no PaX options are enabled."
-+#endif
-+
-+int gr_handle_new_usb(void);
-+
-+void gr_handle_brute_attach(int dumpable);
-+void gr_handle_brute_check(void);
-+void gr_handle_kernel_exploit(void);
-+
-+char gr_roletype_to_char(void);
-+
-+int gr_proc_is_restricted(void);
-+
-+int gr_acl_enable_at_secure(void);
-+
-+int gr_check_user_change(kuid_t real, kuid_t effective, kuid_t fs);
-+int gr_check_group_change(kgid_t real, kgid_t effective, kgid_t fs);
-+
-+int gr_learn_cap(const struct task_struct *task, const struct cred *cred, const int cap);
-+
-+void gr_del_task_from_ip_table(struct task_struct *p);
-+
-+int gr_pid_is_chrooted(struct task_struct *p);
-+int gr_handle_chroot_fowner(struct pid *pid, enum pid_type type);
-+int gr_handle_chroot_nice(void);
-+int gr_handle_chroot_sysctl(const int op);
-+int gr_handle_chroot_setpriority(struct task_struct *p,
-+                                      const int niceval);
-+int gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt);
-+int gr_chroot_fhandle(void);
-+int gr_handle_chroot_chroot(const struct dentry *dentry,
-+                                 const struct vfsmount *mnt);
-+void gr_handle_chroot_chdir(const struct path *path);
-+int gr_handle_chroot_chmod(const struct dentry *dentry,
-+                                const struct vfsmount *mnt, const int mode);
-+int gr_handle_chroot_mknod(const struct dentry *dentry,
-+                                const struct vfsmount *mnt, const int mode);
-+int gr_handle_chroot_mount(const struct dentry *dentry,
-+                                const struct vfsmount *mnt,
-+                                const char *dev_name);
-+int gr_handle_chroot_pivot(void);
-+int gr_handle_chroot_unix(const pid_t pid);
-+
-+int gr_handle_rawio(const struct inode *inode);
-+
-+void gr_handle_ioperm(void);
-+void gr_handle_iopl(void);
-+void gr_handle_msr_write(void);
-+
-+umode_t gr_acl_umask(void);
-+
-+int gr_tpe_allow(const struct file *file);
-+
-+void gr_set_chroot_entries(struct task_struct *task, const struct path *path);
-+void gr_clear_chroot_entries(struct task_struct *task);
-+
-+void gr_log_forkfail(const int retval);
-+void gr_log_timechange(void);
-+void gr_log_signal(const int sig, const void *addr, const struct task_struct *t);
-+void gr_log_chdir(const struct dentry *dentry,
-+                       const struct vfsmount *mnt);
-+void gr_log_chroot_exec(const struct dentry *dentry,
-+                             const struct vfsmount *mnt);
-+void gr_log_remount(const char *devname, const int retval);
-+void gr_log_unmount(const char *devname, const int retval);
-+void gr_log_mount(const char *from, struct path *to, const int retval);
-+void gr_log_textrel(struct vm_area_struct *vma, bool is_textrel_rw);
-+void gr_log_ptgnustack(struct file *file);
-+void gr_log_rwxmmap(struct file *file);
-+void gr_log_rwxmprotect(struct vm_area_struct *vma);
-+
-+int gr_handle_follow_link(const struct dentry *dentry,
-+                               const struct vfsmount *mnt);
-+int gr_handle_fifo(const struct dentry *dentry,
-+                        const struct vfsmount *mnt,
-+                        const struct dentry *dir, const int flag,
-+                        const int acc_mode);
-+int gr_handle_hardlink(const struct dentry *dentry,
-+                            const struct vfsmount *mnt,
-+                            const struct filename *to);
-+
-+int gr_is_capable(const int cap);
-+int gr_is_capable_nolog(const int cap);
-+int gr_task_is_capable(const struct task_struct *task, const struct cred *cred, const int cap);
-+int gr_task_is_capable_nolog(const struct task_struct *task, const int cap);
-+
-+void gr_copy_label(struct task_struct *tsk);
-+void gr_handle_crash(struct task_struct *task, const int sig);
-+int gr_handle_signal(const struct task_struct *p, const int sig);
-+int gr_check_crash_uid(const kuid_t uid);
-+int gr_check_protected_task(const struct task_struct *task);
-+int gr_check_protected_task_fowner(struct pid *pid, enum pid_type type);
-+int gr_acl_handle_mmap(const struct file *file,
-+                            const unsigned long prot);
-+int gr_acl_handle_mprotect(const struct file *file,
-+                                const unsigned long prot);
-+int gr_check_hidden_task(const struct task_struct *tsk);
-+__u32 gr_acl_handle_truncate(const struct dentry *dentry,
-+                                  const struct vfsmount *mnt);
-+__u32 gr_acl_handle_utime(const struct dentry *dentry,
-+                               const struct vfsmount *mnt);
-+__u32 gr_acl_handle_access(const struct dentry *dentry,
-+                                const struct vfsmount *mnt, const int fmode);
-+__u32 gr_acl_handle_chmod(const struct dentry *dentry,
-+                               const struct vfsmount *mnt, umode_t *mode);
-+__u32 gr_acl_handle_chown(const struct dentry *dentry,
-+                               const struct vfsmount *mnt);
-+__u32 gr_acl_handle_setxattr(const struct dentry *dentry,
-+                               const struct vfsmount *mnt);
-+__u32 gr_acl_handle_removexattr(const struct dentry *dentry,
-+                               const struct vfsmount *mnt);
-+int gr_handle_ptrace(struct task_struct *task, const long request);
-+int gr_handle_proc_ptrace(struct task_struct *task);
-+__u32 gr_acl_handle_execve(const struct dentry *dentry,
-+                                const struct vfsmount *mnt);
-+int gr_check_crash_exec(const struct file *filp);
-+int gr_acl_is_enabled(void);
-+void gr_set_role_label(struct task_struct *task, const kuid_t uid,
-+                            const kgid_t gid);
-+int gr_set_proc_label(const struct dentry *dentry,
-+                      const struct vfsmount *mnt,
-+                      const int unsafe_flags);
-+__u32 gr_acl_handle_hidden_file(const struct dentry *dentry,
-+                              const struct vfsmount *mnt);
-+__u32 gr_acl_handle_open(const struct dentry *dentry,
-+                              const struct vfsmount *mnt, int acc_mode);
-+__u32 gr_acl_handle_creat(const struct dentry *dentry,
-+                               const struct dentry *p_dentry,
-+                               const struct vfsmount *p_mnt,
-+                               int open_flags, int acc_mode, const int imode);
-+void gr_handle_create(const struct dentry *dentry,
-+                           const struct vfsmount *mnt);
-+void gr_handle_proc_create(const struct dentry *dentry,
-+                         const struct inode *inode);
-+__u32 gr_acl_handle_mknod(const struct dentry *new_dentry,
-+                               const struct dentry *parent_dentry,
-+                               const struct vfsmount *parent_mnt,
-+                               const int mode);
-+__u32 gr_acl_handle_mkdir(const struct dentry *new_dentry,
-+                               const struct dentry *parent_dentry,
-+                               const struct vfsmount *parent_mnt);
-+__u32 gr_acl_handle_rmdir(const struct dentry *dentry,
-+                               const struct vfsmount *mnt);
-+void gr_handle_delete(const u64 ino, const dev_t dev);
-+__u32 gr_acl_handle_unlink(const struct dentry *dentry,
-+                                const struct vfsmount *mnt);
-+__u32 gr_acl_handle_symlink(const struct dentry *new_dentry,
-+                                 const struct dentry *parent_dentry,
-+                                 const struct vfsmount *parent_mnt,
-+                                 const struct filename *from);
-+__u32 gr_acl_handle_link(const struct dentry *new_dentry,
-+                              const struct dentry *parent_dentry,
-+                              const struct vfsmount *parent_mnt,
-+                              const struct dentry *old_dentry,
-+                              const struct vfsmount *old_mnt, const struct filename *to);
-+int gr_handle_symlink_owner(const struct path *link, const struct inode *target);
-+int gr_acl_handle_rename(struct dentry *new_dentry,
-+                              struct dentry *parent_dentry,
-+                              const struct vfsmount *parent_mnt,
-+                              struct dentry *old_dentry,
-+                              struct inode *old_parent_inode,
-+                              struct vfsmount *old_mnt, const struct filename *newname, unsigned int flags);
-+void gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
-+                              struct dentry *old_dentry,
-+                              struct dentry *new_dentry,
-+                              struct vfsmount *mnt, const __u8 replace, unsigned int flags);
-+__u32 gr_check_link(const struct dentry *new_dentry,
-+                         const struct dentry *parent_dentry,
-+                         const struct vfsmount *parent_mnt,
-+                         const struct dentry *old_dentry,
-+                         const struct vfsmount *old_mnt);
-+int gr_acl_handle_filldir(const struct file *file, const char *name,
-+                               const unsigned int namelen, const u64 ino);
-+
-+__u32 gr_acl_handle_unix(const struct dentry *dentry,
-+                              const struct vfsmount *mnt);
-+void gr_acl_handle_exit(void);
-+void gr_acl_handle_psacct(struct task_struct *task, const long code);
-+int gr_acl_handle_procpidmem(const struct task_struct *task);
-+int gr_handle_rofs_mount(struct dentry *dentry, struct vfsmount *mnt, int mnt_flags);
-+int gr_handle_rofs_blockwrite(struct dentry *dentry, struct vfsmount *mnt, int acc_mode);
-+void gr_audit_ptrace(struct task_struct *task);
-+dev_t gr_get_dev_from_dentry(struct dentry *dentry);
-+u64 gr_get_ino_from_dentry(struct dentry *dentry);
-+void gr_put_exec_file(struct task_struct *task);
-+
-+int gr_get_symlinkown_enabled(void);
-+
-+int gr_ptrace_readexec(struct file *file, int unsafe_flags);
-+
-+void gr_inc_chroot_refcnts(struct dentry *dentry, struct vfsmount *mnt);
-+void gr_dec_chroot_refcnts(struct dentry *dentry, struct vfsmount *mnt);
-+int gr_bad_chroot_rename(struct dentry *olddentry, struct vfsmount *oldmnt,
-+                       struct dentry *newdentry, struct vfsmount *newmnt);
-+
-+#ifdef CONFIG_GRKERNSEC_RESLOG
-+extern void gr_log_resource(const struct task_struct *task, const int res,
-+                                 const unsigned long wanted, const int gt);
-+#else
-+static inline void gr_log_resource(const struct task_struct *task, const int res,
-+                                 const unsigned long wanted, const int gt)
-+{
-+}
-+#endif
-+
-+#ifdef CONFIG_GRKERNSEC
-+void task_grsec_rbac(struct seq_file *m, struct task_struct *p);
-+void gr_handle_vm86(void);
-+void gr_handle_mem_readwrite(u64 from, u64 to);
-+
-+void gr_log_badprocpid(const char *entry);
-+
-+extern int grsec_enable_dmesg;
-+extern int grsec_disable_privio;
-+
-+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
-+extern kgid_t grsec_proc_gid;
-+#endif
-+
-+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
-+extern int grsec_enable_chroot_findtask;
-+#endif
-+#ifdef CONFIG_GRKERNSEC_SETXID
-+extern int grsec_enable_setxid;
-+#endif
-+#endif
-+
-+#endif
-diff -Naur backports-4.2.6-1.org/include/linux/grsock.h backports-4.2.6-1/include/linux/grsock.h
---- backports-4.2.6-1.org/include/linux/grsock.h       1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/include/linux/grsock.h   2016-01-27 12:26:26.289959354 +0100
-@@ -0,0 +1,19 @@
-+#ifndef __GRSOCK_H
-+#define __GRSOCK_H
-+
-+extern void gr_attach_curr_ip(const struct sock *sk);
-+extern int gr_handle_sock_all(const int family, const int type,
-+                            const int protocol);
-+extern int gr_handle_sock_server(const struct sockaddr *sck);
-+extern int gr_handle_sock_server_other(const struct sock *sck);
-+extern int gr_handle_sock_client(const struct sockaddr *sck);
-+extern int gr_search_connect(struct socket * sock,
-+                           struct sockaddr_in * addr);
-+extern int gr_search_bind(struct socket * sock,
-+                        struct sockaddr_in * addr);
-+extern int gr_search_listen(struct socket * sock);
-+extern int gr_search_accept(struct socket * sock);
-+extern int gr_search_socket(const int domain, const int type,
-+                          const int protocol);
-+
-+#endif
-diff -Naur backports-4.2.6-1.org/include/linux/netfilter/xt_gradm.h backports-4.2.6-1/include/linux/netfilter/xt_gradm.h
---- backports-4.2.6-1.org/include/linux/netfilter/xt_gradm.h   1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/include/linux/netfilter/xt_gradm.h       2016-01-27 12:26:31.209959056 +0100
-@@ -0,0 +1,9 @@
-+#ifndef _LINUX_NETFILTER_XT_GRADM_H
-+#define _LINUX_NETFILTER_XT_GRADM_H 1
-+
-+struct xt_gradm_mtinfo {
-+      __u16 flags;
-+      __u16 invflags;
-+};
-+
-+#endif
-diff -Naur backports-4.2.6-1.org/include/linux/unaligned/access_ok.h backports-4.2.6-1/include/linux/unaligned/access_ok.h
---- backports-4.2.6-1.org/include/linux/unaligned/access_ok.h  2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/include/linux/unaligned/access_ok.h      2016-01-27 12:26:31.219959057 +0100
-@@ -4,34 +4,34 @@
- #include <linux/kernel.h>
- #include <asm/byteorder.h>
--static inline u16 get_unaligned_le16(const void *p)
-+static inline u16 __intentional_overflow(-1) get_unaligned_le16(const void *p)
- {
--      return le16_to_cpup((__le16 *)p);
-+      return le16_to_cpup((const __le16 *)p);
- }
--static inline u32 get_unaligned_le32(const void *p)
-+static inline u32 __intentional_overflow(-1) get_unaligned_le32(const void *p)
- {
--      return le32_to_cpup((__le32 *)p);
-+      return le32_to_cpup((const __le32 *)p);
- }
--static inline u64 get_unaligned_le64(const void *p)
-+static inline u64 __intentional_overflow(-1) get_unaligned_le64(const void *p)
- {
--      return le64_to_cpup((__le64 *)p);
-+      return le64_to_cpup((const __le64 *)p);
- }
--static inline u16 get_unaligned_be16(const void *p)
-+static inline u16 __intentional_overflow(-1) get_unaligned_be16(const void *p)
- {
--      return be16_to_cpup((__be16 *)p);
-+      return be16_to_cpup((const __be16 *)p);
- }
--static inline u32 get_unaligned_be32(const void *p)
-+static inline u32 __intentional_overflow(-1) get_unaligned_be32(const void *p)
- {
--      return be32_to_cpup((__be32 *)p);
-+      return be32_to_cpup((const __be32 *)p);
- }
--static inline u64 get_unaligned_be64(const void *p)
-+static inline u64 __intentional_overflow(-1) get_unaligned_be64(const void *p)
- {
--      return be64_to_cpup((__be64 *)p);
-+      return be64_to_cpup((const __be64 *)p);
- }
- static inline void put_unaligned_le16(u16 val, void *p)
-diff -Naur backports-4.2.6-1.org/include/media/v4l2-dev.h backports-4.2.6-1/include/media/v4l2-dev.h
---- backports-4.2.6-1.org/include/media/v4l2-dev.h     2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/include/media/v4l2-dev.h 2016-01-27 12:26:31.219959057 +0100
-@@ -74,7 +74,7 @@
-       int (*mmap) (struct file *, struct vm_area_struct *);
-       int (*open) (struct file *);
-       int (*release) (struct file *);
--};
-+} __do_const;
- /*
-  * Newer version of video_device, handled by videodev2.c
-diff -Naur backports-4.2.6-1.org/include/media/v4l2-device.h backports-4.2.6-1/include/media/v4l2-device.h
---- backports-4.2.6-1.org/include/media/v4l2-device.h  2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/include/media/v4l2-device.h      2016-01-27 12:26:31.219959057 +0100
-@@ -93,7 +93,7 @@
-    this function returns 0. If the name ends with a digit (e.g. cx18),
-    then the name will be set to cx18-0 since cx180 looks really odd. */
- int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
--                                              atomic_t *instance);
-+                                              atomic_unchecked_t *instance);
- /* Set v4l2_dev->dev to NULL. Call when the USB parent disconnects.
-    Since the parent disappears this ensures that v4l2_dev doesn't have an
-diff -Naur backports-4.2.6-1.org/include/net/bluetooth/l2cap.h backports-4.2.6-1/include/net/bluetooth/l2cap.h
---- backports-4.2.6-1.org/include/net/bluetooth/l2cap.h        2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/include/net/bluetooth/l2cap.h    2016-01-27 12:31:52.866600109 +0100
-@@ -615,7 +615,7 @@
-                                                    struct iovec *iov,
-                                                    int len);
- #endif
--};
-+} __do_const;
- struct l2cap_conn {
-       struct hci_conn         *hcon;
-diff -Naur backports-4.2.6-1.org/include/net/mac80211.h backports-4.2.6-1/include/net/mac80211.h
---- backports-4.2.6-1.org/include/net/mac80211.h       2015-11-15 22:19:38.000000000 +0100
-+++ backports-4.2.6-1/include/net/mac80211.h   2016-01-27 12:26:31.223292389 +0100
-@@ -5106,7 +5106,7 @@
-       struct sk_buff *skb;
-       struct ieee80211_tx_rate reported_rate;
-       bool rts, short_preamble;
--      u8 max_rate_idx;
-+      s8 max_rate_idx;
-       u32 rate_idx_mask;
-       u8 *rate_idx_mcs_mask;
-       bool bss;
-@@ -5143,7 +5143,7 @@
-       void (*remove_sta_debugfs)(void *priv, void *priv_sta);
-       u32 (*get_expected_throughput)(void *priv_sta);
--};
-+} __do_const;
- static inline int rate_supported(struct ieee80211_sta *sta,
-                                enum ieee80211_band band,
-diff -Naur backports-4.2.6-1.org/include/trace/events/fs.h backports-4.2.6-1/include/trace/events/fs.h
---- backports-4.2.6-1.org/include/trace/events/fs.h    1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/include/trace/events/fs.h        2016-01-27 12:26:31.226625722 +0100
-@@ -0,0 +1,53 @@
-+#undef TRACE_SYSTEM
-+#define TRACE_SYSTEM fs
-+
-+#if !defined(_TRACE_FS_H) || defined(TRACE_HEADER_MULTI_READ)
-+#define _TRACE_FS_H
-+
-+#include <linux/fs.h>
-+#include <linux/tracepoint.h>
-+
-+TRACE_EVENT(do_sys_open,
-+
-+      TP_PROTO(const char *filename, int flags, int mode),
-+
-+      TP_ARGS(filename, flags, mode),
-+
-+      TP_STRUCT__entry(
-+              __string(       filename, filename              )
-+              __field(        int, flags                      )
-+              __field(        int, mode                       )
-+      ),
-+
-+      TP_fast_assign(
-+              __assign_str(filename, filename);
-+              __entry->flags = flags;
-+              __entry->mode = mode;
-+      ),
-+
-+      TP_printk("\"%s\" %x %o",
-+                __get_str(filename), __entry->flags, __entry->mode)
-+);
-+
-+TRACE_EVENT(open_exec,
-+
-+      TP_PROTO(const char *filename),
-+
-+      TP_ARGS(filename),
-+
-+      TP_STRUCT__entry(
-+              __string(       filename, filename              )
-+      ),
-+
-+      TP_fast_assign(
-+              __assign_str(filename, filename);
-+      ),
-+
-+      TP_printk("\"%s\"",
-+                __get_str(filename))
-+);
-+
-+#endif /* _TRACE_FS_H */
-+
-+/* This part must be outside protection */
-+#include <trace/define_trace.h>
-diff -Naur backports-4.2.6-1.org/net/bluetooth/hci_sock.c backports-4.2.6-1/net/bluetooth/hci_sock.c
---- backports-4.2.6-1.org/net/bluetooth/hci_sock.c     2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/bluetooth/hci_sock.c 2016-01-27 12:26:36.269958751 +0100
-@@ -1266,7 +1266,7 @@
-                       uf.event_mask[1] = *((u32 *) f->event_mask + 1);
-               }
--              len = min_t(unsigned int, len, sizeof(uf));
-+              len = min((size_t)len, sizeof(uf));
-               if (copy_from_user(&uf, optval, len)) {
-                       err = -EFAULT;
-                       break;
-diff -Naur backports-4.2.6-1.org/net/bluetooth/l2cap_core.c backports-4.2.6-1/net/bluetooth/l2cap_core.c
---- backports-4.2.6-1.org/net/bluetooth/l2cap_core.c   2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/bluetooth/l2cap_core.c       2016-01-27 12:26:36.269958751 +0100
-@@ -3547,8 +3547,10 @@
-                       break;
-               case L2CAP_CONF_RFC:
--                      if (olen == sizeof(rfc))
--                              memcpy(&rfc, (void *)val, olen);
-+                      if (olen != sizeof(rfc))
-+                              break;
-+
-+                      memcpy(&rfc, (void *)val, olen);
-                       if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
-                           rfc.mode != chan->mode)
-diff -Naur backports-4.2.6-1.org/net/bluetooth/l2cap_sock.c backports-4.2.6-1/net/bluetooth/l2cap_sock.c
---- backports-4.2.6-1.org/net/bluetooth/l2cap_sock.c   2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/bluetooth/l2cap_sock.c       2016-01-27 12:26:36.269958751 +0100
-@@ -633,7 +633,8 @@
-       struct sock *sk = sock->sk;
-       struct l2cap_chan *chan = l2cap_pi(sk)->chan;
-       struct l2cap_options opts;
--      int len, err = 0;
-+      int err = 0;
-+      size_t len = optlen;
-       u32 opt;
-       BT_DBG("sk %p", sk);
-@@ -660,7 +661,7 @@
-               opts.max_tx   = chan->max_tx;
-               opts.txwin_size = chan->tx_win;
--              len = min_t(unsigned int, sizeof(opts), optlen);
-+              len = min(sizeof(opts), len);
-               if (copy_from_user((char *) &opts, optval, len)) {
-                       err = -EFAULT;
-                       break;
-@@ -747,7 +748,8 @@
-       struct bt_security sec;
-       struct bt_power pwr;
-       struct l2cap_conn *conn;
--      int len, err = 0;
-+      int err = 0;
-+      size_t len = optlen;
-       u32 opt;
-       BT_DBG("sk %p", sk);
-@@ -771,7 +773,7 @@
-               sec.level = BT_SECURITY_LOW;
--              len = min_t(unsigned int, sizeof(sec), optlen);
-+              len = min(sizeof(sec), len);
-               if (copy_from_user((char *) &sec, optval, len)) {
-                       err = -EFAULT;
-                       break;
-@@ -867,7 +869,7 @@
-               pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
--              len = min_t(unsigned int, sizeof(pwr), optlen);
-+              len = min(sizeof(pwr), len);
-               if (copy_from_user((char *) &pwr, optval, len)) {
-                       err = -EFAULT;
-                       break;
-diff -Naur backports-4.2.6-1.org/net/bluetooth/rfcomm/sock.c backports-4.2.6-1/net/bluetooth/rfcomm/sock.c
---- backports-4.2.6-1.org/net/bluetooth/rfcomm/sock.c  2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/bluetooth/rfcomm/sock.c      2016-01-27 12:26:36.269958751 +0100
-@@ -713,7 +713,7 @@
-       struct sock *sk = sock->sk;
-       struct bt_security sec;
-       int err = 0;
--      size_t len;
-+      size_t len = optlen;
-       u32 opt;
-       BT_DBG("sk %p", sk);
-@@ -735,7 +735,7 @@
-               sec.level = BT_SECURITY_LOW;
--              len = min_t(unsigned int, sizeof(sec), optlen);
-+              len = min(sizeof(sec), len);
-               if (copy_from_user((char *) &sec, optval, len)) {
-                       err = -EFAULT;
-                       break;
-diff -Naur backports-4.2.6-1.org/net/bluetooth/rfcomm/tty.c backports-4.2.6-1/net/bluetooth/rfcomm/tty.c
---- backports-4.2.6-1.org/net/bluetooth/rfcomm/tty.c   2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/bluetooth/rfcomm/tty.c       2016-01-27 12:26:36.269958751 +0100
-@@ -752,7 +752,7 @@
-       BT_DBG("tty %p id %d", tty, tty->index);
-       BT_DBG("dev %p dst %pMR channel %d opened %d", dev, &dev->dst,
--             dev->channel, dev->port.count);
-+             dev->channel, atomic_read(&dev->port.count));
-       err = tty_port_open(&dev->port, tty, filp);
-       if (err)
-@@ -775,7 +775,7 @@
-       struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
-       BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc,
--                                              dev->port.count);
-+                                              atomic_read(&dev->port.count));
-       tty_port_close(&dev->port, tty, filp);
- }
-diff -Naur backports-4.2.6-1.org/net/ieee802154/6lowpan/core.c backports-4.2.6-1/net/ieee802154/6lowpan/core.c
---- backports-4.2.6-1.org/net/ieee802154/6lowpan/core.c        2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/ieee802154/6lowpan/core.c    2016-01-27 12:26:36.273292083 +0100
-@@ -191,7 +191,7 @@
-       dev_put(real_dev);
- }
--static struct rtnl_link_ops lowpan_link_ops __read_mostly = {
-+static struct rtnl_link_ops lowpan_link_ops = {
-       .kind           = "lowpan",
-       .priv_size      = sizeof(struct lowpan_dev_info),
-       .setup          = lowpan_setup,
-diff -Naur backports-4.2.6-1.org/net/ieee802154/6lowpan/reassembly.c backports-4.2.6-1/net/ieee802154/6lowpan/reassembly.c
---- backports-4.2.6-1.org/net/ieee802154/6lowpan/reassembly.c  2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/ieee802154/6lowpan/reassembly.c      2016-01-27 12:26:36.273292083 +0100
-@@ -435,14 +435,13 @@
- static int __net_init lowpan_frags_ns_sysctl_register(struct net *net)
- {
--      struct ctl_table *table;
-+      ctl_table_no_const *table = NULL;
-       struct ctl_table_header *hdr;
-       struct netns_ieee802154_lowpan *ieee802154_lowpan =
-               net_ieee802154_lowpan(net);
--      table = lowpan_frags_ns_ctl_table;
-       if (!net_eq(net, &init_net)) {
--              table = kmemdup(table, sizeof(lowpan_frags_ns_ctl_table),
-+              table = kmemdup(lowpan_frags_ns_ctl_table, sizeof(lowpan_frags_ns_ctl_table),
-                               GFP_KERNEL);
-               if (table == NULL)
-                       goto err_alloc;
-@@ -457,9 +456,9 @@
-               /* Don't export sysctls to unprivileged users */
-               if (net->user_ns != &init_user_ns)
-                       table[0].procname = NULL;
--      }
--
--      hdr = register_net_sysctl(net, "net/ieee802154/6lowpan", table);
-+              hdr = register_net_sysctl(net, "net/ieee802154/6lowpan", table);
-+      } else
-+              hdr = register_net_sysctl(net, "net/ieee802154/6lowpan", lowpan_frags_ns_ctl_table);
-       if (hdr == NULL)
-               goto err_reg;
-@@ -467,8 +466,7 @@
-       return 0;
- err_reg:
--      if (!net_eq(net, &init_net))
--              kfree(table);
-+      kfree(table);
- err_alloc:
-       return -ENOMEM;
- }
-diff -Naur backports-4.2.6-1.org/net/mac80211/cfg.c backports-4.2.6-1/net/mac80211/cfg.c
---- backports-4.2.6-1.org/net/mac80211/cfg.c   2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/mac80211/cfg.c       2016-01-27 12:26:36.286625417 +0100
-@@ -580,7 +580,7 @@
-                       ret = ieee80211_vif_use_channel(sdata, chandef,
-                                       IEEE80211_CHANCTX_EXCLUSIVE);
-               }
--      } else if (local->open_count == local->monitors) {
-+      } else if (local_read(&local->open_count) == local->monitors) {
-               local->_oper_chandef = *chandef;
-               ieee80211_hw_config(local, 0);
-       }
-@@ -3488,7 +3488,7 @@
-               else
-                       local->probe_req_reg--;
--              if (!local->open_count)
-+              if (!local_read(&local->open_count))
-                       break;
-               ieee80211_queue_work(&local->hw, &local->reconfig_filter);
-@@ -3637,8 +3637,8 @@
-       if (chanctx_conf) {
-               *chandef = sdata->vif.bss_conf.chandef;
-               ret = 0;
--      } else if (local->open_count > 0 &&
--                 local->open_count == local->monitors &&
-+      } else if (local_read(&local->open_count) > 0 &&
-+                 local_read(&local->open_count) == local->monitors &&
-                  sdata->vif.type == NL80211_IFTYPE_MONITOR) {
-               if (local->use_chanctx)
-                       *chandef = local->monitor_chandef;
-diff -Naur backports-4.2.6-1.org/net/mac80211/ieee80211_i.h backports-4.2.6-1/net/mac80211/ieee80211_i.h
---- backports-4.2.6-1.org/net/mac80211/ieee80211_i.h   2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/mac80211/ieee80211_i.h       2016-01-27 12:26:36.289958749 +0100
-@@ -30,6 +30,7 @@
- #include <net/ieee80211_radiotap.h>
- #include <net/cfg80211.h>
- #include <net/mac80211.h>
-+#include <asm/local.h>
- #include "key.h"
- #include "sta_info.h"
- #include "debug.h"
-@@ -1112,7 +1113,7 @@
-       /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
-       spinlock_t queue_stop_reason_lock;
--      int open_count;
-+      local_t open_count;
-       int monitors, cooked_mntrs;
-       /* number of interfaces with corresponding FIF_ flags */
-       int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
-diff -Naur backports-4.2.6-1.org/net/mac80211/iface.c backports-4.2.6-1/net/mac80211/iface.c
---- backports-4.2.6-1.org/net/mac80211/iface.c 2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/mac80211/iface.c     2016-01-27 12:26:36.289958749 +0100
-@@ -550,7 +550,7 @@
-               break;
-       }
--      if (local->open_count == 0) {
-+      if (local_read(&local->open_count) == 0) {
-               res = drv_start(local);
-               if (res)
-                       goto err_del_bss;
-@@ -597,7 +597,7 @@
-                       res = drv_add_interface(local, sdata);
-                       if (res)
-                               goto err_stop;
--              } else if (local->monitors == 0 && local->open_count == 0) {
-+              } else if (local->monitors == 0 && local_read(&local->open_count) == 0) {
-                       res = ieee80211_add_virtual_monitor(local);
-                       if (res)
-                               goto err_stop;
-@@ -704,7 +704,7 @@
-               atomic_inc(&local->iff_allmultis);
-       if (coming_up)
--              local->open_count++;
-+              local_inc(&local->open_count);
-       if (hw_reconf_flags)
-               ieee80211_hw_config(local, hw_reconf_flags);
-@@ -742,7 +742,7 @@
-  err_del_interface:
-       drv_remove_interface(local, sdata);
-  err_stop:
--      if (!local->open_count)
-+      if (!local_read(&local->open_count))
-               drv_stop(local);
-  err_del_bss:
-       sdata->bss = NULL;
-@@ -909,7 +909,7 @@
-       }
-       if (going_down)
--              local->open_count--;
-+              local_dec(&local->open_count);
-       switch (sdata->vif.type) {
-       case NL80211_IFTYPE_AP_VLAN:
-@@ -978,7 +978,7 @@
-               atomic_set(&sdata->txqs_len[txqi->txq.ac], 0);
-       }
--      if (local->open_count == 0)
-+      if (local_read(&local->open_count) == 0)
-               ieee80211_clear_tx_pending(local);
-       /*
-@@ -1021,7 +1021,7 @@
-       if (cancel_scan)
-               flush_delayed_work(&local->scan_work);
--      if (local->open_count == 0) {
-+      if (local_read(&local->open_count) == 0) {
-               ieee80211_stop_device(local);
-               /* no reconfiguring after stop! */
-@@ -1032,7 +1032,7 @@
-       ieee80211_configure_filter(local);
-       ieee80211_hw_config(local, hw_reconf_flags);
--      if (local->monitors == local->open_count)
-+      if (local->monitors == local_read(&local->open_count))
-               ieee80211_add_virtual_monitor(local);
- }
-@@ -1905,8 +1905,8 @@
-        */
-       cfg80211_shutdown_all_interfaces(local->hw.wiphy);
--      WARN(local->open_count, "%s: open count remains %d\n",
--           wiphy_name(local->hw.wiphy), local->open_count);
-+      WARN(local_read(&local->open_count), "%s: open count remains %ld\n",
-+           wiphy_name(local->hw.wiphy), local_read(&local->open_count));
-       mutex_lock(&local->iflist_mtx);
-       list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
-diff -Naur backports-4.2.6-1.org/net/mac80211/main.c backports-4.2.6-1/net/mac80211/main.c
---- backports-4.2.6-1.org/net/mac80211/main.c  2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/mac80211/main.c      2016-01-27 12:26:36.289958749 +0100
-@@ -172,7 +172,7 @@
-               changed &= ~(IEEE80211_CONF_CHANGE_CHANNEL |
-                            IEEE80211_CONF_CHANGE_POWER);
--      if (changed && local->open_count) {
-+      if (changed && local_read(&local->open_count)) {
-               ret = drv_config(local, changed);
-               /*
-                * Goal:
-diff -Naur backports-4.2.6-1.org/net/mac80211/pm.c backports-4.2.6-1/net/mac80211/pm.c
---- backports-4.2.6-1.org/net/mac80211/pm.c    2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/mac80211/pm.c        2016-01-27 12:26:36.289958749 +0100
-@@ -12,7 +12,7 @@
-       struct ieee80211_sub_if_data *sdata;
-       struct sta_info *sta;
--      if (!local->open_count)
-+      if (!local_read(&local->open_count))
-               goto suspend;
-       ieee80211_scan_cancel(local);
-@@ -166,7 +166,7 @@
-       WARN_ON(!list_empty(&local->chanctx_list));
-       /* stop hardware - this must stop RX */
--      if (local->open_count)
-+      if (local_read(&local->open_count))
-               ieee80211_stop_device(local);
-  suspend:
-diff -Naur backports-4.2.6-1.org/net/mac80211/rate.c backports-4.2.6-1/net/mac80211/rate.c
---- backports-4.2.6-1.org/net/mac80211/rate.c  2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/mac80211/rate.c      2016-01-27 12:26:36.289958749 +0100
-@@ -730,7 +730,7 @@
-       ASSERT_RTNL();
--      if (local->open_count)
-+      if (local_read(&local->open_count))
-               return -EBUSY;
-       if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
-diff -Naur backports-4.2.6-1.org/net/mac80211/sta_info.c backports-4.2.6-1/net/mac80211/sta_info.c
---- backports-4.2.6-1.org/net/mac80211/sta_info.c      2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/mac80211/sta_info.c  2016-01-27 12:26:36.289958749 +0100
-@@ -341,7 +341,7 @@
-               int size = sizeof(struct txq_info) +
-                          ALIGN(hw->txq_data_size, sizeof(void *));
--              txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp);
-+              txq_data = kcalloc(size, ARRAY_SIZE(sta->sta.txq), gfp);
-               if (!txq_data)
-                       goto free;
-diff -Naur backports-4.2.6-1.org/net/mac80211/util.c backports-4.2.6-1/net/mac80211/util.c
---- backports-4.2.6-1.org/net/mac80211/util.c  2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/mac80211/util.c      2016-01-27 12:26:36.289958749 +0100
-@@ -1761,7 +1761,7 @@
-       bool sched_scan_stopped = false;
-       /* nothing to do if HW shouldn't run */
--      if (!local->open_count)
-+      if (!local_read(&local->open_count))
-               goto wake_up;
- #ifdef CONFIG_PM
-@@ -2033,7 +2033,7 @@
-       local->in_reconfig = false;
-       barrier();
--      if (local->monitors == local->open_count && local->monitors > 0)
-+      if (local->monitors == local_read(&local->open_count) && local->monitors > 0)
-               ieee80211_add_virtual_monitor(local);
-       /*
-@@ -2088,7 +2088,7 @@
-        * If this is for hw restart things are still running.
-        * We may want to change that later, however.
-        */
--      if (local->open_count && (!local->suspended || reconfig_due_to_wowlan))
-+      if (local_read(&local->open_count) && (!local->suspended || reconfig_due_to_wowlan))
-               drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
-       if (!local->suspended)
-@@ -2112,7 +2112,7 @@
-               flush_delayed_work(&local->scan_work);
-       }
--      if (local->open_count && !reconfig_due_to_wowlan)
-+      if (local_read(&local->open_count) && !reconfig_due_to_wowlan)
-               drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND);
-       list_for_each_entry(sdata, &local->interfaces, list) {
-diff -Naur backports-4.2.6-1.org/net/wireless/wext-core.c backports-4.2.6-1/net/wireless/wext-core.c
---- backports-4.2.6-1.org/net/wireless/wext-core.c     2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/net/wireless/wext-core.c 2016-01-27 12:26:36.303292082 +0100
-@@ -748,8 +748,7 @@
-                */
-               /* Support for very large requests */
--              if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
--                  (user_length > descr->max_tokens)) {
-+              if (user_length > descr->max_tokens) {
-                       /* Allow userspace to GET more than max so
-                        * we can support any size GET requests.
-                        * There is still a limit : -ENOMEM.
-@@ -788,22 +787,6 @@
-               }
-       }
--      if (IW_IS_GET(cmd) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) {
--              /*
--               * If this is a GET, but not NOMAX, it means that the extra
--               * data is not bounded by userspace, but by max_tokens. Thus
--               * set the length to max_tokens. This matches the extra data
--               * allocation.
--               * The driver should fill it with the number of tokens it
--               * provided, and it may check iwp->length rather than having
--               * knowledge of max_tokens. If the driver doesn't change the
--               * iwp->length, this ioctl just copies back max_token tokens
--               * filled with zeroes. Hopefully the driver isn't claiming
--               * them to be valid data.
--               */
--              iwp->length = descr->max_tokens;
--      }
--
-       err = handler(dev, info, (union iwreq_data *) iwp, extra);
-       iwp->length += essid_compat;
-diff -Naur backports-4.2.6-1.org/scripts/gcc-plugin.sh backports-4.2.6-1/scripts/gcc-plugin.sh
---- backports-4.2.6-1.org/scripts/gcc-plugin.sh        1970-01-01 01:00:00.000000000 +0100
-+++ backports-4.2.6-1/scripts/gcc-plugin.sh    2016-01-27 12:26:36.303292082 +0100
-@@ -0,0 +1,51 @@
-+#!/bin/sh
-+srctree=$(dirname "$0")
-+gccplugins_dir=$($3 -print-file-name=plugin)
-+plugincc=$($1 -E -x c++ - -o /dev/null -I"${srctree}"/../tools/gcc -I"${gccplugins_dir}"/include 2>&1 <<EOF
-+#include "gcc-common.h"
-+#if BUILDING_GCC_VERSION >= 4008 || defined(ENABLE_BUILD_WITH_CXX)
-+#warning $2 CXX
-+#else
-+#warning $1 CC
-+#endif
-+EOF
-+)
-+
-+if [ $? -ne 0 ]
-+then
-+      exit 1
-+fi
-+
-+case "$plugincc" in
-+      *"$1 CC"*)
-+              echo "$1"
-+              exit 0
-+              ;;
-+
-+      *"$2 CXX"*)
-+              # the c++ compiler needs another test, see below
-+              ;;
-+
-+      *)
-+              exit 1
-+              ;;
-+esac
-+
-+# we need a c++ compiler that supports the designated initializer GNU extension
-+plugincc=$($2 -c -x c++ -std=gnu++98 - -fsyntax-only -I"${srctree}"/../tools/gcc -I"${gccplugins_dir}"/include 2>&1 <<EOF
-+#include "gcc-common.h"
-+class test {
-+public:
-+      int test;
-+} test = {
-+      .test = 1
-+};
-+EOF
-+)
-+
-+if [ $? -eq 0 ]
-+then
-+      echo "$2"
-+      exit 0
-+fi
-+exit 1
diff --git a/src/patches/backports-4.2.6-1-mt7601_upstream_fixes.patch b/src/patches/backports-4.2.6-1-mt7601_upstream_fixes.patch
deleted file mode 100644 (file)
index 9918d65..0000000
+++ /dev/null
@@ -1,441 +0,0 @@
-From bed429e1ae8b7ee207e01f3aa60dcc0d06a8ed4d Mon Sep 17 00:00:00 2001
-From: Jakub Kicinski <kubakici@wp.pl>
-Date: Fri, 31 Jul 2015 15:04:46 +0200
-Subject: mt7601u: fix dma from stack address
-
-DMA to variables located on the stack is a bad idea.
-For simplicity and to avoid frequent allocations create
-a buffer inside the device structure.  Protect this
-buffer with vendor_req_mutex.  Don't protect vendor
-requests which don't use this buffer.
-
-Signed-off-by: Jakub Kicinski <kubakici@wp.pl>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/mediatek/mt7601u/mt7601u.h |  4 +-
- drivers/net/wireless/mediatek/mt7601u/usb.c     | 63 ++++++++++++-------------
- drivers/net/wireless/mediatek/mt7601u/usb.h     |  2 +
- 3 files changed, 34 insertions(+), 35 deletions(-)
-
-diff --git a/drivers/net/wireless/mediatek/mt7601u/mt7601u.h b/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
-index 9102be6b..6bdfc11 100644
---- a/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
-+++ b/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
-@@ -146,7 +146,7 @@ enum {
-  * @rx_lock:          protects @rx_q.
-  * @con_mon_lock:     protects @ap_bssid, @bcn_*, @avg_rssi.
-  * @mutex:            ensures exclusive access from mac80211 callbacks.
-- * @vendor_req_mutex: ensures atomicity of vendor requests.
-+ * @vendor_req_mutex: protects @vend_buf, ensures atomicity of split writes.
-  * @reg_atomic_mutex: ensures atomicity of indirect register accesses
-  *                    (accesses to RF and BBP).
-  * @hw_atomic_mutex:  ensures exclusive access to HW during critical
-@@ -184,6 +184,8 @@ struct mt7601u_dev {
-       struct mt7601u_eeprom_params *ee;
-       struct mutex vendor_req_mutex;
-+      void *vend_buf;
-+
-       struct mutex reg_atomic_mutex;
-       struct mutex hw_atomic_mutex;
-diff --git a/drivers/net/wireless/mediatek/mt7601u/usb.c b/drivers/net/wireless/mediatek/mt7601u/usb.c
-index 54dba40..416c604 100644
---- a/drivers/net/wireless/mediatek/mt7601u/usb.c
-+++ b/drivers/net/wireless/mediatek/mt7601u/usb.c
-@@ -92,10 +92,9 @@ void mt7601u_complete_urb(struct urb *urb)
-       complete(cmpl);
- }
--static int
--__mt7601u_vendor_request(struct mt7601u_dev *dev, const u8 req,
--                       const u8 direction, const u16 val, const u16 offset,
--                       void *buf, const size_t buflen)
-+int mt7601u_vendor_request(struct mt7601u_dev *dev, const u8 req,
-+                         const u8 direction, const u16 val, const u16 offset,
-+                         void *buf, const size_t buflen)
- {
-       int i, ret;
-       struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
-@@ -110,6 +109,8 @@ __mt7601u_vendor_request(struct mt7601u_dev *dev, const u8 req,
-               trace_mt_vend_req(dev, pipe, req, req_type, val, offset,
-                                 buf, buflen, ret);
-+              if (ret == -ENODEV)
-+                      set_bit(MT7601U_STATE_REMOVED, &dev->state);
-               if (ret >= 0 || ret == -ENODEV)
-                       return ret;
-@@ -122,25 +123,6 @@ __mt7601u_vendor_request(struct mt7601u_dev *dev, const u8 req,
-       return ret;
- }
--int
--mt7601u_vendor_request(struct mt7601u_dev *dev, const u8 req,
--                     const u8 direction, const u16 val, const u16 offset,
--                     void *buf, const size_t buflen)
--{
--      int ret;
--
--      mutex_lock(&dev->vendor_req_mutex);
--
--      ret = __mt7601u_vendor_request(dev, req, direction, val, offset,
--                                     buf, buflen);
--      if (ret == -ENODEV)
--              set_bit(MT7601U_STATE_REMOVED, &dev->state);
--
--      mutex_unlock(&dev->vendor_req_mutex);
--
--      return ret;
--}
--
- void mt7601u_vendor_reset(struct mt7601u_dev *dev)
- {
-       mt7601u_vendor_request(dev, MT_VEND_DEV_MODE, USB_DIR_OUT,
-@@ -150,19 +132,21 @@ void mt7601u_vendor_reset(struct mt7601u_dev *dev)
- u32 mt7601u_rr(struct mt7601u_dev *dev, u32 offset)
- {
-       int ret;
--      __le32 reg;
--      u32 val;
-+      u32 val = ~0;
-       WARN_ONCE(offset > USHRT_MAX, "read high off:%08x", offset);
-+      mutex_lock(&dev->vendor_req_mutex);
-+
-       ret = mt7601u_vendor_request(dev, MT_VEND_MULTI_READ, USB_DIR_IN,
--                                   0, offset, &reg, sizeof(reg));
--      val = le32_to_cpu(reg);
--      if (ret > 0 && ret != sizeof(reg)) {
-+                                   0, offset, dev->vend_buf, MT_VEND_BUF);
-+      if (ret == MT_VEND_BUF)
-+              val = get_unaligned_le32(dev->vend_buf);
-+      else if (ret > 0)
-               dev_err(dev->dev, "Error: wrong size read:%d off:%08x\n",
-                       ret, offset);
--              val = ~0;
--      }
-+
-+      mutex_unlock(&dev->vendor_req_mutex);
-       trace_reg_read(dev, offset, val);
-       return val;
-@@ -173,12 +157,17 @@ int mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req,
- {
-       int ret;
-+      mutex_lock(&dev->vendor_req_mutex);
-+
-       ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT,
-                                    val & 0xffff, offset, NULL, 0);
--      if (ret)
--              return ret;
--      return mt7601u_vendor_request(dev, req, USB_DIR_OUT,
--                                    val >> 16, offset + 2, NULL, 0);
-+      if (!ret)
-+              ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT,
-+                                           val >> 16, offset + 2, NULL, 0);
-+
-+      mutex_unlock(&dev->vendor_req_mutex);
-+
-+      return ret;
- }
- void mt7601u_wr(struct mt7601u_dev *dev, u32 offset, u32 val)
-@@ -275,6 +264,12 @@ static int mt7601u_probe(struct usb_interface *usb_intf,
-       usb_set_intfdata(usb_intf, dev);
-+      dev->vend_buf = devm_kmalloc(dev->dev, MT_VEND_BUF, GFP_KERNEL);
-+      if (!dev->vend_buf) {
-+              ret = -ENOMEM;
-+              goto err;
-+      }
-+
-       ret = mt7601u_assign_pipes(usb_intf, dev);
-       if (ret)
-               goto err;
-diff --git a/drivers/net/wireless/mediatek/mt7601u/usb.h b/drivers/net/wireless/mediatek/mt7601u/usb.h
-index 49e188f..bc18202 100644
---- a/drivers/net/wireless/mediatek/mt7601u/usb.h
-+++ b/drivers/net/wireless/mediatek/mt7601u/usb.h
-@@ -23,6 +23,8 @@
- #define MT_VEND_DEV_MODE_RESET        1
-+#define MT_VEND_BUF           sizeof(__le32)
-+
- enum mt_vendor_req {
-       MT_VEND_DEV_MODE = 1,
-       MT_VEND_WRITE = 2,
--- 
-cgit v0.12
-
-From d9517c0a5d7468a7ea63086057604fcb0fff480e Mon Sep 17 00:00:00 2001
-From: Jakub Kicinski <kubakici@wp.pl>
-Date: Fri, 31 Jul 2015 15:04:47 +0200
-Subject: mt7601u: use correct ieee80211_rx variant
-
-Rx is run inside a tasklet so ieee80211_rx() should be used
-instead of ieee80211_rx_ni().
-
-Signed-off-by: Jakub Kicinski <kubakici@wp.pl>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/mediatek/mt7601u/dma.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c
-index 7217da4..fb183e3 100644
---- a/drivers/net/wireless/mediatek/mt7601u/dma.c
-+++ b/drivers/net/wireless/mediatek/mt7601u/dma.c
-@@ -112,7 +112,7 @@ static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
-       if (!skb)
-               return;
--      ieee80211_rx_ni(dev->hw, skb);
-+      ieee80211_rx(dev->hw, skb);
- }
- static u16 mt7601u_rx_next_seg_len(u8 *data, u32 data_len)
--- 
-cgit v0.12
-
-From 4513493d188d5e3052aee68eda85eaaa1a4e41c2 Mon Sep 17 00:00:00 2001
-From: Jakub Kicinski <kubakici@wp.pl>
-Date: Fri, 31 Jul 2015 15:04:48 +0200
-Subject: mt7601u: fix tx status reporting contexts
-
-mac80211 requires that rx path does not run concurrently with
-tx status reporting.  Since rx path is run in driver tasklet,
-tx status cannot be reported directly from interrupt context
-(there would be no way to lock it out).
-
-Add tasklet for tx and move all possible code from irq handler
-there.
-
-Note: tx tasklet is needed because workqueue is queued very
-      rarely and that kills TCP performance.
-
-Signed-off-by: Jakub Kicinski <kubakici@wp.pl>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/mediatek/mt7601u/dma.c     | 30 +++++++++++++++++++++----
- drivers/net/wireless/mediatek/mt7601u/init.c    |  1 +
- drivers/net/wireless/mediatek/mt7601u/mac.c     |  4 ++++
- drivers/net/wireless/mediatek/mt7601u/mt7601u.h |  2 ++
- 4 files changed, 33 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c
-index fb183e3..63c4854 100644
---- a/drivers/net/wireless/mediatek/mt7601u/dma.c
-+++ b/drivers/net/wireless/mediatek/mt7601u/dma.c
-@@ -236,23 +236,42 @@ static void mt7601u_complete_tx(struct urb *urb)
-       skb = q->e[q->start].skb;
-       trace_mt_tx_dma_done(dev, skb);
--      mt7601u_tx_status(dev, skb);
-+      __skb_queue_tail(&dev->tx_skb_done, skb);
-+      tasklet_schedule(&dev->tx_tasklet);
-       if (q->used == q->entries - q->entries / 8)
-               ieee80211_wake_queue(dev->hw, skb_get_queue_mapping(skb));
-       q->start = (q->start + 1) % q->entries;
-       q->used--;
-+out:
-+      spin_unlock_irqrestore(&dev->tx_lock, flags);
-+}
--      if (urb->status)
--              goto out;
-+static void mt7601u_tx_tasklet(unsigned long data)
-+{
-+      struct mt7601u_dev *dev = (struct mt7601u_dev *) data;
-+      struct sk_buff_head skbs;
-+      unsigned long flags;
-+
-+      __skb_queue_head_init(&skbs);
-+
-+      spin_lock_irqsave(&dev->tx_lock, flags);
-       set_bit(MT7601U_STATE_MORE_STATS, &dev->state);
-       if (!test_and_set_bit(MT7601U_STATE_READING_STATS, &dev->state))
-               queue_delayed_work(dev->stat_wq, &dev->stat_work,
-                                  msecs_to_jiffies(10));
--out:
-+
-+      skb_queue_splice_init(&dev->tx_skb_done, &skbs);
-+
-       spin_unlock_irqrestore(&dev->tx_lock, flags);
-+
-+      while (!skb_queue_empty(&skbs)) {
-+              struct sk_buff *skb = __skb_dequeue(&skbs);
-+
-+              mt7601u_tx_status(dev, skb);
-+      }
- }
- static int mt7601u_dma_submit_tx(struct mt7601u_dev *dev,
-@@ -475,6 +494,7 @@ int mt7601u_dma_init(struct mt7601u_dev *dev)
- {
-       int ret = -ENOMEM;
-+      tasklet_init(&dev->tx_tasklet, mt7601u_tx_tasklet, (unsigned long) dev);
-       tasklet_init(&dev->rx_tasklet, mt7601u_rx_tasklet, (unsigned long) dev);
-       ret = mt7601u_alloc_tx(dev);
-@@ -502,4 +522,6 @@ void mt7601u_dma_cleanup(struct mt7601u_dev *dev)
-       mt7601u_free_rx(dev);
-       mt7601u_free_tx(dev);
-+
-+      tasklet_kill(&dev->tx_tasklet);
- }
-diff --git a/drivers/net/wireless/mediatek/mt7601u/init.c b/drivers/net/wireless/mediatek/mt7601u/init.c
-index df3dd56..38eb20b 100644
---- a/drivers/net/wireless/mediatek/mt7601u/init.c
-+++ b/drivers/net/wireless/mediatek/mt7601u/init.c
-@@ -456,6 +456,7 @@ struct mt7601u_dev *mt7601u_alloc_device(struct device *pdev)
-       spin_lock_init(&dev->lock);
-       spin_lock_init(&dev->con_mon_lock);
-       atomic_set(&dev->avg_ampdu_len, 1);
-+      skb_queue_head_init(&dev->tx_skb_done);
-       dev->stat_wq = alloc_workqueue("mt7601u", WQ_UNBOUND, 0);
-       if (!dev->stat_wq) {
-diff --git a/drivers/net/wireless/mediatek/mt7601u/mac.c b/drivers/net/wireless/mediatek/mt7601u/mac.c
-index 7514bce..e3928cf 100644
---- a/drivers/net/wireless/mediatek/mt7601u/mac.c
-+++ b/drivers/net/wireless/mediatek/mt7601u/mac.c
-@@ -181,7 +181,11 @@ void mt76_send_tx_status(struct mt7601u_dev *dev, struct mt76_tx_status *stat)
-       }
-       mt76_mac_fill_tx_status(dev, &info, stat);
-+
-+      local_bh_disable();
-       ieee80211_tx_status_noskb(dev->hw, sta, &info);
-+      local_bh_enable();
-+
-       rcu_read_unlock();
- }
-diff --git a/drivers/net/wireless/mediatek/mt7601u/mt7601u.h b/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
-index 6bdfc11..bc5e294 100644
---- a/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
-+++ b/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
-@@ -199,7 +199,9 @@ struct mt7601u_dev {
-       /* TX */
-       spinlock_t tx_lock;
-+      struct tasklet_struct tx_tasklet;
-       struct mt7601u_tx_queue *tx_q;
-+      struct sk_buff_head tx_skb_done;
-       atomic_t avg_ampdu_len;
--- 
-cgit v0.12
-
-From 78623bfb6f4cbdba3183621e8e0e781611217022 Mon Sep 17 00:00:00 2001
-From: Jakub Kicinski <kubakici@wp.pl>
-Date: Fri, 31 Jul 2015 15:04:49 +0200
-Subject: mt7601u: lock out rx path and tx status reporting
-
-mac80211 requires that rx path does not run concurrently with
-tx status reporting.  Add a spinlock which will ensure that.
-
-Signed-off-by: Jakub Kicinski <kubakici@wp.pl>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/mediatek/mt7601u/dma.c     | 2 ++
- drivers/net/wireless/mediatek/mt7601u/init.c    | 1 +
- drivers/net/wireless/mediatek/mt7601u/mac.c     | 4 ++--
- drivers/net/wireless/mediatek/mt7601u/mt7601u.h | 4 +++-
- drivers/net/wireless/mediatek/mt7601u/tx.c      | 3 +++
- 5 files changed, 11 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c
-index 63c4854..57a80cf 100644
---- a/drivers/net/wireless/mediatek/mt7601u/dma.c
-+++ b/drivers/net/wireless/mediatek/mt7601u/dma.c
-@@ -112,7 +112,9 @@ static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
-       if (!skb)
-               return;
-+      spin_lock(&dev->mac_lock);
-       ieee80211_rx(dev->hw, skb);
-+      spin_unlock(&dev->mac_lock);
- }
- static u16 mt7601u_rx_next_seg_len(u8 *data, u32 data_len)
-diff --git a/drivers/net/wireless/mediatek/mt7601u/init.c b/drivers/net/wireless/mediatek/mt7601u/init.c
-index 38eb20b..26190fd 100644
---- a/drivers/net/wireless/mediatek/mt7601u/init.c
-+++ b/drivers/net/wireless/mediatek/mt7601u/init.c
-@@ -454,6 +454,7 @@ struct mt7601u_dev *mt7601u_alloc_device(struct device *pdev)
-       spin_lock_init(&dev->tx_lock);
-       spin_lock_init(&dev->rx_lock);
-       spin_lock_init(&dev->lock);
-+      spin_lock_init(&dev->mac_lock);
-       spin_lock_init(&dev->con_mon_lock);
-       atomic_set(&dev->avg_ampdu_len, 1);
-       skb_queue_head_init(&dev->tx_skb_done);
-diff --git a/drivers/net/wireless/mediatek/mt7601u/mac.c b/drivers/net/wireless/mediatek/mt7601u/mac.c
-index e3928cf..e21c53e 100644
---- a/drivers/net/wireless/mediatek/mt7601u/mac.c
-+++ b/drivers/net/wireless/mediatek/mt7601u/mac.c
-@@ -182,9 +182,9 @@ void mt76_send_tx_status(struct mt7601u_dev *dev, struct mt76_tx_status *stat)
-       mt76_mac_fill_tx_status(dev, &info, stat);
--      local_bh_disable();
-+      spin_lock_bh(&dev->mac_lock);
-       ieee80211_tx_status_noskb(dev->hw, sta, &info);
--      local_bh_enable();
-+      spin_unlock_bh(&dev->mac_lock);
-       rcu_read_unlock();
- }
-diff --git a/drivers/net/wireless/mediatek/mt7601u/mt7601u.h b/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
-index bc5e294..428bd2f 100644
---- a/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
-+++ b/drivers/net/wireless/mediatek/mt7601u/mt7601u.h
-@@ -141,8 +141,9 @@ enum {
- /**
-  * struct mt7601u_dev - adapter structure
-  * @lock:             protects @wcid->tx_rate.
-+ * @mac_lock:         locks out mac80211's tx status and rx paths.
-  * @tx_lock:          protects @tx_q and changes of MT7601U_STATE_*_STATS
--                      flags in @state.
-+ *                    flags in @state.
-  * @rx_lock:          protects @rx_q.
-  * @con_mon_lock:     protects @ap_bssid, @bcn_*, @avg_rssi.
-  * @mutex:            ensures exclusive access from mac80211 callbacks.
-@@ -177,6 +178,7 @@ struct mt7601u_dev {
-       struct mt76_wcid __rcu *wcid[N_WCIDS];
-       spinlock_t lock;
-+      spinlock_t mac_lock;
-       const u16 *beacon_offsets;
-diff --git a/drivers/net/wireless/mediatek/mt7601u/tx.c b/drivers/net/wireless/mediatek/mt7601u/tx.c
-index 0be2080..a0a33dc 100644
---- a/drivers/net/wireless/mediatek/mt7601u/tx.c
-+++ b/drivers/net/wireless/mediatek/mt7601u/tx.c
-@@ -116,7 +116,10 @@ void mt7601u_tx_status(struct mt7601u_dev *dev, struct sk_buff *skb)
-       ieee80211_tx_info_clear_status(info);
-       info->status.rates[0].idx = -1;
-       info->flags |= IEEE80211_TX_STAT_ACK;
-+
-+      spin_lock(&dev->mac_lock);
-       ieee80211_tx_status(dev->hw, skb);
-+      spin_unlock(&dev->mac_lock);
- }
- static int mt7601u_skb_rooms(struct mt7601u_dev *dev, struct sk_buff *skb)
--- 
-cgit v0.12
-
diff --git a/src/patches/backports-4.2.6-1_ath10k_remove_logspam.patch b/src/patches/backports-4.2.6-1_ath10k_remove_logspam.patch
deleted file mode 100644 (file)
index bdb1534..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath10k/htt_rx.c backports-4.2.6-1/drivers/net/wireless/ath/ath10k/htt_rx.c
---- backports-4.2.6-1.org/drivers/net/wireless/ath/ath10k/htt_rx.c     2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ath/ath10k/htt_rx.c 2016-03-26 10:48:17.189430101 +0100
-@@ -1476,7 +1476,7 @@
-        */
-       if (!rx_status->freq) {
--              ath10k_warn(ar, "no channel configured; ignoring frame(s)!\n");
-+              ath10k_dbg(ar,ATH10K_DBG_DATA ,"no channel configured; ignoring frame(s)!\n");
-               return false;
-       }
diff --git a/src/patches/linux/backports-4.2.6-1_ath10k_remove_logspam.patch b/src/patches/linux/backports-4.2.6-1_ath10k_remove_logspam.patch
deleted file mode 100644 (file)
index bdb1534..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -Naur backports-4.2.6-1.org/drivers/net/wireless/ath/ath10k/htt_rx.c backports-4.2.6-1/drivers/net/wireless/ath/ath10k/htt_rx.c
---- backports-4.2.6-1.org/drivers/net/wireless/ath/ath10k/htt_rx.c     2015-11-15 22:19:40.000000000 +0100
-+++ backports-4.2.6-1/drivers/net/wireless/ath/ath10k/htt_rx.c 2016-03-26 10:48:17.189430101 +0100
-@@ -1476,7 +1476,7 @@
-        */
-       if (!rx_status->freq) {
--              ath10k_warn(ar, "no channel configured; ignoring frame(s)!\n");
-+              ath10k_dbg(ar,ATH10K_DBG_DATA ,"no channel configured; ignoring frame(s)!\n");
-               return false;
-       }