Merge remote-tracking branch 'stable/linux-4.9.y' into rpi-4.9.y

This commit is contained in:
popcornmix
2017-02-26 19:08:53 +00:00
31 changed files with 368 additions and 125 deletions

View File

@@ -1391,6 +1391,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
When zero, profiling data is discarded and associated When zero, profiling data is discarded and associated
debugfs files are removed at module unload time. 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 gpt [EFI] Forces disk with valid GPT signature but
invalid Protective MBR to be treated as GPT. If the invalid Protective MBR to be treated as GPT. If the
primary GPT is corrupted, it enables the backup/alternate primary GPT is corrupted, it enables the backup/alternate

View File

@@ -1,6 +1,6 @@
VERSION = 4 VERSION = 4
PATCHLEVEL = 9 PATCHLEVEL = 9
SUBLEVEL = 12 SUBLEVEL = 13
EXTRAVERSION = EXTRAVERSION =
NAME = Roaring Lionus NAME = Roaring Lionus

View File

@@ -42,8 +42,20 @@ 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) static int __init goldfish_init(void)
{ {
if (!goldfish_enable)
return -ENODEV;
platform_device_register_simple("goldfish_pdev_bus", -1, platform_device_register_simple("goldfish_pdev_bus", -1,
goldfish_pdev_bus_resources, 2); goldfish_pdev_bus_resources, 2);
return 0; return 0;

View File

@@ -567,10 +567,14 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse); mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
preempt_disable();
tcf_exts_to_list(f->exts, &actions); tcf_exts_to_list(f->exts, &actions);
list_for_each_entry(a, &actions, list) list_for_each_entry(a, &actions, list)
tcf_action_stats_update(a, bytes, packets, lastuse); tcf_action_stats_update(a, bytes, packets, lastuse);
preempt_enable();
return 0; return 0;
} }

View File

@@ -2925,7 +2925,7 @@ static int cpsw_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev = platform_get_drvdata(pdev); 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 */ /* Select default pin state */
pinctrl_pm_select_default_state(dev); pinctrl_pm_select_default_state(dev);

View File

@@ -2449,7 +2449,8 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
return -EINVAL; return -EINVAL;
rt = vxlan_get_route(vxlan, skb, 0, info->key.tos, rt = vxlan_get_route(vxlan, skb, 0, info->key.tos,
info->key.u.ipv4.dst, 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)) if (IS_ERR(rt))
return PTR_ERR(rt); return PTR_ERR(rt);
ip_rt_put(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, ndst = vxlan6_get_route(vxlan, skb, 0, info->key.tos,
info->key.label, &info->key.u.ipv6.dst, 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)) if (IS_ERR(ndst))
return PTR_ERR(ndst); return PTR_ERR(ndst);
dst_release(ndst); dst_release(ndst);

View File

@@ -831,12 +831,30 @@ static void rtl_usb_stop(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
struct urb *urb;
/* should after adapter start and interrupt enable. */ /* should after adapter start and interrupt enable. */
set_hal_stop(rtlhal); set_hal_stop(rtlhal);
cancel_work_sync(&rtlpriv->works.fill_h2c_cmd); cancel_work_sync(&rtlpriv->works.fill_h2c_cmd);
/* Enable software */ /* Enable software */
SET_USB_STOP(rtlusb); 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); rtlpriv->cfg->ops->hw_disable(hw);
} }

View File

@@ -157,23 +157,26 @@ static int goldfish_new_pdev(void)
static irqreturn_t goldfish_pdev_bus_interrupt(int irq, void *dev_id) static irqreturn_t goldfish_pdev_bus_interrupt(int irq, void *dev_id)
{ {
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
while (1) { while (1) {
u32 op = readl(pdev_bus_base + PDEV_BUS_OP); 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: case PDEV_BUS_OP_REMOVE_DEV:
goldfish_pdev_remove(); goldfish_pdev_remove();
ret = IRQ_HANDLED;
break; break;
case PDEV_BUS_OP_ADD_DEV: case PDEV_BUS_OP_ADD_DEV:
goldfish_new_pdev(); goldfish_new_pdev();
break;
}
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
} break;
case PDEV_BUS_OP_DONE:
default:
return ret; return ret;
}
}
} }
static int goldfish_pdev_bus_probe(struct platform_device *pdev) static int goldfish_pdev_bus_probe(struct platform_device *pdev)

View File

