diff options
Diffstat (limited to '4.9.13/1012_linux-4.9.13.patch')
-rw-r--r-- | 4.9.13/1012_linux-4.9.13.patch | 1079 |
1 files changed, 0 insertions, 1079 deletions
diff --git a/4.9.13/1012_linux-4.9.13.patch b/4.9.13/1012_linux-4.9.13.patch deleted file mode 100644 index 8a48815..0000000 --- a/4.9.13/1012_linux-4.9.13.patch +++ /dev/null @@ -1,1079 +0,0 @@ -diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 922dec8..65b05ba 100644 ---- a/Documentation/kernel-parameters.txt -+++ b/Documentation/kernel-parameters.txt -@@ -1391,6 +1391,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. - 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 3cd6f6f..14dc275 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 9 --SUBLEVEL = 12 -+SUBLEVEL = 13 - EXTRAVERSION = - NAME = Roaring Lionus - -diff --git a/arch/x86/platform/goldfish/goldfish.c b/arch/x86/platform/goldfish/goldfish.c -index 1693107..0d17c0a 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/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c -index 6bb21b3..a543ea6 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c -@@ -567,10 +567,14 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv, - - mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse); - -+ preempt_disable(); -+ - tcf_exts_to_list(f->exts, &actions); - list_for_each_entry(a, &actions, list) - tcf_action_stats_update(a, bytes, packets, lastuse); - -+ preempt_enable(); -+ - return 0; - } - -diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c -index b9087b8..3f1971d 100644 ---- a/drivers/net/ethernet/ti/cpsw.c -+++ b/drivers/net/ethernet/ti/cpsw.c -@@ -2925,7 +2925,7 @@ static int cpsw_resume(struct device *dev) - { - struct platform_device *pdev = to_platform_device(dev); - struct net_device *ndev = platform_get_drvdata(pdev); -- struct cpsw_common *cpsw = netdev_priv(ndev); -+ struct cpsw_common *cpsw = ndev_to_cpsw(ndev); - - /* Select default pin state */ - pinctrl_pm_select_default_state(dev); -diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c -index 0fafaa9..d4f495b 100644 ---- a/drivers/net/vxlan.c -+++ b/drivers/net/vxlan.c -@@ -2449,7 +2449,8 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) - return -EINVAL; - rt = vxlan_get_route(vxlan, skb, 0, info->key.tos, - info->key.u.ipv4.dst, -- &info->key.u.ipv4.src, NULL, info); -+ &info->key.u.ipv4.src, -+ &info->dst_cache, info); - if (IS_ERR(rt)) - return PTR_ERR(rt); - ip_rt_put(rt); -@@ -2459,7 +2460,8 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) - - ndst = vxlan6_get_route(vxlan, skb, 0, info->key.tos, - info->key.label, &info->key.u.ipv6.dst, -- &info->key.u.ipv6.src, NULL, info); -+ &info->key.u.ipv6.src, -+ &info->dst_cache, info); - if (IS_ERR(ndst)) - return PTR_ERR(ndst); - dst_release(ndst); -diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c -index 3837bbd..ae0c48f 100644 ---- a/drivers/net/wireless/realtek/rtlwifi/usb.c -+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c -@@ -831,12 +831,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 1f52462..dd9ea46 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 7312e7e..6788e75 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 1532cde..7812052 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 8967715..b6f1ade 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 243ac5e..8bb4875 100644 ---- a/drivers/usb/serial/cp210x.c -+++ b/drivers/usb/serial/cp210x.c -@@ -172,6 +172,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 6e9fc8b..99a0a5f 100644 ---- a/drivers/usb/serial/ftdi_sio.c -+++ b/drivers/usb/serial/ftdi_sio.c -@@ -1807,8 +1807,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); - -@@ -2072,6 +2070,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 -@@ -2094,15 +2106,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; - -@@ -2433,8 +2436,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 4f9af47..5c4fc3a 100644 ---- a/drivers/usb/serial/mos7840.c -+++ b/drivers/usb/serial/mos7840.c -@@ -1024,6 +1024,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, -@@ -2119,7 +2120,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 4b7bfb3..64bf258 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 475e6c3..ddfd787 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 cdc6bdd..e888961 100644 ---- a/fs/xfs/xfs_iomap.c -+++ b/fs/xfs/xfs_iomap.c -@@ -1068,7 +1068,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); - - /* -@@ -1080,6 +1088,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 34cce72..fca1539 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 0000000..17bd3b7 ---- /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 2052011..6c70444 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 8fde443..6ff2d77 100644 ---- a/mm/backing-dev.c -+++ b/mm/backing-dev.c -@@ -757,15 +757,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/core/neighbour.c b/net/core/neighbour.c -index 2ae929f..9901e5b 100644 ---- a/net/core/neighbour.c -+++ b/net/core/neighbour.c -@@ -2927,7 +2927,8 @@ static void neigh_proc_update(struct ctl_table *ctl, int write) - return; - - set_bit(index, p->data_state); -- call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p); -+ if (index == NEIGH_VAR_DELAY_PROBE_TIME) -+ call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p); - if (!dev) /* NULL dev means this is default value */ - neigh_copy_dflt_parms(net, p, index); - } -diff --git a/net/dccp/input.c b/net/dccp/input.c -index ba34718..8fedc2d 100644 ---- a/net/dccp/input.c -+++ b/net/dccp/input.c -@@ -606,7 +606,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, - if (inet_csk(sk)->icsk_af_ops->conn_request(sk, - skb) < 0) - return 1; -- goto discard; -+ consume_skb(skb); -+ return 0; - } - if (dh->dccph_type == DCCP_PKT_RESET) - goto discard; -diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c -index 65336f3..9826695 100644 ---- a/net/ipv4/ip_sockglue.c -+++ b/net/ipv4/ip_sockglue.c -@@ -105,10 +105,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/irda/irqueue.c b/net/irda/irqueue.c -index acbe61c..160dc89 100644 ---- a/net/irda/irqueue.c -+++ b/net/irda/irqueue.c -@@ -383,9 +383,6 @@ EXPORT_SYMBOL(hashbin_new); - * for deallocating this structure if it's complex. If not the user can - * just supply kfree, which should take care of the job. - */ --#ifdef CONFIG_LOCKDEP --static int hashbin_lock_depth = 0; --#endif - int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) - { - irda_queue_t* queue; -@@ -396,22 +393,27 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) - IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;); - - /* Synchronize */ -- if ( hashbin->hb_type & HB_LOCK ) { -- spin_lock_irqsave_nested(&hashbin->hb_spinlock, flags, -- hashbin_lock_depth++); -- } -+ if (hashbin->hb_type & HB_LOCK) -+ spin_lock_irqsave(&hashbin->hb_spinlock, flags); - - /* - * Free the entries in the hashbin, TODO: use hashbin_clear when - * it has been shown to work - */ - for (i = 0; i < HASHBIN_SIZE; i ++ ) { -- queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); -- while (queue ) { -- if (free_func) -- (*free_func)(queue); -- queue = dequeue_first( -- (irda_queue_t**) &hashbin->hb_queue[i]); -+ while (1) { -+ queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); -+ -+ if (!queue) -+ break; -+ -+ if (free_func) { -+ if (hashbin->hb_type & HB_LOCK) -+ spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); -+ free_func(queue); -+ if (hashbin->hb_type & HB_LOCK) -+ spin_lock_irqsave(&hashbin->hb_spinlock, flags); -+ } - } - } - -@@ -420,12 +422,8 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) - hashbin->magic = ~HB_MAGIC; - - /* Release lock */ -- if ( hashbin->hb_type & HB_LOCK) { -+ if (hashbin->hb_type & HB_LOCK) - spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); --#ifdef CONFIG_LOCKDEP -- hashbin_lock_depth--; --#endif -- } - - /* - * Free the hashbin structure -diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c -index 7e08a4d..a646f34 100644 ---- a/net/kcm/kcmsock.c -+++ b/net/kcm/kcmsock.c -@@ -929,23 +929,25 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) - goto out_error; - } - -- /* New message, alloc head skb */ -- head = alloc_skb(0, sk->sk_allocation); -- while (!head) { -- kcm_push(kcm); -- err = sk_stream_wait_memory(sk, &timeo); -- if (err) -- goto out_error; -- -+ if (msg_data_left(msg)) { -+ /* New message, alloc head skb */ - head = alloc_skb(0, sk->sk_allocation); -- } -+ while (!head) { -+ kcm_push(kcm); -+ err = sk_stream_wait_memory(sk, &timeo); -+ if (err) -+ goto out_error; - -- skb = head; -+ head = alloc_skb(0, sk->sk_allocation); -+ } - -- /* Set ip_summed to CHECKSUM_UNNECESSARY to avoid calling -- * csum_and_copy_from_iter from skb_do_copy_data_nocache. -- */ -- skb->ip_summed = CHECKSUM_UNNECESSARY; -+ skb = head; -+ -+ /* Set ip_summed to CHECKSUM_UNNECESSARY to avoid calling -+ * csum_and_copy_from_iter from skb_do_copy_data_nocache. -+ */ -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ } - - start: - while (msg_data_left(msg)) { -@@ -1018,10 +1020,12 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) - if (eor) { - bool not_busy = skb_queue_empty(&sk->sk_write_queue); - -- /* Message complete, queue it on send buffer */ -- __skb_queue_tail(&sk->sk_write_queue, head); -- kcm->seq_skb = NULL; -- KCM_STATS_INCR(kcm->stats.tx_msgs); -+ if (head) { -+ /* Message complete, queue it on send buffer */ -+ __skb_queue_tail(&sk->sk_write_queue, head); -+ kcm->seq_skb = NULL; -+ KCM_STATS_INCR(kcm->stats.tx_msgs); -+ } - - if (msg->msg_flags & MSG_BATCH) { - kcm->tx_wait_more = true; -@@ -1040,8 +1044,10 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) - } else { - /* Message not complete, save state */ - partial_message: -- kcm->seq_skb = head; -- kcm_tx_msg(head)->last_skb = skb; -+ if (head) { -+ kcm->seq_skb = head; -+ kcm_tx_msg(head)->last_skb = skb; -+ } - } - - KCM_STATS_ADD(kcm->stats.tx_bytes, copied); -diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c -index 3e821da..8bc5a1b 100644 ---- a/net/llc/llc_conn.c -+++ b/net/llc/llc_conn.c -@@ -821,7 +821,10 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) - * another trick required to cope with how the PROCOM state - * machine works. -acme - */ -+ skb_orphan(skb); -+ sock_hold(sk); - skb->sk = sk; -+ skb->destructor = sock_efree; - } - if (!sock_owned_by_user(sk)) - llc_conn_rcv(sk, skb); -diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c -index d0e1e80..5404d0d 100644 ---- a/net/llc/llc_sap.c -+++ b/net/llc/llc_sap.c -@@ -290,7 +290,10 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb, - - ev->type = LLC_SAP_EV_TYPE_PDU; - ev->reason = 0; -+ skb_orphan(skb); -+ sock_hold(sk); - skb->sk = sk; -+ skb->destructor = sock_efree; - llc_sap_state_process(sap, skb); - } - -diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c -index 7341adf..6dc44d9 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/packet/af_packet.c b/net/packet/af_packet.c -index 458722b..34de326 100644 ---- a/net/packet/af_packet.c -+++ b/net/packet/af_packet.c -@@ -1497,6 +1497,8 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po) - f->arr[f->num_members] = sk; - smp_wmb(); - f->num_members++; -+ if (f->num_members == 1) -+ dev_add_pack(&f->prot_hook); - spin_unlock(&f->lock); - } - -@@ -1513,6 +1515,8 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po) - BUG_ON(i >= f->num_members); - f->arr[i] = f->arr[f->num_members - 1]; - f->num_members--; -+ if (f->num_members == 0) -+ __dev_remove_pack(&f->prot_hook); - spin_unlock(&f->lock); - } - -@@ -1619,6 +1623,7 @@ static void fanout_release_data(struct packet_fanout *f) - - static int fanout_add(struct sock *sk, u16 id, u16 type_flags) - { -+ struct packet_rollover *rollover = NULL; - struct packet_sock *po = pkt_sk(sk); - struct packet_fanout *f, *match; - u8 type = type_flags & 0xff; -@@ -1641,23 +1646,28 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) - return -EINVAL; - } - -+ mutex_lock(&fanout_mutex); -+ -+ err = -EINVAL; - if (!po->running) -- return -EINVAL; -+ goto out; - -+ err = -EALREADY; - if (po->fanout) -- return -EALREADY; -+ goto out; - - if (type == PACKET_FANOUT_ROLLOVER || - (type_flags & PACKET_FANOUT_FLAG_ROLLOVER)) { -- po->rollover = kzalloc(sizeof(*po->rollover), GFP_KERNEL); -- if (!po->rollover) -- return -ENOMEM; -- atomic_long_set(&po->rollover->num, 0); -- atomic_long_set(&po->rollover->num_huge, 0); -- atomic_long_set(&po->rollover->num_failed, 0); -+ err = -ENOMEM; -+ rollover = kzalloc(sizeof(*rollover), GFP_KERNEL); -+ if (!rollover) -+ goto out; -+ atomic_long_set(&rollover->num, 0); -+ atomic_long_set(&rollover->num_huge, 0); -+ atomic_long_set(&rollover->num_failed, 0); -+ po->rollover = rollover; - } - -- mutex_lock(&fanout_mutex); - match = NULL; - list_for_each_entry(f, &fanout_list, list) { - if (f->id == id && -@@ -1687,7 +1697,6 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) - match->prot_hook.func = packet_rcv_fanout; - match->prot_hook.af_packet_priv = match; - match->prot_hook.id_match = match_fanout_group; -- dev_add_pack(&match->prot_hook); - list_add(&match->list, &fanout_list); - } - err = -EINVAL; -@@ -1704,36 +1713,40 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) - } - } - out: -- mutex_unlock(&fanout_mutex); -- if (err) { -- kfree(po->rollover); -+ if (err && rollover) { -+ kfree(rollover); - po->rollover = NULL; - } -+ mutex_unlock(&fanout_mutex); - return err; - } - --static void fanout_release(struct sock *sk) -+/* If pkt_sk(sk)->fanout->sk_ref is zero, this function removes -+ * pkt_sk(sk)->fanout from fanout_list and returns pkt_sk(sk)->fanout. -+ * It is the responsibility of the caller to call fanout_release_data() and -+ * free the returned packet_fanout (after synchronize_net()) -+ */ -+static struct packet_fanout *fanout_release(struct sock *sk) - { - struct packet_sock *po = pkt_sk(sk); - struct packet_fanout *f; - -+ mutex_lock(&fanout_mutex); - f = po->fanout; -- if (!f) -- return; -+ if (f) { -+ po->fanout = NULL; - -- mutex_lock(&fanout_mutex); -- po->fanout = NULL; -+ if (atomic_dec_and_test(&f->sk_ref)) -+ list_del(&f->list); -+ else -+ f = NULL; - -- if (atomic_dec_and_test(&f->sk_ref)) { -- list_del(&f->list); -- dev_remove_pack(&f->prot_hook); -- fanout_release_data(f); -- kfree(f); -+ if (po->rollover) -+ kfree_rcu(po->rollover, rcu); - } - mutex_unlock(&fanout_mutex); - -- if (po->rollover) -- kfree_rcu(po->rollover, rcu); -+ return f; - } - - static bool packet_extra_vlan_len_allowed(const struct net_device *dev, -@@ -2965,6 +2978,7 @@ static int packet_release(struct socket *sock) - { - struct sock *sk = sock->sk; - struct packet_sock *po; -+ struct packet_fanout *f; - struct net *net; - union tpacket_req_u req_u; - -@@ -3004,9 +3018,14 @@ static int packet_release(struct socket *sock) - packet_set_ring(sk, &req_u, 1, 1); - } - -- fanout_release(sk); -+ f = fanout_release(sk); - - synchronize_net(); -+ -+ if (f) { -+ fanout_release_data(f); -+ kfree(f); -+ } - /* - * Now the socket is dead. No more input will appear. - */ -@@ -3958,7 +3977,6 @@ static int packet_notifier(struct notifier_block *this, - } - if (msg == NETDEV_UNREGISTER) { - packet_cached_dev_reset(po); -- fanout_release(sk); - po->ifindex = -1; - if (po->prot_hook.dev) - dev_put(po->prot_hook.dev); -diff --git a/net/socket.c b/net/socket.c -index 73dc69f..6bbccf0 100644 ---- a/net/socket.c -+++ b/net/socket.c -@@ -2197,8 +2197,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; |