diff --git a/Documentation/admin-guide/kernel-parameters.txt 
b/Documentation/admin-guide/kernel-parameters.txt
index be7c0d9506b1..18eefa860f76 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1201,6 +1201,10 @@
                        When zero, profiling data is discarded and associated
                        debugfs files are removed at module unload time.
 
+       goldfish        [X86] Enable the goldfish android emulator platform.
+                       Don't use this when you are not running on the
+                       android emulator
+
        gpt             [EFI] Forces disk with valid GPT signature but
                        invalid Protective MBR to be treated as GPT. If the
                        primary GPT is corrupted, it enables the 
backup/alternate
diff --git a/Makefile b/Makefile
index f1e6a02a0c19..09eccff4f569 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 10
-SUBLEVEL = 0
+SUBLEVEL = 1
 EXTRAVERSION =
 NAME = Fearless Coyote
 
diff --git a/arch/x86/platform/goldfish/goldfish.c 
b/arch/x86/platform/goldfish/goldfish.c
index 1693107a518e..0d17c0aafeb1 100644
--- a/arch/x86/platform/goldfish/goldfish.c
+++ b/arch/x86/platform/goldfish/goldfish.c
@@ -42,10 +42,22 @@ static struct resource goldfish_pdev_bus_resources[] = {
        }
 };
 
+static bool goldfish_enable __initdata;
+
+static int __init goldfish_setup(char *str)
+{
+       goldfish_enable = true;
+       return 0;
+}
+__setup("goldfish", goldfish_setup);
+
 static int __init goldfish_init(void)
 {
+       if (!goldfish_enable)
+               return -ENODEV;
+
        platform_device_register_simple("goldfish_pdev_bus", -1,
-                                               goldfish_pdev_bus_resources, 2);
+                                       goldfish_pdev_bus_resources, 2);
        return 0;
 }
 device_initcall(goldfish_init);
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c 
b/drivers/net/wireless/realtek/rtlwifi/usb.c
index 49015b05f3d1..abdaf203835c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -827,12 +827,30 @@ static void rtl_usb_stop(struct ieee80211_hw *hw)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
        struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+       struct urb *urb;
 
        /* should after adapter start and interrupt enable. */
        set_hal_stop(rtlhal);
        cancel_work_sync(&rtlpriv->works.fill_h2c_cmd);
        /* Enable software */
        SET_USB_STOP(rtlusb);
+
+       /* free pre-allocated URBs from rtl_usb_start() */
+       usb_kill_anchored_urbs(&rtlusb->rx_submitted);
+
+       tasklet_kill(&rtlusb->rx_work_tasklet);
+       cancel_work_sync(&rtlpriv->works.lps_change_work);
+
+       flush_workqueue(rtlpriv->works.rtl_wq);
+
+       skb_queue_purge(&rtlusb->rx_queue);
+
+       while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) {
+               usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+                               urb->transfer_buffer, urb->transfer_dma);
+               usb_free_urb(urb);
+       }
+
        rtlpriv->cfg->ops->hw_disable(hw);
 }
 