@@ -1809,6 +1809,7 @@ static const struct of_device_id msm_match_table[] = {
{ .compatible = "qcom,msm-uartdm" }, { .compatible = "qcom,msm-uartdm" },
{} {}
}; };
MODULE_DEVICE_TABLE(of, msm_match_table);
static struct platform_driver msm_platform_driver = { static struct platform_driver msm_platform_driver = {
.remove = msm_serial_remove, .remove = msm_serial_remove,

View File

@@ -99,9 +99,16 @@ static int ark3116_read_reg(struct usb_serial *serial,
usb_rcvctrlpipe(serial->dev, 0), usb_rcvctrlpipe(serial->dev, 0),
0xfe, 0xc0, 0, reg, 0xfe, 0xc0, 0, reg,
buf, 1, ARK_TIMEOUT); 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; return result;
else }
return buf[0]; return buf[0];
} }

View File

@@ -143,6 +143,7 @@ static int usb_console_setup(struct console *co, char *options)
tty->driver = usb_serial_tty_driver; tty->driver = usb_serial_tty_driver;
tty->index = co->index; tty->index = co->index;
init_ldsem(&tty->ldisc_sem); init_ldsem(&tty->ldisc_sem);
spin_lock_init(&tty->files_lock);
INIT_LIST_HEAD(&tty->tty_files); INIT_LIST_HEAD(&tty->tty_files);
kref_get(&tty->driver->kref); kref_get(&tty->driver->kref);
__module_get(tty->driver->owner); __module_get(tty->driver->owner);

View File

