summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2017-02-26 20:08:24 -0500
committerMike Pagano <mpagano@gentoo.org>2017-02-26 20:08:24 -0500
commita7614e16e5934261b1d377edad0f36a133adeb96 (patch)
tree825538d8fd4a951682bb74b45c10ce522a7a552e
parentFor GENTOO_LINUX_INIT_SYSTEMD don't add DMIID for non X86 architectures. See ... (diff)
downloadlinux-patches-a7614e16.tar.gz
linux-patches-a7614e16.tar.bz2
linux-patches-a7614e16.zip
Linux patch 4.10.14.10-2
-rw-r--r--0000_README4
-rw-r--r--1000_linux-4.10.1.patch661
2 files changed, 665 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index 58e3c749..decfe627 100644
--- a/0000_README
+++ b/0000_README
@@ -43,6 +43,10 @@ EXPERIMENTAL
Individual Patch Descriptions:
--------------------------------------------------------------------------
+Patch: 1000_linux-4.10.1.patch
+From: http://www.kernel.org
+Desc: Linux 4.10.1
+
Patch: 1500_XATTR_USER_PREFIX.patch
From: https://bugs.gentoo.org/show_bug.cgi?id=470644
Desc: Support for namespace user.pax.* on tmpfs.
diff --git a/1000_linux-4.10.1.patch b/1000_linux-4.10.1.patch
new file mode 100644
index 00000000..7b19ec2a
--- /dev/null
+++ b/1000_linux-4.10.1.patch
@@ -0,0 +1,661 @@
+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;