Contents of /trunk/kernel-magellan/patches-4.10/0100-4.10.1-all-fixes.patch
Parent Directory | Revision Log
Revision 2855 -
(show annotations)
(download)
Thu Mar 9 13:08:16 2017 UTC (7 years, 6 months ago) by niro
File size: 21901 byte(s)
Thu Mar 9 13:08:16 2017 UTC (7 years, 6 months ago) by niro
File size: 21901 byte(s)
-linux-4.10.1
1 | diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt |
2 | index be7c0d9506b1..18eefa860f76 100644 |
3 | --- a/Documentation/admin-guide/kernel-parameters.txt |
4 | +++ b/Documentation/admin-guide/kernel-parameters.txt |
5 | @@ -1201,6 +1201,10 @@ |
6 | When zero, profiling data is discarded and associated |
7 | debugfs files are removed at module unload time. |
8 | |
9 | + goldfish [X86] Enable the goldfish android emulator platform. |
10 | + Don't use this when you are not running on the |
11 | + android emulator |
12 | + |
13 | gpt [EFI] Forces disk with valid GPT signature but |
14 | invalid Protective MBR to be treated as GPT. If the |
15 | primary GPT is corrupted, it enables the backup/alternate |
16 | diff --git a/Makefile b/Makefile |
17 | index f1e6a02a0c19..09eccff4f569 100644 |
18 | --- a/Makefile |
19 | +++ b/Makefile |
20 | @@ -1,6 +1,6 @@ |
21 | VERSION = 4 |
22 | PATCHLEVEL = 10 |
23 | -SUBLEVEL = 0 |
24 | +SUBLEVEL = 1 |
25 | EXTRAVERSION = |
26 | NAME = Fearless Coyote |
27 | |
28 | diff --git a/arch/x86/platform/goldfish/goldfish.c b/arch/x86/platform/goldfish/goldfish.c |
29 | index 1693107a518e..0d17c0aafeb1 100644 |
30 | --- a/arch/x86/platform/goldfish/goldfish.c |
31 | +++ b/arch/x86/platform/goldfish/goldfish.c |
32 | @@ -42,10 +42,22 @@ static struct resource goldfish_pdev_bus_resources[] = { |
33 | } |
34 | }; |
35 | |
36 | +static bool goldfish_enable __initdata; |
37 | + |
38 | +static int __init goldfish_setup(char *str) |
39 | +{ |
40 | + goldfish_enable = true; |
41 | + return 0; |
42 | +} |
43 | +__setup("goldfish", goldfish_setup); |
44 | + |
45 | static int __init goldfish_init(void) |
46 | { |
47 | + if (!goldfish_enable) |
48 | + return -ENODEV; |
49 | + |
50 | platform_device_register_simple("goldfish_pdev_bus", -1, |
51 | - goldfish_pdev_bus_resources, 2); |
52 | + goldfish_pdev_bus_resources, 2); |
53 | return 0; |
54 | } |
55 | device_initcall(goldfish_init); |
56 | diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c |
57 | index 49015b05f3d1..abdaf203835c 100644 |
58 | --- a/drivers/net/wireless/realtek/rtlwifi/usb.c |
59 | +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c |
60 | @@ -827,12 +827,30 @@ static void rtl_usb_stop(struct ieee80211_hw *hw) |
61 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
62 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
63 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
64 | + struct urb *urb; |
65 | |
66 | /* should after adapter start and interrupt enable. */ |
67 | set_hal_stop(rtlhal); |
68 | cancel_work_sync(&rtlpriv->works.fill_h2c_cmd); |
69 | /* Enable software */ |
70 | SET_USB_STOP(rtlusb); |
71 | + |
72 | + /* free pre-allocated URBs from rtl_usb_start() */ |
73 | + usb_kill_anchored_urbs(&rtlusb->rx_submitted); |
74 | + |
75 | + tasklet_kill(&rtlusb->rx_work_tasklet); |
76 | + cancel_work_sync(&rtlpriv->works.lps_change_work); |
77 | + |
78 | + flush_workqueue(rtlpriv->works.rtl_wq); |
79 | + |
80 | + skb_queue_purge(&rtlusb->rx_queue); |
81 | + |
82 | + while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) { |
83 | + usb_free_coherent(urb->dev, urb->transfer_buffer_length, |
84 | + urb->transfer_buffer, urb->transfer_dma); |
85 | + usb_free_urb(urb); |
86 | + } |
87 | + |
88 | rtlpriv->cfg->ops->hw_disable(hw); |
89 | } |
90 | |
91 | diff --git a/drivers/platform/goldfish/pdev_bus.c b/drivers/platform/goldfish/pdev_bus.c |
92 | index 1f52462f4cdd..dd9ea463c2a4 100644 |
93 | --- a/drivers/platform/goldfish/pdev_bus.c |
94 | +++ b/drivers/platform/goldfish/pdev_bus.c |
95 | @@ -157,23 +157,26 @@ static int goldfish_new_pdev(void) |
96 | static irqreturn_t goldfish_pdev_bus_interrupt(int irq, void *dev_id) |
97 | { |
98 | irqreturn_t ret = IRQ_NONE; |
99 | + |
100 | while (1) { |
101 | u32 op = readl(pdev_bus_base + PDEV_BUS_OP); |
102 | - switch (op) { |
103 | - case PDEV_BUS_OP_DONE: |
104 | - return IRQ_NONE; |
105 | |
106 | + switch (op) { |
107 | case PDEV_BUS_OP_REMOVE_DEV: |
108 | goldfish_pdev_remove(); |
109 | + ret = IRQ_HANDLED; |
110 | break; |
111 | |
112 | case PDEV_BUS_OP_ADD_DEV: |
113 | goldfish_new_pdev(); |
114 | + ret = IRQ_HANDLED; |
115 | break; |
116 | + |
117 | + case PDEV_BUS_OP_DONE: |
118 | + default: |
119 | + return ret; |
120 | } |
121 | - ret = IRQ_HANDLED; |
122 | } |
123 | - return ret; |
124 | } |
125 | |
126 | static int goldfish_pdev_bus_probe(struct platform_device *pdev) |
127 | diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c |
128 | index 7312e7e01b7e..6788e7532dff 100644 |
129 | --- a/drivers/tty/serial/msm_serial.c |
130 | +++ b/drivers/tty/serial/msm_serial.c |
131 | @@ -1809,6 +1809,7 @@ static const struct of_device_id msm_match_table[] = { |
132 | { .compatible = "qcom,msm-uartdm" }, |
133 | {} |
134 | }; |
135 | +MODULE_DEVICE_TABLE(of, msm_match_table); |
136 | |
137 | static struct platform_driver msm_platform_driver = { |
138 | .remove = msm_serial_remove, |
139 | diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c |
140 | index 1532cde8a437..7812052dc700 100644 |
141 | --- a/drivers/usb/serial/ark3116.c |
142 | +++ b/drivers/usb/serial/ark3116.c |
143 | @@ -99,10 +99,17 @@ static int ark3116_read_reg(struct usb_serial *serial, |
144 | usb_rcvctrlpipe(serial->dev, 0), |
145 | 0xfe, 0xc0, 0, reg, |
146 | buf, 1, ARK_TIMEOUT); |
147 | - if (result < 0) |
148 | + if (result < 1) { |
149 | + dev_err(&serial->interface->dev, |
150 | + "failed to read register %u: %d\n", |
151 | + reg, result); |
152 | + if (result >= 0) |
153 | + result = -EIO; |
154 | + |
155 | return result; |
156 | - else |
157 | - return buf[0]; |
158 | + } |
159 | + |
160 | + return buf[0]; |
161 | } |
162 | |
163 | static inline int calc_divisor(int bps) |
164 | diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c |
165 | index 8967715fe6fc..b6f1adefb758 100644 |
166 | --- a/drivers/usb/serial/console.c |
167 | +++ b/drivers/usb/serial/console.c |
168 | @@ -143,6 +143,7 @@ static int usb_console_setup(struct console *co, char *options) |
169 | tty->driver = usb_serial_tty_driver; |
170 | tty->index = co->index; |
171 | init_ldsem(&tty->ldisc_sem); |
172 | + spin_lock_init(&tty->files_lock); |
173 | INIT_LIST_HEAD(&tty->tty_files); |
174 | kref_get(&tty->driver->kref); |
175 | __module_get(tty->driver->owner); |
176 | diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c |
177 | index fff718352e0c..fbe69465eefa 100644 |
178 | --- a/drivers/usb/serial/cp210x.c |
179 | +++ b/drivers/usb/serial/cp210x.c |
180 | @@ -178,6 +178,8 @@ static const struct usb_device_id id_table[] = { |
181 | { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ |
182 | { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */ |
183 | { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ |
184 | + { USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART interface */ |
185 | + { USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */ |
186 | { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ |
187 | { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ |
188 | { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ |
189 | diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c |
190 | index 23d14b98ae2a..7d863fda1f18 100644 |
191 | --- a/drivers/usb/serial/ftdi_sio.c |
192 | +++ b/drivers/usb/serial/ftdi_sio.c |
193 | @@ -1802,8 +1802,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) |
194 | |
195 | mutex_init(&priv->cfg_lock); |
196 | |
197 | - priv->flags = ASYNC_LOW_LATENCY; |
198 | - |
199 | if (quirk && quirk->port_probe) |
200 | quirk->port_probe(priv); |
201 | |
202 | @@ -2067,6 +2065,20 @@ static int ftdi_process_packet(struct usb_serial_port *port, |
203 | priv->prev_status = status; |
204 | } |
205 | |
206 | + /* save if the transmitter is empty or not */ |
207 | + if (packet[1] & FTDI_RS_TEMT) |
208 | + priv->transmit_empty = 1; |
209 | + else |
210 | + priv->transmit_empty = 0; |
211 | + |
212 | + len -= 2; |
213 | + if (!len) |
214 | + return 0; /* status only */ |
215 | + |
216 | + /* |
217 | + * Break and error status must only be processed for packets with |
218 | + * data payload to avoid over-reporting. |
219 | + */ |
220 | flag = TTY_NORMAL; |
221 | if (packet[1] & FTDI_RS_ERR_MASK) { |
222 | /* Break takes precedence over parity, which takes precedence |
223 | @@ -2089,15 +2101,6 @@ static int ftdi_process_packet(struct usb_serial_port *port, |
224 | } |
225 | } |
226 | |
227 | - /* save if the transmitter is empty or not */ |
228 | - if (packet[1] & FTDI_RS_TEMT) |
229 | - priv->transmit_empty = 1; |
230 | - else |
231 | - priv->transmit_empty = 0; |
232 | - |
233 | - len -= 2; |
234 | - if (!len) |
235 | - return 0; /* status only */ |
236 | port->icount.rx += len; |
237 | ch = packet + 2; |
238 | |
239 | @@ -2428,8 +2431,12 @@ static int ftdi_get_modem_status(struct usb_serial_port *port, |
240 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, |
241 | 0, priv->interface, |
242 | buf, len, WDR_TIMEOUT); |
243 | - if (ret < 0) { |
244 | + |
245 | + /* NOTE: We allow short responses and handle that below. */ |
246 | + if (ret < 1) { |
247 | dev_err(&port->dev, "failed to get modem status: %d\n", ret); |
248 | + if (ret >= 0) |
249 | + ret = -EIO; |
250 | ret = usb_translate_errors(ret); |
251 | goto out; |
252 | } |
253 | diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c |
254 | index ea27fb23967a..e536ac8a080b 100644 |
255 | --- a/drivers/usb/serial/mos7840.c |
256 | +++ b/drivers/usb/serial/mos7840.c |
257 | @@ -1023,6 +1023,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) |
258 | * (can't set it up in mos7840_startup as the structures * |
259 | * were not set up at that time.) */ |
260 | if (port0->open_ports == 1) { |
261 | + /* FIXME: Buffer never NULL, so URB is not submitted. */ |
262 | if (serial->port[0]->interrupt_in_buffer == NULL) { |
263 | /* set up interrupt urb */ |
264 | usb_fill_int_urb(serial->port[0]->interrupt_in_urb, |
265 | @@ -2106,7 +2107,8 @@ static int mos7840_calc_num_ports(struct usb_serial *serial) |
266 | static int mos7840_attach(struct usb_serial *serial) |
267 | { |
268 | if (serial->num_bulk_in < serial->num_ports || |
269 | - serial->num_bulk_out < serial->num_ports) { |
270 | + serial->num_bulk_out < serial->num_ports || |
271 | + serial->num_interrupt_in < 1) { |
272 | dev_err(&serial->interface->dev, "missing endpoints\n"); |
273 | return -ENODEV; |
274 | } |
275 | diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c |
276 | index 5ded6f524d59..b3c64f557d60 100644 |
277 | --- a/drivers/usb/serial/opticon.c |
278 | +++ b/drivers/usb/serial/opticon.c |
279 | @@ -142,7 +142,7 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) |
280 | usb_clear_halt(port->serial->dev, port->read_urb->pipe); |
281 | |
282 | res = usb_serial_generic_open(tty, port); |
283 | - if (!res) |
284 | + if (res) |
285 | return res; |
286 | |
287 | /* Request CTS line state, sometimes during opening the current |
288 | diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c |
289 | index 475e6c31b266..ddfd787c461c 100644 |
290 | --- a/drivers/usb/serial/spcp8x5.c |
291 | +++ b/drivers/usb/serial/spcp8x5.c |
292 | @@ -232,11 +232,17 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status) |
293 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
294 | GET_UART_STATUS, GET_UART_STATUS_TYPE, |
295 | 0, GET_UART_STATUS_MSR, buf, 1, 100); |
296 | - if (ret < 0) |
297 | + if (ret < 1) { |
298 | dev_err(&port->dev, "failed to get modem status: %d\n", ret); |
299 | + if (ret >= 0) |
300 | + ret = -EIO; |
301 | + goto out; |
302 | + } |
303 | |
304 | dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x\n", ret, *buf); |
305 | *status = *buf; |
306 | + ret = 0; |
307 | +out: |
308 | kfree(buf); |
309 | |
310 | return ret; |
311 | diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c |
312 | index 1aa3abd67b36..fdecf79d2fa4 100644 |
313 | --- a/fs/xfs/xfs_iomap.c |
314 | +++ b/fs/xfs/xfs_iomap.c |
315 | @@ -1102,7 +1102,15 @@ xfs_file_iomap_end_delalloc( |
316 | xfs_fileoff_t end_fsb; |
317 | int error = 0; |
318 | |
319 | - start_fsb = XFS_B_TO_FSB(mp, offset + written); |
320 | + /* |
321 | + * start_fsb refers to the first unused block after a short write. If |
322 | + * nothing was written, round offset down to point at the first block in |
323 | + * the range. |
324 | + */ |
325 | + if (unlikely(!written)) |
326 | + start_fsb = XFS_B_TO_FSBT(mp, offset); |
327 | + else |
328 | + start_fsb = XFS_B_TO_FSB(mp, offset + written); |
329 | end_fsb = XFS_B_TO_FSB(mp, offset + length); |
330 | |
331 | /* |
332 | @@ -1114,6 +1122,9 @@ xfs_file_iomap_end_delalloc( |
333 | * blocks in the range, they are ours. |
334 | */ |
335 | if (start_fsb < end_fsb) { |
336 | + truncate_pagecache_range(VFS_I(ip), XFS_FSB_TO_B(mp, start_fsb), |
337 | + XFS_FSB_TO_B(mp, end_fsb) - 1); |
338 | + |
339 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
340 | error = xfs_bmap_punch_delalloc_range(ip, start_fsb, |
341 | end_fsb - start_fsb); |
342 | diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h |
343 | index 34cce729109c..fca15390a42c 100644 |
344 | --- a/include/acpi/platform/acenv.h |
345 | +++ b/include/acpi/platform/acenv.h |
346 | @@ -177,7 +177,7 @@ |
347 | #include "acmsvc.h" |
348 | |
349 | #elif defined(__INTEL_COMPILER) |
350 | -#include "acintel.h" |
351 | +#include <acpi/platform/acintel.h> |
352 | |
353 | #endif |
354 | |
355 | diff --git a/include/acpi/platform/acintel.h b/include/acpi/platform/acintel.h |
356 | new file mode 100644 |
357 | index 000000000000..17bd3b7b4e5a |
358 | --- /dev/null |
359 | +++ b/include/acpi/platform/acintel.h |
360 | @@ -0,0 +1,87 @@ |
361 | +/****************************************************************************** |
362 | + * |
363 | + * Name: acintel.h - VC specific defines, etc. |
364 | + * |
365 | + *****************************************************************************/ |
366 | + |
367 | +/* |
368 | + * Copyright (C) 2000 - 2017, Intel Corp. |
369 | + * All rights reserved. |
370 | + * |
371 | + * Redistribution and use in source and binary forms, with or without |
372 | + * modification, are permitted provided that the following conditions |
373 | + * are met: |
374 | + * 1. Redistributions of source code must retain the above copyright |
375 | + * notice, this list of conditions, and the following disclaimer, |
376 | + * without modification. |
377 | + * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
378 | + * substantially similar to the "NO WARRANTY" disclaimer below |
379 | + * ("Disclaimer") and any redistribution must be conditioned upon |
380 | + * including a substantially similar Disclaimer requirement for further |
381 | + * binary redistribution. |
382 | + * 3. Neither the names of the above-listed copyright holders nor the names |
383 | + * of any contributors may be used to endorse or promote products derived |
384 | + * from this software without specific prior written permission. |
385 | + * |
386 | + * Alternatively, this software may be distributed under the terms of the |
387 | + * GNU General Public License ("GPL") version 2 as published by the Free |
388 | + * Software Foundation. |
389 | + * |
390 | + * NO WARRANTY |
391 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
392 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
393 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
394 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
395 | + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
396 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
397 | + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
398 | + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
399 | + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
400 | + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
401 | + * POSSIBILITY OF SUCH DAMAGES. |
402 | + */ |
403 | + |
404 | +#ifndef __ACINTEL_H__ |
405 | +#define __ACINTEL_H__ |
406 | + |
407 | +/* |
408 | + * Use compiler specific <stdarg.h> is a good practice for even when |
409 | + * -nostdinc is specified (i.e., ACPI_USE_STANDARD_HEADERS undefined. |
410 | + */ |
411 | +#include <stdarg.h> |
412 | + |
413 | +/* Configuration specific to Intel 64-bit C compiler */ |
414 | + |
415 | +#define COMPILER_DEPENDENT_INT64 __int64 |
416 | +#define COMPILER_DEPENDENT_UINT64 unsigned __int64 |
417 | +#define ACPI_INLINE __inline |
418 | + |
419 | +/* |
420 | + * Calling conventions: |
421 | + * |
422 | + * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) |
423 | + * ACPI_EXTERNAL_XFACE - External ACPI interfaces |
424 | + * ACPI_INTERNAL_XFACE - Internal ACPI interfaces |
425 | + * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces |
426 | + */ |
427 | +#define ACPI_SYSTEM_XFACE |
428 | +#define ACPI_EXTERNAL_XFACE |
429 | +#define ACPI_INTERNAL_XFACE |
430 | +#define ACPI_INTERNAL_VAR_XFACE |
431 | + |
432 | +/* remark 981 - operands evaluated in no particular order */ |
433 | +#pragma warning(disable:981) |
434 | + |
435 | +/* warn C4100: unreferenced formal parameter */ |
436 | +#pragma warning(disable:4100) |
437 | + |
438 | +/* warn C4127: conditional expression is constant */ |
439 | +#pragma warning(disable:4127) |
440 | + |
441 | +/* warn C4706: assignment within conditional expression */ |
442 | +#pragma warning(disable:4706) |
443 | + |
444 | +/* warn C4214: bit field types other than int */ |
445 | +#pragma warning(disable:4214) |
446 | + |
447 | +#endif /* __ACINTEL_H__ */ |
448 | diff --git a/include/linux/ptr_ring.h b/include/linux/ptr_ring.h |
449 | index 2052011bf9fb..6c70444da3b9 100644 |
450 | --- a/include/linux/ptr_ring.h |
451 | +++ b/include/linux/ptr_ring.h |
452 | @@ -111,6 +111,11 @@ static inline int __ptr_ring_produce(struct ptr_ring *r, void *ptr) |
453 | return 0; |
454 | } |
455 | |
456 | +/* |
457 | + * Note: resize (below) nests producer lock within consumer lock, so if you |
458 | + * consume in interrupt or BH context, you must disable interrupts/BH when |
459 | + * calling this. |
460 | + */ |
461 | static inline int ptr_ring_produce(struct ptr_ring *r, void *ptr) |
462 | { |
463 | int ret; |
464 | @@ -242,6 +247,11 @@ static inline void *__ptr_ring_consume(struct ptr_ring *r) |
465 | return ptr; |
466 | } |
467 | |
468 | +/* |
469 | + * Note: resize (below) nests producer lock within consumer lock, so if you |
470 | + * call this in interrupt or BH context, you must disable interrupts/BH when |
471 | + * producing. |
472 | + */ |
473 | static inline void *ptr_ring_consume(struct ptr_ring *r) |
474 | { |
475 | void *ptr; |
476 | @@ -357,7 +367,7 @@ static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue, |
477 | void **old; |
478 | void *ptr; |
479 | |
480 | - while ((ptr = ptr_ring_consume(r))) |
481 | + while ((ptr = __ptr_ring_consume(r))) |
482 | if (producer < size) |
483 | queue[producer++] = ptr; |
484 | else if (destroy) |
485 | @@ -372,6 +382,12 @@ static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue, |
486 | return old; |
487 | } |
488 | |
489 | +/* |
490 | + * Note: producer lock is nested within consumer lock, so if you |
491 | + * resize you must make sure all uses nest correctly. |
492 | + * In particular if you consume ring in interrupt or BH context, you must |
493 | + * disable interrupts/BH when doing so. |
494 | + */ |
495 | static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, |
496 | void (*destroy)(void *)) |
497 | { |
498 | @@ -382,17 +398,25 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, |
499 | if (!queue) |
500 | return -ENOMEM; |
501 | |
502 | - spin_lock_irqsave(&(r)->producer_lock, flags); |
503 | + spin_lock_irqsave(&(r)->consumer_lock, flags); |
504 | + spin_lock(&(r)->producer_lock); |
505 | |
506 | old = __ptr_ring_swap_queue(r, queue, size, gfp, destroy); |
507 | |
508 | - spin_unlock_irqrestore(&(r)->producer_lock, flags); |
509 | + spin_unlock(&(r)->producer_lock); |
510 | + spin_unlock_irqrestore(&(r)->consumer_lock, flags); |
511 | |
512 | kfree(old); |
513 | |
514 | return 0; |
515 | } |
516 | |
517 | +/* |
518 | + * Note: producer lock is nested within consumer lock, so if you |
519 | + * resize you must make sure all uses nest correctly. |
520 | + * In particular if you consume ring in interrupt or BH context, you must |
521 | + * disable interrupts/BH when doing so. |
522 | + */ |
523 | static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings, |
524 | int size, |
525 | gfp_t gfp, void (*destroy)(void *)) |
526 | @@ -412,10 +436,12 @@ static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings, |
527 | } |
528 | |
529 | for (i = 0; i < nrings; ++i) { |
530 | - spin_lock_irqsave(&(rings[i])->producer_lock, flags); |
531 | + spin_lock_irqsave(&(rings[i])->consumer_lock, flags); |
532 | + spin_lock(&(rings[i])->producer_lock); |
533 | queues[i] = __ptr_ring_swap_queue(rings[i], queues[i], |
534 | size, gfp, destroy); |
535 | - spin_unlock_irqrestore(&(rings[i])->producer_lock, flags); |
536 | + spin_unlock(&(rings[i])->producer_lock); |
537 | + spin_unlock_irqrestore(&(rings[i])->consumer_lock, flags); |
538 | } |
539 | |
540 | for (i = 0; i < nrings; ++i) |
541 | diff --git a/mm/backing-dev.c b/mm/backing-dev.c |
542 | index 3bfed5ab2475..61b34071e3ee 100644 |
543 | --- a/mm/backing-dev.c |
544 | +++ b/mm/backing-dev.c |
545 | @@ -758,15 +758,20 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi) |
546 | if (!bdi->wb_congested) |
547 | return -ENOMEM; |
548 | |
549 | + atomic_set(&bdi->wb_congested->refcnt, 1); |
550 | + |
551 | err = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL); |
552 | if (err) { |
553 | - kfree(bdi->wb_congested); |
554 | + wb_congested_put(bdi->wb_congested); |
555 | return err; |
556 | } |
557 | return 0; |
558 | } |
559 | |
560 | -static void cgwb_bdi_destroy(struct backing_dev_info *bdi) { } |
561 | +static void cgwb_bdi_destroy(struct backing_dev_info *bdi) |
562 | +{ |
563 | + wb_congested_put(bdi->wb_congested); |
564 | +} |
565 | |
566 | #endif /* CONFIG_CGROUP_WRITEBACK */ |
567 | |
568 | diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c |
569 | index 900011709e3b..fc4bf4d54158 100644 |
570 | --- a/net/ipv4/ip_sockglue.c |
571 | +++ b/net/ipv4/ip_sockglue.c |
572 | @@ -116,10 +116,10 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb, |
573 | if (skb->ip_summed != CHECKSUM_COMPLETE) |
574 | return; |
575 | |
576 | - if (offset != 0) |
577 | - csum = csum_sub(csum, |
578 | - csum_partial(skb_transport_header(skb) + tlen, |
579 | - offset, 0)); |
580 | + if (offset != 0) { |
581 | + int tend_off = skb_transport_offset(skb) + tlen; |
582 | + csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0)); |
583 | + } |
584 | |
585 | put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum); |
586 | } |
587 | diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c |
588 | index 7341adf7059d..6dc44d9b4190 100644 |
589 | --- a/net/netfilter/nf_conntrack_helper.c |
590 | +++ b/net/netfilter/nf_conntrack_helper.c |
591 | @@ -188,6 +188,26 @@ nf_ct_helper_ext_add(struct nf_conn *ct, |
592 | } |
593 | EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); |
594 | |
595 | +static struct nf_conntrack_helper * |
596 | +nf_ct_lookup_helper(struct nf_conn *ct, struct net *net) |
597 | +{ |
598 | + if (!net->ct.sysctl_auto_assign_helper) { |
599 | + if (net->ct.auto_assign_helper_warned) |
600 | + return NULL; |
601 | + if (!__nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple)) |
602 | + return NULL; |
603 | + pr_info("nf_conntrack: default automatic helper assignment " |
604 | + "has been turned off for security reasons and CT-based " |
605 | + " firewall rule not found. Use the iptables CT target " |
606 | + "to attach helpers instead.\n"); |
607 | + net->ct.auto_assign_helper_warned = 1; |
608 | + return NULL; |
609 | + } |
610 | + |
611 | + return __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); |
612 | +} |
613 | + |
614 | + |
615 | int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, |
616 | gfp_t flags) |
617 | { |
618 | @@ -213,21 +233,14 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, |
619 | } |
620 | |
621 | help = nfct_help(ct); |
622 | - if (net->ct.sysctl_auto_assign_helper && helper == NULL) { |
623 | - helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); |
624 | - if (unlikely(!net->ct.auto_assign_helper_warned && helper)) { |
625 | - pr_info("nf_conntrack: automatic helper " |
626 | - "assignment is deprecated and it will " |
627 | - "be removed soon. Use the iptables CT target " |
628 | - "to attach helpers instead.\n"); |
629 | - net->ct.auto_assign_helper_warned = true; |
630 | - } |
631 | - } |
632 | |
633 | if (helper == NULL) { |
634 | - if (help) |
635 | - RCU_INIT_POINTER(help->helper, NULL); |
636 | - return 0; |
637 | + helper = nf_ct_lookup_helper(ct, net); |
638 | + if (helper == NULL) { |
639 | + if (help) |
640 | + RCU_INIT_POINTER(help->helper, NULL); |
641 | + return 0; |
642 | + } |
643 | } |
644 | |
645 | if (help == NULL) { |
646 | diff --git a/net/socket.c b/net/socket.c |
647 | index 0758e13754e2..02bd9249e295 100644 |
648 | --- a/net/socket.c |
649 | +++ b/net/socket.c |
650 | @@ -2228,8 +2228,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, |
651 | return err; |
652 | |
653 | err = sock_error(sock->sk); |
654 | - if (err) |
655 | + if (err) { |
656 | + datagrams = err; |
657 | goto out_put; |
658 | + } |
659 | |
660 | entry = mmsg; |
661 | compat_entry = (struct compat_mmsghdr __user *)mmsg; |