@@ -172,6 +172,8 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */
{ USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */ { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
{ USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ { 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(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
{ USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
{ USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */

View File

@@ -1807,8 +1807,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
mutex_init(&priv->cfg_lock); mutex_init(&priv->cfg_lock);
priv->flags = ASYNC_LOW_LATENCY;
if (quirk && quirk->port_probe) if (quirk && quirk->port_probe)
quirk->port_probe(priv); quirk->port_probe(priv);
@@ -2072,6 +2070,20 @@ static int ftdi_process_packet(struct usb_serial_port *port,
priv->prev_status = status; 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; flag = TTY_NORMAL;
if (packet[1] & FTDI_RS_ERR_MASK) { if (packet[1] & FTDI_RS_ERR_MASK) {
/* Break takes precedence over parity, which takes precedence /* 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; port->icount.rx += len;
ch = packet + 2; 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, FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
0, priv->interface, 0, priv->interface,
buf, len, WDR_TIMEOUT); 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); dev_err(&port->dev, "failed to get modem status: %d\n", ret);
if (ret >= 0)
ret = -EIO;
ret = usb_translate_errors(ret); ret = usb_translate_errors(ret);
goto out; goto out;
} }

View File

@@ -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 * * (can't set it up in mos7840_startup as the structures *
* were not set up at that time.) */ * were not set up at that time.) */
if (port0->open_ports == 1) { if (port0->open_ports == 1) {
/* FIXME: Buffer never NULL, so URB is not submitted. */
if (serial->port[0]->interrupt_in_buffer == NULL) { if (serial->port[0]->interrupt_in_buffer == NULL) {
/* set up interrupt urb */ /* set up interrupt urb */
usb_fill_int_urb(serial->port[0]->interrupt_in_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) static int mos7840_attach(struct usb_serial *serial)
{ {
if (serial->num_bulk_in < serial->num_ports || 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"); dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV; return -ENODEV;
} }

View File

@@ -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); usb_clear_halt(port->serial->dev, port->read_urb->pipe);
res = usb_serial_generic_open(tty, port); res = usb_serial_generic_open(tty, port);
if (!res) if (res)
return res; return res;
/* Request CTS line state, sometimes during opening the current /* Request CTS line state, sometimes during opening the current

View File

@@ -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), ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
GET_UART_STATUS, GET_UART_STATUS_TYPE, GET_UART_STATUS, GET_UART_STATUS_TYPE,
0, GET_UART_STATUS_MSR, buf, 1, 100); 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); 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); dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x\n", ret, *buf);
*status = *buf; *status = *buf;
ret = 0;
out:
kfree(buf); kfree(buf);
return ret; return ret;

View File

@@ -1068,6 +1068,14 @@ xfs_file_iomap_end_delalloc(
xfs_fileoff_t end_fsb; xfs_fileoff_t end_fsb;
int error = 0; int error = 0;
/*
* 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); start_fsb = XFS_B_TO_FSB(mp, offset + written);
end_fsb = XFS_B_TO_FSB(mp, offset + length); 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. * blocks in the range, they are ours.
*/ */
if (start_fsb < end_fsb) { 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); xfs_ilock(ip, XFS_ILOCK_EXCL);
error = xfs_bmap_punch_delalloc_range(ip, start_fsb, error = xfs_bmap_punch_delalloc_range(ip, start_fsb,
end_fsb - start_fsb); end_fsb - start_fsb);

View File

@@ -177,7 +177,7 @@
#include "acmsvc.h" #include "acmsvc.h"
#elif defined(__INTEL_COMPILER) #elif defined(__INTEL_COMPILER)
#include "acintel.h" #include <acpi/platform/acintel.h>
#endif #endif

View File

@@ -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__ */

View File

@@ -111,6 +111,11 @@ static inline int __ptr_ring_produce(struct ptr_ring *r, void *ptr)
return 0; 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) static inline int ptr_ring_produce(struct ptr_ring *r, void *ptr)
{ {
int ret; int ret;
@@ -242,6 +247,11 @@ static inline void *__ptr_ring_consume(struct ptr_ring *r)
return ptr; 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) static inline void *ptr_ring_consume(struct ptr_ring *r)
{ {
void *ptr; void *ptr;
@@ -357,7 +367,7 @@ static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue,
void **old; void **old;
void *ptr; void *ptr;
while ((ptr = ptr_ring_consume(r))) while ((ptr = __ptr_ring_consume(r)))
if (producer < size) if (producer < size)
queue[producer++] = ptr; queue[producer++] = ptr;
else if (destroy) else if (destroy)
@@ -372,6 +382,12 @@ static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue,
return old; 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, static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
void (*destroy)(void *)) void (*destroy)(void *))
{ {
@@ -382,17 +398,25 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
if (!queue) if (!queue)
return -ENOMEM; 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); 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); kfree(old);
return 0; 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, static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings,
int size, int size,
gfp_t gfp, void (*destroy)(void *)) 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) { 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], queues[i] = __ptr_ring_swap_queue(rings[i], queues[i],
size, gfp, destroy); 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) for (i = 0; i < nrings; ++i)

View File

@@ -757,15 +757,20 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
if (!bdi->wb_congested) if (!bdi->wb_congested)
return -ENOMEM; return -ENOMEM;
atomic_set(&bdi->wb_congested->refcnt, 1);
err = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL); err = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL);
if (err) { if (err) {
kfree(bdi->wb_congested); wb_congested_put(bdi->wb_congested);
return err; return err;
} }
return 0; 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 */ #endif /* CONFIG_CGROUP_WRITEBACK */

View File

@@ -2927,6 +2927,7 @@ static void neigh_proc_update(struct ctl_table *ctl, int write)
return; return;
set_bit(index, p->data_state); set_bit(index, p->data_state);
if (index == NEIGH_VAR_DELAY_PROBE_TIME)
call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p); call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
if (!dev) /* NULL dev means this is default value */ if (!dev) /* NULL dev means this is default value */
neigh_copy_dflt_parms(net, p, index); neigh_copy_dflt_parms(net, p, index);

View File

@@ -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, if (inet_csk(sk)->icsk_af_ops->conn_request(sk,
skb) < 0) skb) < 0)
return 1; return 1;
goto discard; consume_skb(skb);
return 0;
} }
if (dh->dccph_type == DCCP_PKT_RESET) if (dh->dccph_type == DCCP_PKT_RESET)
goto discard; goto discard;

View File

@@ -105,10 +105,10 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
if (skb->ip_summed != CHECKSUM_COMPLETE) if (skb->ip_summed != CHECKSUM_COMPLETE)
return; return;
if (offset != 0) if (offset != 0) {
csum = csum_sub(csum, int tend_off = skb_transport_offset(skb) + tlen;
csum_partial(skb_transport_header(skb) + tlen, csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0));
offset, 0)); }
put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum); put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum);
} }

View File