diff --git a/drivers/platform/goldfish/pdev_bus.c 
b/drivers/platform/goldfish/pdev_bus.c
index 1f52462f4cdd..dd9ea463c2a4 100644
--- a/drivers/platform/goldfish/pdev_bus.c
+++ b/drivers/platform/goldfish/pdev_bus.c
@@ -157,23 +157,26 @@ static int goldfish_new_pdev(void)
 static irqreturn_t goldfish_pdev_bus_interrupt(int irq, void *dev_id)
 {
        irqreturn_t ret = IRQ_NONE;
+
        while (1) {
                u32 op = readl(pdev_bus_base + PDEV_BUS_OP);
-               switch (op) {
-               case PDEV_BUS_OP_DONE:
-                       return IRQ_NONE;
 
+               switch (op) {
                case PDEV_BUS_OP_REMOVE_DEV:
                        goldfish_pdev_remove();
+                       ret = IRQ_HANDLED;
                        break;
 
                case PDEV_BUS_OP_ADD_DEV:
                        goldfish_new_pdev();
+                       ret = IRQ_HANDLED;
                        break;
+
+               case PDEV_BUS_OP_DONE:
+               default:
+                       return ret;
                }
-               ret = IRQ_HANDLED;
        }
-       return ret;
 }
 
 static int goldfish_pdev_bus_probe(struct platform_device *pdev)
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 7312e7e01b7e..6788e7532dff 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -1809,6 +1809,7 @@ static const struct of_device_id msm_match_table[] = {
        { .compatible = "qcom,msm-uartdm" },
        {}
 };
+MODULE_DEVICE_TABLE(of, msm_match_table);
 
 static struct platform_driver msm_platform_driver = {
        .remove = msm_serial_remove,
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 1532cde8a437..7812052dc700 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -99,10 +99,17 @@ static int ark3116_read_reg(struct usb_serial *serial,
                                 usb_rcvctrlpipe(serial->dev, 0),
                                 0xfe, 0xc0, 0, reg,
                                 buf, 1, ARK_TIMEOUT);
-       if (result < 0)
+       if (result < 1) {
+               dev_err(&serial->interface->dev,
+                               "failed to read register %u: %d\n",
+                               reg, result);
+               if (result >= 0)
+                       result = -EIO;
+
                return result;
-       else
-               return buf[0];
+       }
+
+       return buf[0];
 }
 
 static inline int calc_divisor(int bps)
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 8967715fe6fc..b6f1adefb758 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -143,6 +143,7 @@ static int usb_console_setup(struct console *co, char 
*options)
                        tty->driver = usb_serial_tty_driver;
                        tty->index = co->index;
                        init_ldsem(&tty->ldisc_sem);
+                       spin_lock_init(&tty->files_lock);
                        INIT_LIST_HEAD(&tty->tty_files);
                        kref_get(&tty->driver->kref);
                        __module_get(tty->driver->owner);
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index fff718352e0c..fbe69465eefa 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -178,6 +178,8 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */
        { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
        { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */
+       { USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART 
interface */
+       { USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */
        { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
        { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
        { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 23d14b98ae2a..7d863fda1f18 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1802,8 +1802,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port 
*port)
 
        mutex_init(&priv->cfg_lock);
 
-       priv->flags = ASYNC_LOW_LATENCY;
-
        if (quirk && quirk->port_probe)
                quirk->port_probe(priv);
 
@@ -2067,6 +2065,20 @@ static int ftdi_process_packet(struct usb_serial_port 
*port,
                priv->prev_status = status;
        }
 
+       /* save if the transmitter is empty or not */
+       if (packet[1] & FTDI_RS_TEMT)
+               priv->transmit_empty = 1;
+       else
+               priv->transmit_empty = 0;
+
+       len -= 2;
+       if (!len)
+               return 0;       /* status only */
+
+       /*
+        * Break and error status must only be processed for packets with
+        * data payload to avoid over-reporting.
+        */
        flag = TTY_NORMAL;
        if (packet[1] & FTDI_RS_ERR_MASK) {
                /* Break takes precedence over parity, which takes precedence
@@ -2089,15 +2101,6 @@ static int ftdi_process_packet(struct usb_serial_port 
*port,
                }
        }
 
-       /* save if the transmitter is empty or not */
-       if (packet[1] & FTDI_RS_TEMT)
-               priv->transmit_empty = 1;
-       else
-               priv->transmit_empty = 0;
-
-       len -= 2;
-       if (!len)
-               return 0;       /* status only */
        port->icount.rx += len;
        ch = packet + 2;
 
@@ -2428,8 +2431,12 @@ static int ftdi_get_modem_status(struct usb_serial_port 
*port,
                        FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
                        0, priv->interface,
                        buf, len, WDR_TIMEOUT);
-       if (ret < 0) {
+
+       /* NOTE: We allow short responses and handle that below. */
+       if (ret < 1) {
                dev_err(&port->dev, "failed to get modem status: %d\n", ret);
+               if (ret >= 0)
+                       ret = -EIO;
                ret = usb_translate_errors(ret);
                goto out;
        }
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index ea27fb23967a..e536ac8a080b 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1023,6 +1023,7 @@ static int mos7840_open(struct tty_struct *tty, struct 
usb_serial_port *port)
         * (can't set it up in mos7840_startup as the structures *
         * were not set up at that time.)                        */
        if (port0->open_ports == 1) {
+               /* FIXME: Buffer never NULL, so URB is not submitted. */
                if (serial->port[0]->interrupt_in_buffer == NULL) {
                        /* set up interrupt urb */
                        usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
@@ -2106,7 +2107,8 @@ static int mos7840_calc_num_ports(struct usb_serial 
*serial)
 static int mos7840_attach(struct usb_serial *serial)
 {
        if (serial->num_bulk_in < serial->num_ports ||
-                       serial->num_bulk_out < serial->num_ports) {
+                       serial->num_bulk_out < serial->num_ports ||
+                       serial->num_interrupt_in < 1) {
                dev_err(&serial->interface->dev, "missing endpoints\n");
                return -ENODEV;
        }
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 5ded6f524d59..b3c64f557d60 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -142,7 +142,7 @@ static int opticon_open(struct tty_struct *tty, struct 
usb_serial_port *port)
        usb_clear_halt(port->serial->dev, port->read_urb->pipe);
 
        res = usb_serial_generic_open(tty, port);
-       if (!res)
+       if (res)
                return res;
 
        /* Request CTS line state, sometimes during opening the current
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 475e6c31b266..ddfd787c461c 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -232,11 +232,17 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, 
u8 *status)
        ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
                              GET_UART_STATUS, GET_UART_STATUS_TYPE,
                              0, GET_UART_STATUS_MSR, buf, 1, 100);
-       if (ret < 0)
+       if (ret < 1) {
                dev_err(&port->dev, "failed to get modem status: %d\n", ret);
+               if (ret >= 0)
+                       ret = -EIO;
+               goto out;
+       }
 
        dev_dbg(&port->dev, "0xc0:0x22:0:6  %d - 0x02%x\n", ret, *buf);
        *status = *buf;
+       ret = 0;
+out:
        kfree(buf);
 
        return ret;
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 1aa3abd67b36..fdecf79d2fa4 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -1102,7 +1102,15 @@ xfs_file_iomap_end_delalloc(
        xfs_fileoff_t           end_fsb;
        int                     error = 0;
 
-       start_fsb = XFS_B_TO_FSB(mp, offset + written);
+       /*
+        * start_fsb refers to the first unused block after a short write. If
+        * nothing was written, round offset down to point at the first block in
+        * the range.
+        */
+       if (unlikely(!written))
+               start_fsb = XFS_B_TO_FSBT(mp, offset);
+       else
+               start_fsb = XFS_B_TO_FSB(mp, offset + written);
        end_fsb = XFS_B_TO_FSB(mp, offset + length);
 
        /*
@@ -1114,6 +1122,9 @@ xfs_file_iomap_end_delalloc(
         * blocks in the range, they are ours.
         */
        if (start_fsb < end_fsb) {
+               truncate_pagecache_range(VFS_I(ip), XFS_FSB_TO_B(mp, start_fsb),
+                                        XFS_FSB_TO_B(mp, end_fsb) - 1);
+
                xfs_ilock(ip, XFS_ILOCK_EXCL);
                error = xfs_bmap_punch_delalloc_range(ip, start_fsb,
                                               end_fsb - start_fsb);
diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
index 34cce729109c..fca15390a42c 100644
--- a/include/acpi/platform/acenv.h
+++ b/include/acpi/platform/acenv.h
@@ -177,7 +177,7 @@
 #include "acmsvc.h"
 
 #elif defined(__INTEL_COMPILER)
-#include "acintel.h"
+#include <acpi/platform/acintel.h>
 
 #endif
 
diff --git a/include/acpi/platform/acintel.h b/include/acpi/platform/acintel.h
new file mode 100644
index 000000000000..17bd3b7b4e5a
--- /dev/null
+++ b/include/acpi/platform/acintel.h
@@ -0,0 +1,87 @@
+/******************************************************************************
+ *
+ * Name: acintel.h - VC specific defines, etc.
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2017, Intel Corp.
+ * 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,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#ifndef __ACINTEL_H__
+#define __ACINTEL_H__
+
+/*
+ * Use compiler specific <stdarg.h> is a good practice for even when
+ * -nostdinc is specified (i.e., ACPI_USE_STANDARD_HEADERS undefined.
+ */
+#include <stdarg.h>
+
+/* Configuration specific to Intel 64-bit C compiler */
+
+#define COMPILER_DEPENDENT_INT64    __int64
+#define COMPILER_DEPENDENT_UINT64   unsigned __int64
+#define ACPI_INLINE                 __inline
+
+/*
+ * Calling conventions:
+ *
+ * ACPI_SYSTEM_XFACE        - Interfaces to host OS (handlers, threads)
+ * ACPI_EXTERNAL_XFACE      - External ACPI interfaces
+ * ACPI_INTERNAL_XFACE      - Internal ACPI interfaces
+ * ACPI_INTERNAL_VAR_XFACE  - Internal variable-parameter list interfaces
+ */
+#define ACPI_SYSTEM_XFACE
+#define ACPI_EXTERNAL_XFACE
+#define ACPI_INTERNAL_XFACE
+#define ACPI_INTERNAL_VAR_XFACE
+
+/* remark 981 - operands evaluated in no particular order */
+#pragma warning(disable:981)
+
+/* warn C4100: unreferenced formal parameter */
+#pragma warning(disable:4100)
+
+/* warn C4127: conditional expression is constant */
+#pragma warning(disable:4127)
+
+/* warn C4706: assignment within conditional expression */
+#pragma warning(disable:4706)
+
+/* warn C4214: bit field types other than int */
+#pragma warning(disable:4214)
+
+#endif                         /* __ACINTEL_H__ */
diff --git a/include/linux/ptr_ring.h b/include/linux/ptr_ring.h
index 2052011bf9fb..6c70444da3b9 100644
--- a/include/linux/ptr_ring.h
+++ b/include/linux/ptr_ring.h
@@ -111,6 +111,11 @@ static inline int __ptr_ring_produce(struct ptr_ring *r, 
void *ptr)
        return 0;
 }
 
+/*
+ * Note: resize (below) nests producer lock within consumer lock, so if you
+ * consume in interrupt or BH context, you must disable interrupts/BH when
+ * calling this.
+ */
 static inline int ptr_ring_produce(struct ptr_ring *r, void *ptr)
 {
        int ret;
@@ -242,6 +247,11 @@ static inline void *__ptr_ring_consume(struct ptr_ring *r)
        return ptr;
 }
 
+/*
+ * Note: resize (below) nests producer lock within consumer lock, so if you
+ * call this in interrupt or BH context, you must disable interrupts/BH when
+ * producing.
+ */
 static inline void *ptr_ring_consume(struct ptr_ring *r)
 {
        void *ptr;
@@ -357,7 +367,7 @@ static inline void **__ptr_ring_swap_queue(struct ptr_ring 
*r, void **queue,
        void **old;
        void *ptr;
 
-       while ((ptr = ptr_ring_consume(r)))
+       while ((ptr = __ptr_ring_consume(r)))
                if (producer < size)
                        queue[producer++] = ptr;
                else if (destroy)
@@ -372,6 +382,12 @@ static inline void **__ptr_ring_swap_queue(struct ptr_ring 
*r, void **queue,
        return old;
 }
 
+/*
+ * Note: producer lock is nested within consumer lock, so if you
+ * resize you must make sure all uses nest correctly.
+ * In particular if you consume ring in interrupt or BH context, you must
+ * disable interrupts/BH when doing so.
+ */
 static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
                                  void (*destroy)(void *))
 {
@@ -382,17 +398,25 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int 
size, gfp_t gfp,
        if (!queue)
                return -ENOMEM;
 
-       spin_lock_irqsave(&(r)->producer_lock, flags);
+       spin_lock_irqsave(&(r)->consumer_lock, flags);
+       spin_lock(&(r)->producer_lock);
 
        old = __ptr_ring_swap_queue(r, queue, size, gfp, destroy);
 
-       spin_unlock_irqrestore(&(r)->producer_lock, flags);
+       spin_unlock(&(r)->producer_lock);
+       spin_unlock_irqrestore(&(r)->consumer_lock, flags);
 
        kfree(old);
 
        return 0;
 }
 
+/*
+ * Note: producer lock is nested within consumer lock, so if you
+ * resize you must make sure all uses nest correctly.
+ * In particular if you consume ring in interrupt or BH context, you must
+ * disable interrupts/BH when doing so.
+ */
 static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings,
                                           int size,
                                           gfp_t gfp, void (*destroy)(void *))
@@ -412,10 +436,12 @@ static inline int ptr_ring_resize_multiple(struct 
ptr_ring **rings, int nrings,
        }
 
        for (i = 0; i < nrings; ++i) {
-               spin_lock_irqsave(&(rings[i])->producer_lock, flags);
+               spin_lock_irqsave(&(rings[i])->consumer_lock, flags);
+               spin_lock(&(rings[i])->producer_lock);
                queues[i] = __ptr_ring_swap_queue(rings[i], queues[i],
                                                  size, gfp, destroy);
-               spin_unlock_irqrestore(&(rings[i])->producer_lock, flags);
+               spin_unlock(&(rings[i])->producer_lock);
+               spin_unlock_irqrestore(&(rings[i])->consumer_lock, flags);
        }
 
        for (i = 0; i < nrings; ++i)
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 3bfed5ab2475..61b34071e3ee 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -758,15 +758,20 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
        if (!bdi->wb_congested)
                return -ENOMEM;
 
+       atomic_set(&bdi->wb_congested->refcnt, 1);
+
        err = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL);
        if (err) {
-               kfree(bdi->wb_congested);
+               wb_congested_put(bdi->wb_congested);
                return err;
        }
        return 0;
 }
 
-static void cgwb_bdi_destroy(struct backing_dev_info *bdi) { }
+static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
+{
+       wb_congested_put(bdi->wb_congested);
+}
 
 #endif /* CONFIG_CGROUP_WRITEBACK */
 
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 900011709e3b..fc4bf4d54158 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -116,10 +116,10 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, 
struct sk_buff *skb,
        if (skb->ip_summed != CHECKSUM_COMPLETE)
                return;
 
-       if (offset != 0)
-               csum = csum_sub(csum,
-                               csum_partial(skb_transport_header(skb) + tlen,
-                                            offset, 0));
+       if (offset != 0) {
+               int tend_off = skb_transport_offset(skb) + tlen;
+               csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0));
+       }
 
        put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum);
 }
diff --git a/net/netfilter/nf_conntrack_helper.c 
b/net/netfilter/nf_conntrack_helper.c
index 7341adf7059d..6dc44d9b4190 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -188,6 +188,26 @@ nf_ct_helper_ext_add(struct nf_conn *ct,
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add);
 
+static struct nf_conntrack_helper *
+nf_ct_lookup_helper(struct nf_conn *ct, struct net *net)
+{
+       if (!net->ct.sysctl_auto_assign_helper) {
+               if (net->ct.auto_assign_helper_warned)
+                       return NULL;
+               if (!__nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple))
+                       return NULL;
+               pr_info("nf_conntrack: default automatic helper assignment "
+                       "has been turned off for security reasons and CT-based "
+                       " firewall rule not found. Use the iptables CT target "
+                       "to attach helpers instead.\n");
+               net->ct.auto_assign_helper_warned = 1;
+               return NULL;
+       }
+
+       return __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+}
+
+
 int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
                              gfp_t flags)
 {
@@ -213,21 +233,14 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct 
nf_conn *tmpl,
        }
 
        help = nfct_help(ct);
-       if (net->ct.sysctl_auto_assign_helper && helper == NULL) {
-               helper = 
__nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
-               if (unlikely(!net->ct.auto_assign_helper_warned && helper)) {
-                       pr_info("nf_conntrack: automatic helper "
-                               "assignment is deprecated and it will "
-                               "be removed soon. Use the iptables CT target "
-                               "to attach helpers instead.\n");
-                       net->ct.auto_assign_helper_warned = true;
-               }
-       }
 
        if (helper == NULL) {
-               if (help)
-                       RCU_INIT_POINTER(help->helper, NULL);
-               return 0;
+               helper = nf_ct_lookup_helper(ct, net);
+               if (helper == NULL) {
+                       if (help)
+                               RCU_INIT_POINTER(help->helper, NULL);
+                       return 0;
+               }
        }
 
        if (help == NULL) {
diff --git a/net/socket.c b/net/socket.c
index 0758e13754e2..02bd9249e295 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2228,8 +2228,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, 
unsigned int vlen,
                return err;
 
        err = sock_error(sock->sk);
-       if (err)
+       if (err) {
+               datagrams = err;
                goto out_put;
+       }
 
        entry = mmsg;
        compat_entry = (struct compat_mmsghdr __user *)mmsg;

Reply via email to