@@ -383,9 +383,6 @@ EXPORT_SYMBOL(hashbin_new);
* for deallocating this structure if it's complex. If not the user can * for deallocating this structure if it's complex. If not the user can
* just supply kfree, which should take care of the job. * 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) int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
{ {
irda_queue_t* queue; 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;); IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;);
/* Synchronize */ /* Synchronize */
if ( hashbin->hb_type & HB_LOCK ) { if (hashbin->hb_type & HB_LOCK)
spin_lock_irqsave_nested(&hashbin->hb_spinlock, flags, spin_lock_irqsave(&hashbin->hb_spinlock, flags);
hashbin_lock_depth++);
}
/* /*
* Free the entries in the hashbin, TODO: use hashbin_clear when * Free the entries in the hashbin, TODO: use hashbin_clear when
* it has been shown to work * it has been shown to work
*/ */
for (i = 0; i < HASHBIN_SIZE; i ++ ) { for (i = 0; i < HASHBIN_SIZE; i ++ ) {
while (1) {
queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]);
while (queue ) {
if (free_func) if (!queue)
(*free_func)(queue); break;
queue = dequeue_first(
(irda_queue_t**) &hashbin->hb_queue[i]); 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; hashbin->magic = ~HB_MAGIC;
/* Release lock */ /* Release lock */
if ( hashbin->hb_type & HB_LOCK) { if (hashbin->hb_type & HB_LOCK)
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
#ifdef CONFIG_LOCKDEP
hashbin_lock_depth--;
#endif
}
/* /*
* Free the hashbin structure * Free the hashbin structure

View File

@@ -929,6 +929,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
goto out_error; goto out_error;
} }
if (msg_data_left(msg)) {
/* New message, alloc head skb */ /* New message, alloc head skb */
head = alloc_skb(0, sk->sk_allocation); head = alloc_skb(0, sk->sk_allocation);
while (!head) { while (!head) {
@@ -946,6 +947,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
* csum_and_copy_from_iter from skb_do_copy_data_nocache. * csum_and_copy_from_iter from skb_do_copy_data_nocache.
*/ */
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
}
start: start:
while (msg_data_left(msg)) { while (msg_data_left(msg)) {
@@ -1018,10 +1020,12 @@ wait_for_memory:
if (eor) { if (eor) {
bool not_busy = skb_queue_empty(&sk->sk_write_queue); bool not_busy = skb_queue_empty(&sk->sk_write_queue);
if (head) {
/* Message complete, queue it on send buffer */ /* Message complete, queue it on send buffer */
__skb_queue_tail(&sk->sk_write_queue, head); __skb_queue_tail(&sk->sk_write_queue, head);
kcm->seq_skb = NULL; kcm->seq_skb = NULL;
KCM_STATS_INCR(kcm->stats.tx_msgs); KCM_STATS_INCR(kcm->stats.tx_msgs);
}
if (msg->msg_flags & MSG_BATCH) { if (msg->msg_flags & MSG_BATCH) {
kcm->tx_wait_more = true; kcm->tx_wait_more = true;
@@ -1040,9 +1044,11 @@ wait_for_memory:
} else { } else {
/* Message not complete, save state */ /* Message not complete, save state */
partial_message: partial_message:
if (head) {
kcm->seq_skb = head; kcm->seq_skb = head;
kcm_tx_msg(head)->last_skb = skb; kcm_tx_msg(head)->last_skb = skb;
} }
}
KCM_STATS_ADD(kcm->stats.tx_bytes, copied); KCM_STATS_ADD(kcm->stats.tx_bytes, copied);

View File

@@ -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 * another trick required to cope with how the PROCOM state
* machine works. -acme * machine works. -acme
*/ */
skb_orphan(skb);
sock_hold(sk);
skb->sk = sk; skb->sk = sk;
skb->destructor = sock_efree;
} }
if (!sock_owned_by_user(sk)) if (!sock_owned_by_user(sk))
llc_conn_rcv(sk, skb); llc_conn_rcv(sk, skb);

View File

@@ -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->type = LLC_SAP_EV_TYPE_PDU;
ev->reason = 0; ev->reason = 0;
skb_orphan(skb);
sock_hold(sk);
skb->sk = sk; skb->sk = sk;
skb->destructor = sock_efree;
llc_sap_state_process(sap, skb); llc_sap_state_process(sap, skb);
} }

View File

@@ -188,6 +188,26 @@ nf_ct_helper_ext_add(struct nf_conn *ct,
} }
EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); 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, int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
gfp_t flags) gfp_t flags)
{ {
@@ -213,22 +233,15 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
} }
help = nfct_help(ct); 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) {
helper = nf_ct_lookup_helper(ct, net);
if (helper == NULL) { if (helper == NULL) {
if (help) if (help)
RCU_INIT_POINTER(help->helper, NULL); RCU_INIT_POINTER(help->helper, NULL);
return 0; return 0;
} }
}
if (help == NULL) { if (help == NULL) {
help = nf_ct_helper_ext_add(ct, helper, flags); help = nf_ct_helper_ext_add(ct, helper, flags);

View File

@@ -1497,6 +1497,8 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po)
f->arr[f->num_members] = sk; f->arr[f->num_members] = sk;
smp_wmb(); smp_wmb();
f->num_members++; f->num_members++;
if (f->num_members == 1)
dev_add_pack(&f->prot_hook);
spin_unlock(&f->lock); 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); BUG_ON(i >= f->num_members);
f->arr[i] = f->arr[f->num_members - 1]; f->arr[i] = f->arr[f->num_members - 1];
f->num_members--; f->num_members--;
if (f->num_members == 0)
__dev_remove_pack(&f->prot_hook);
spin_unlock(&f->lock); 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) 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_sock *po = pkt_sk(sk);
struct packet_fanout *f, *match; struct packet_fanout *f, *match;
u8 type = type_flags & 0xff; u8 type = type_flags & 0xff;
@@ -1641,23 +1646,28 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
return -EINVAL; return -EINVAL;
} }
if (!po->running) mutex_lock(&fanout_mutex);
return -EINVAL;
err = -EINVAL;
if (!po->running)
goto out;
err = -EALREADY;
if (po->fanout) if (po->fanout)
return -EALREADY; goto out;
if (type == PACKET_FANOUT_ROLLOVER || if (type == PACKET_FANOUT_ROLLOVER ||
(type_flags & PACKET_FANOUT_FLAG_ROLLOVER)) { (type_flags & PACKET_FANOUT_FLAG_ROLLOVER)) {
po->rollover = kzalloc(sizeof(*po->rollover), GFP_KERNEL); err = -ENOMEM;
if (!po->rollover) rollover = kzalloc(sizeof(*rollover), GFP_KERNEL);
return -ENOMEM; if (!rollover)
atomic_long_set(&po->rollover->num, 0); goto out;
atomic_long_set(&po->rollover->num_huge, 0); atomic_long_set(&rollover->num, 0);
atomic_long_set(&po->rollover->num_failed, 0); atomic_long_set(&rollover->num_huge, 0);
atomic_long_set(&rollover->num_failed, 0);
po->rollover = rollover;
} }
mutex_lock(&fanout_mutex);
match = NULL; match = NULL;
list_for_each_entry(f, &fanout_list, list) { list_for_each_entry(f, &fanout_list, list) {
if (f->id == id && 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.func = packet_rcv_fanout;
match->prot_hook.af_packet_priv = match; match->prot_hook.af_packet_priv = match;
match->prot_hook.id_match = match_fanout_group; match->prot_hook.id_match = match_fanout_group;
dev_add_pack(&match->prot_hook);
list_add(&match->list, &fanout_list); list_add(&match->list, &fanout_list);
} }
err = -EINVAL; err = -EINVAL;
@@ -1704,36 +1713,40 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
} }
} }
out: out:
mutex_unlock(&fanout_mutex); if (err && rollover) {
if (err) { kfree(rollover);
kfree(po->rollover);
po->rollover = NULL; po->rollover = NULL;
} }
mutex_unlock(&fanout_mutex);
return err; 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_sock *po = pkt_sk(sk);
struct packet_fanout *f; struct packet_fanout *f;
f = po->fanout;
if (!f)
return;
mutex_lock(&fanout_mutex); mutex_lock(&fanout_mutex);
f = po->fanout;
if (f) {
po->fanout = NULL; po->fanout = NULL;
if (atomic_dec_and_test(&f->sk_ref)) { if (atomic_dec_and_test(&f->sk_ref))
list_del(&f->list); list_del(&f->list);
dev_remove_pack(&f->prot_hook); else
fanout_release_data(f); f = NULL;
kfree(f);
}
mutex_unlock(&fanout_mutex);
if (po->rollover) if (po->rollover)
kfree_rcu(po->rollover, rcu); kfree_rcu(po->rollover, rcu);
}
mutex_unlock(&fanout_mutex);
return f;
} }
static bool packet_extra_vlan_len_allowed(const struct net_device *dev, 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 sock *sk = sock->sk;
struct packet_sock *po; struct packet_sock *po;
struct packet_fanout *f;
struct net *net; struct net *net;
union tpacket_req_u req_u; 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); packet_set_ring(sk, &req_u, 1, 1);
} }
fanout_release(sk); f = fanout_release(sk);
synchronize_net(); synchronize_net();
if (f) {
fanout_release_data(f);
kfree(f);
}
/* /*
* Now the socket is dead. No more input will appear. * 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) { if (msg == NETDEV_UNREGISTER) {
packet_cached_dev_reset(po); packet_cached_dev_reset(po);
fanout_release(sk);
po->ifindex = -1; po->ifindex = -1;
if (po->prot_hook.dev) if (po->prot_hook.dev)
dev_put(po->prot_hook.dev); dev_put(po->prot_hook.dev);

View File

@@ -2197,8 +2197,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
return err; return err;
err = sock_error(sock->sk); err = sock_error(sock->sk);
if (err) if (err) {
datagrams = err;
goto out_put; goto out_put;
}
entry = mmsg; entry = mmsg;
compat_entry = (struct compat_mmsghdr __user *)mmsg; compat_entry = (struct compat_mmsghdr __user *)mmsg;