Contents of /trunk/kernel-alx/patches-4.9/0112-4.9.13-all-fixes.patch
Parent Directory | Revision Log
Revision 2956 -
(show annotations)
(download)
Mon Jul 24 12:03:46 2017 UTC (7 years, 2 months ago) by niro
File size: 34344 byte(s)
Mon Jul 24 12:03:46 2017 UTC (7 years, 2 months ago) by niro
File size: 34344 byte(s)
-added patches-4.9
1 | diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt |
2 | index 922dec8fa07e..65b05ba6ef98 100644 |
3 | --- a/Documentation/kernel-parameters.txt |
4 | +++ b/Documentation/kernel-parameters.txt |
5 | @@ -1391,6 +1391,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. |
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 3cd6f6fb4f20..14dc2758345b 100644 |
18 | --- a/Makefile |
19 | +++ b/Makefile |
20 | @@ -1,6 +1,6 @@ |
21 | VERSION = 4 |
22 | PATCHLEVEL = 9 |
23 | -SUBLEVEL = 12 |
24 | +SUBLEVEL = 13 |
25 | EXTRAVERSION = |
26 | NAME = Roaring Lionus |
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/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c |
57 | index 6bb21b31cfeb..a543ea676de3 100644 |
58 | --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c |
59 | +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c |
60 | @@ -567,10 +567,14 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv, |
61 | |
62 | mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse); |
63 | |
64 | + preempt_disable(); |
65 | + |
66 | tcf_exts_to_list(f->exts, &actions); |
67 | list_for_each_entry(a, &actions, list) |
68 | tcf_action_stats_update(a, bytes, packets, lastuse); |
69 | |
70 | + preempt_enable(); |
71 | + |
72 | return 0; |
73 | } |
74 | |
75 | diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c |
76 | index b9087b828eff..3f1971d485f3 100644 |
77 | --- a/drivers/net/ethernet/ti/cpsw.c |
78 | +++ b/drivers/net/ethernet/ti/cpsw.c |
79 | @@ -2925,7 +2925,7 @@ static int cpsw_resume(struct device *dev) |
80 | { |
81 | struct platform_device *pdev = to_platform_device(dev); |
82 | struct net_device *ndev = platform_get_drvdata(pdev); |
83 | - struct cpsw_common *cpsw = netdev_priv(ndev); |
84 | + struct cpsw_common *cpsw = ndev_to_cpsw(ndev); |
85 | |
86 | /* Select default pin state */ |
87 | pinctrl_pm_select_default_state(dev); |
88 | diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c |
89 | index 0fafaa9d903b..d4f495b41bd4 100644 |
90 | --- a/drivers/net/vxlan.c |
91 | +++ b/drivers/net/vxlan.c |
92 | @@ -2449,7 +2449,8 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) |
93 | return -EINVAL; |
94 | rt = vxlan_get_route(vxlan, skb, 0, info->key.tos, |
95 | info->key.u.ipv4.dst, |
96 | - &info->key.u.ipv4.src, NULL, info); |
97 | + &info->key.u.ipv4.src, |
98 | + &info->dst_cache, info); |
99 | if (IS_ERR(rt)) |
100 | return PTR_ERR(rt); |
101 | ip_rt_put(rt); |
102 | @@ -2459,7 +2460,8 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) |
103 | |
104 | ndst = vxlan6_get_route(vxlan, skb, 0, info->key.tos, |
105 | info->key.label, &info->key.u.ipv6.dst, |
106 | - &info->key.u.ipv6.src, NULL, info); |
107 | + &info->key.u.ipv6.src, |
108 | + &info->dst_cache, info); |
109 | if (IS_ERR(ndst)) |
110 | return PTR_ERR(ndst); |
111 | dst_release(ndst); |
112 | diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c |
113 | index 3837bbdecf05..ae0c48f3c2bc 100644 |
114 | --- a/drivers/net/wireless/realtek/rtlwifi/usb.c |
115 | +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c |
116 | @@ -831,12 +831,30 @@ static void rtl_usb_stop(struct ieee80211_hw *hw) |
117 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
118 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
119 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
120 | + struct urb *urb; |
121 | |
122 | /* should after adapter start and interrupt enable. */ |
123 | set_hal_stop(rtlhal); |
124 | cancel_work_sync(&rtlpriv->works.fill_h2c_cmd); |
125 | /* Enable software */ |
126 | SET_USB_STOP(rtlusb); |
127 | + |
128 | + /* free pre-allocated URBs from rtl_usb_start() */ |
129 | + usb_kill_anchored_urbs(&rtlusb->rx_submitted); |
130 | + |
131 | + tasklet_kill(&rtlusb->rx_work_tasklet); |
132 | + cancel_work_sync(&rtlpriv->works.lps_change_work); |
133 | + |
134 | + flush_workqueue(rtlpriv->works.rtl_wq); |
135 | + |
136 | + skb_queue_purge(&rtlusb->rx_queue); |
137 | + |
138 | + while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) { |
139 | + usb_free_coherent(urb->dev, urb->transfer_buffer_length, |
140 | + urb->transfer_buffer, urb->transfer_dma); |
141 | + usb_free_urb(urb); |
142 | + } |
143 | + |
144 | rtlpriv->cfg->ops->hw_disable(hw); |
145 | } |
146 | |
147 | diff --git a/drivers/platform/goldfish/pdev_bus.c b/drivers/platform/goldfish/pdev_bus.c |
148 | index 1f52462f4cdd..dd9ea463c2a4 100644 |
149 | --- a/drivers/platform/goldfish/pdev_bus.c |
150 | +++ b/drivers/platform/goldfish/pdev_bus.c |
151 | @@ -157,23 +157,26 @@ static int goldfish_new_pdev(void) |
152 | static irqreturn_t goldfish_pdev_bus_interrupt(int irq, void *dev_id) |
153 | { |
154 | irqreturn_t ret = IRQ_NONE; |
155 | + |
156 | while (1) { |
157 | u32 op = readl(pdev_bus_base + PDEV_BUS_OP); |
158 | - switch (op) { |
159 | - case PDEV_BUS_OP_DONE: |
160 | - return IRQ_NONE; |
161 | |
162 | + switch (op) { |
163 | case PDEV_BUS_OP_REMOVE_DEV: |
164 | goldfish_pdev_remove(); |
165 | + ret = IRQ_HANDLED; |
166 | break; |
167 | |
168 | case PDEV_BUS_OP_ADD_DEV: |
169 | goldfish_new_pdev(); |
170 | + ret = IRQ_HANDLED; |
171 | break; |
172 | + |
173 | + case PDEV_BUS_OP_DONE: |
174 | + default: |
175 | + return ret; |
176 | } |
177 | - ret = IRQ_HANDLED; |
178 | } |
179 | - return ret; |
180 | } |
181 | |
182 | static int goldfish_pdev_bus_probe(struct platform_device *pdev) |
183 | diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c |
184 | index 7312e7e01b7e..6788e7532dff 100644 |
185 | --- a/drivers/tty/serial/msm_serial.c |
186 | +++ b/drivers/tty/serial/msm_serial.c |
187 | @@ -1809,6 +1809,7 @@ static const struct of_device_id msm_match_table[] = { |
188 | { .compatible = "qcom,msm-uartdm" }, |
189 | {} |
190 | }; |
191 | +MODULE_DEVICE_TABLE(of, msm_match_table); |
192 | |
193 | static struct platform_driver msm_platform_driver = { |
194 | .remove = msm_serial_remove, |
195 | diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c |
196 | index 1532cde8a437..7812052dc700 100644 |
197 | --- a/drivers/usb/serial/ark3116.c |
198 | +++ b/drivers/usb/serial/ark3116.c |
199 | @@ -99,10 +99,17 @@ static int ark3116_read_reg(struct usb_serial *serial, |
200 | usb_rcvctrlpipe(serial->dev, 0), |
201 | 0xfe, 0xc0, 0, reg, |
202 | buf, 1, ARK_TIMEOUT); |
203 | - if (result < 0) |
204 | + if (result < 1) { |
205 | + dev_err(&serial->interface->dev, |
206 | + "failed to read register %u: %d\n", |
207 | + reg, result); |
208 | + if (result >= 0) |
209 | + result = -EIO; |
210 | + |
211 | return result; |
212 | - else |
213 | - return buf[0]; |
214 | + } |
215 | + |
216 | + return buf[0]; |
217 | } |
218 | |
219 | static inline int calc_divisor(int bps) |
220 | diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c |
221 | index 8967715fe6fc..b6f1adefb758 100644 |
222 | --- a/drivers/usb/serial/console.c |
223 | +++ b/drivers/usb/serial/console.c |
224 | @@ -143,6 +143,7 @@ static int usb_console_setup(struct console *co, char *options) |
225 | tty->driver = usb_serial_tty_driver; |
226 | tty->index = co->index; |
227 | init_ldsem(&tty->ldisc_sem); |
228 | + spin_lock_init(&tty->files_lock); |
229 | INIT_LIST_HEAD(&tty->tty_files); |
230 | kref_get(&tty->driver->kref); |
231 | __module_get(tty->driver->owner); |
232 | diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c |
233 | index 243ac5ebe46a..8bb48751028c 100644 |
234 | --- a/drivers/usb/serial/cp210x.c |
235 | +++ b/drivers/usb/serial/cp210x.c |
236 | @@ -172,6 +172,8 @@ static const struct usb_device_id id_table[] = { |
237 | { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ |
238 | { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */ |
239 | { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ |
240 | + { USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART interface */ |
241 | + { USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */ |
242 | { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ |
243 | { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ |
244 | { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ |
245 | diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c |
246 | index 6e9fc8bcc285..99a0a5f1b400 100644 |
247 | --- a/drivers/usb/serial/ftdi_sio.c |
248 | +++ b/drivers/usb/serial/ftdi_sio.c |
249 | @@ -1807,8 +1807,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) |
250 | |
251 | mutex_init(&priv->cfg_lock); |
252 | |
253 | - priv->flags = ASYNC_LOW_LATENCY; |
254 | - |
255 | if (quirk && quirk->port_probe) |
256 | quirk->port_probe(priv); |
257 | |
258 | @@ -2072,6 +2070,20 @@ static int ftdi_process_packet(struct usb_serial_port *port, |
259 | priv->prev_status = status; |
260 | } |
261 | |
262 | + /* save if the transmitter is empty or not */ |
263 | + if (packet[1] & FTDI_RS_TEMT) |
264 | + priv->transmit_empty = 1; |
265 | + else |
266 | + priv->transmit_empty = 0; |
267 | + |
268 | + len -= 2; |
269 | + if (!len) |
270 | + return 0; /* status only */ |
271 | + |
272 | + /* |
273 | + * Break and error status must only be processed for packets with |
274 | + * data payload to avoid over-reporting. |
275 | + */ |
276 | flag = TTY_NORMAL; |
277 | if (packet[1] & FTDI_RS_ERR_MASK) { |
278 | /* Break takes precedence over parity, which takes precedence |
279 | @@ -2094,15 +2106,6 @@ static int ftdi_process_packet(struct usb_serial_port *port, |
280 | } |
281 | } |
282 | |
283 | - /* save if the transmitter is empty or not */ |
284 | - if (packet[1] & FTDI_RS_TEMT) |
285 | - priv->transmit_empty = 1; |
286 | - else |
287 | - priv->transmit_empty = 0; |
288 | - |
289 | - len -= 2; |
290 | - if (!len) |
291 | - return 0; /* status only */ |
292 | port->icount.rx += len; |
293 | ch = packet + 2; |
294 | |
295 | @@ -2433,8 +2436,12 @@ static int ftdi_get_modem_status(struct usb_serial_port *port, |
296 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, |
297 | 0, priv->interface, |
298 | buf, len, WDR_TIMEOUT); |
299 | - if (ret < 0) { |
300 | + |
301 | + /* NOTE: We allow short responses and handle that below. */ |
302 | + if (ret < 1) { |
303 | dev_err(&port->dev, "failed to get modem status: %d\n", ret); |
304 | + if (ret >= 0) |
305 | + ret = -EIO; |
306 | ret = usb_translate_errors(ret); |
307 | goto out; |
308 | } |
309 | diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c |
310 | index 4f9af47e6a29..5c4fc3abf6a7 100644 |
311 | --- a/drivers/usb/serial/mos7840.c |
312 | +++ b/drivers/usb/serial/mos7840.c |
313 | @@ -1024,6 +1024,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) |
314 | * (can't set it up in mos7840_startup as the structures * |
315 | * were not set up at that time.) */ |
316 | if (port0->open_ports == 1) { |
317 | + /* FIXME: Buffer never NULL, so URB is not submitted. */ |
318 | if (serial->port[0]->interrupt_in_buffer == NULL) { |
319 | /* set up interrupt urb */ |
320 | usb_fill_int_urb(serial->port[0]->interrupt_in_urb, |
321 | @@ -2119,7 +2120,8 @@ static int mos7840_calc_num_ports(struct usb_serial *serial) |
322 | static int mos7840_attach(struct usb_serial *serial) |
323 | { |
324 | if (serial->num_bulk_in < serial->num_ports || |
325 | - serial->num_bulk_out < serial->num_ports) { |
326 | + serial->num_bulk_out < serial->num_ports || |
327 | + serial->num_interrupt_in < 1) { |
328 | dev_err(&serial->interface->dev, "missing endpoints\n"); |
329 | return -ENODEV; |
330 | } |
331 | diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c |
332 | index 4b7bfb394a32..64bf258e7e00 100644 |
333 | --- a/drivers/usb/serial/opticon.c |
334 | +++ b/drivers/usb/serial/opticon.c |
335 | @@ -142,7 +142,7 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) |
336 | usb_clear_halt(port->serial->dev, port->read_urb->pipe); |
337 | |
338 | res = usb_serial_generic_open(tty, port); |
339 | - if (!res) |
340 | + if (res) |
341 | return res; |
342 | |
343 | /* Request CTS line state, sometimes during opening the current |
344 | diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c |
345 | index 475e6c31b266..ddfd787c461c 100644 |
346 | --- a/drivers/usb/serial/spcp8x5.c |
347 | +++ b/drivers/usb/serial/spcp8x5.c |
348 | @@ -232,11 +232,17 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status) |
349 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
350 | GET_UART_STATUS, GET_UART_STATUS_TYPE, |
351 | 0, GET_UART_STATUS_MSR, buf, 1, 100); |
352 | - if (ret < 0) |
353 | + if (ret < 1) { |
354 | dev_err(&port->dev, "failed to get modem status: %d\n", ret); |
355 | + if (ret >= 0) |
356 | + ret = -EIO; |
357 | + goto out; |
358 | + } |
359 | |
360 | dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x\n", ret, *buf); |
361 | *status = *buf; |
362 | + ret = 0; |
363 | +out: |
364 | kfree(buf); |
365 | |
366 | return ret; |
367 | diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c |
368 | index cdc6bdd495be..e8889614cec3 100644 |
369 | --- a/fs/xfs/xfs_iomap.c |
370 | +++ b/fs/xfs/xfs_iomap.c |
371 | @@ -1068,7 +1068,15 @@ xfs_file_iomap_end_delalloc( |
372 | xfs_fileoff_t end_fsb; |
373 | int error = 0; |
374 | |
375 | - start_fsb = XFS_B_TO_FSB(mp, offset + written); |
376 | + /* |
377 | + * start_fsb refers to the first unused block after a short write. If |
378 | + * nothing was written, round offset down to point at the first block in |
379 | + * the range. |
380 | + */ |
381 | + if (unlikely(!written)) |
382 | + start_fsb = XFS_B_TO_FSBT(mp, offset); |
383 | + else |
384 | + start_fsb = XFS_B_TO_FSB(mp, offset + written); |
385 | end_fsb = XFS_B_TO_FSB(mp, offset + length); |
386 | |
387 | /* |
388 | @@ -1080,6 +1088,9 @@ xfs_file_iomap_end_delalloc( |
389 | * blocks in the range, they are ours. |
390 | */ |
391 | if (start_fsb < end_fsb) { |
392 | + truncate_pagecache_range(VFS_I(ip), XFS_FSB_TO_B(mp, start_fsb), |
393 | + XFS_FSB_TO_B(mp, end_fsb) - 1); |
394 | + |
395 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
396 | error = xfs_bmap_punch_delalloc_range(ip, start_fsb, |
397 | end_fsb - start_fsb); |
398 | diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h |
399 | index 34cce729109c..fca15390a42c 100644 |
400 | --- a/include/acpi/platform/acenv.h |
401 | +++ b/include/acpi/platform/acenv.h |
402 | @@ -177,7 +177,7 @@ |
403 | #include "acmsvc.h" |
404 | |
405 | #elif defined(__INTEL_COMPILER) |
406 | -#include "acintel.h" |
407 | +#include <acpi/platform/acintel.h> |
408 | |
409 | #endif |
410 | |
411 | diff --git a/include/acpi/platform/acintel.h b/include/acpi/platform/acintel.h |
412 | new file mode 100644 |
413 | index 000000000000..17bd3b7b4e5a |
414 | --- /dev/null |
415 | +++ b/include/acpi/platform/acintel.h |
416 | @@ -0,0 +1,87 @@ |
417 | +/****************************************************************************** |
418 | + * |
419 | + * Name: acintel.h - VC specific defines, etc. |
420 | + * |
421 | + *****************************************************************************/ |
422 | + |
423 | +/* |
424 | + * Copyright (C) 2000 - 2017, Intel Corp. |
425 | + * All rights reserved. |
426 | + * |
427 | + * Redistribution and use in source and binary forms, with or without |
428 | + * modification, are permitted provided that the following conditions |
429 | + * are met: |
430 | + * 1. Redistributions of source code must retain the above copyright |
431 | + * notice, this list of conditions, and the following disclaimer, |
432 | + * without modification. |
433 | + * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
434 | + * substantially similar to the "NO WARRANTY" disclaimer below |
435 | + * ("Disclaimer") and any redistribution must be conditioned upon |
436 | + * including a substantially similar Disclaimer requirement for further |
437 | + * binary redistribution. |
438 | + * 3. Neither the names of the above-listed copyright holders nor the names |
439 | + * of any contributors may be used to endorse or promote products derived |
440 | + * from this software without specific prior written permission. |
441 | + * |
442 | + * Alternatively, this software may be distributed under the terms of the |
443 | + * GNU General Public License ("GPL") version 2 as published by the Free |
444 | + * Software Foundation. |
445 | + * |
446 | + * NO WARRANTY |
447 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
448 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
449 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
450 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
451 | + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
452 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
453 | + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
454 | + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
455 | + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
456 | + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
457 | + * POSSIBILITY OF SUCH DAMAGES. |
458 | + */ |
459 | + |
460 | +#ifndef __ACINTEL_H__ |
461 | +#define __ACINTEL_H__ |
462 | + |
463 | +/* |
464 | + * Use compiler specific <stdarg.h> is a good practice for even when |
465 | + * -nostdinc is specified (i.e., ACPI_USE_STANDARD_HEADERS undefined. |
466 | + */ |
467 | +#include <stdarg.h> |
468 | + |
469 | +/* Configuration specific to Intel 64-bit C compiler */ |
470 | + |
471 | +#define COMPILER_DEPENDENT_INT64 __int64 |
472 | +#define COMPILER_DEPENDENT_UINT64 unsigned __int64 |
473 | +#define ACPI_INLINE __inline |
474 | + |
475 | +/* |
476 | + * Calling conventions: |
477 | + * |
478 | + * ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads) |
479 | + * ACPI_EXTERNAL_XFACE - External ACPI interfaces |
480 | + * ACPI_INTERNAL_XFACE - Internal ACPI interfaces |
481 | + * ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces |
482 | + */ |
483 | +#define ACPI_SYSTEM_XFACE |
484 | +#define ACPI_EXTERNAL_XFACE |
485 | +#define ACPI_INTERNAL_XFACE |
486 | +#define ACPI_INTERNAL_VAR_XFACE |
487 | + |
488 | +/* remark 981 - operands evaluated in no particular order */ |
489 | +#pragma warning(disable:981) |
490 | + |
491 | +/* warn C4100: unreferenced formal parameter */ |
492 | +#pragma warning(disable:4100) |
493 | + |
494 | +/* warn C4127: conditional expression is constant */ |
495 | +#pragma warning(disable:4127) |
496 | + |
497 | +/* warn C4706: assignment within conditional expression */ |
498 | +#pragma warning(disable:4706) |
499 | + |
500 | +/* warn C4214: bit field types other than int */ |
501 | +#pragma warning(disable:4214) |
502 | + |
503 | +#endif /* __ACINTEL_H__ */ |
504 | diff --git a/include/linux/ptr_ring.h b/include/linux/ptr_ring.h |
505 | index 2052011bf9fb..6c70444da3b9 100644 |
506 | --- a/include/linux/ptr_ring.h |
507 | +++ b/include/linux/ptr_ring.h |
508 | @@ -111,6 +111,11 @@ static inline int __ptr_ring_produce(struct ptr_ring *r, void *ptr) |
509 | return 0; |
510 | } |
511 | |
512 | +/* |
513 | + * Note: resize (below) nests producer lock within consumer lock, so if you |
514 | + * consume in interrupt or BH context, you must disable interrupts/BH when |
515 | + * calling this. |
516 | + */ |
517 | static inline int ptr_ring_produce(struct ptr_ring *r, void *ptr) |
518 | { |
519 | int ret; |
520 | @@ -242,6 +247,11 @@ static inline void *__ptr_ring_consume(struct ptr_ring *r) |
521 | return ptr; |
522 | } |
523 | |
524 | +/* |
525 | + * Note: resize (below) nests producer lock within consumer lock, so if you |
526 | + * call this in interrupt or BH context, you must disable interrupts/BH when |
527 | + * producing. |
528 | + */ |
529 | static inline void *ptr_ring_consume(struct ptr_ring *r) |
530 | { |
531 | void *ptr; |
532 | @@ -357,7 +367,7 @@ static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue, |
533 | void **old; |
534 | void *ptr; |
535 | |
536 | - while ((ptr = ptr_ring_consume(r))) |
537 | + while ((ptr = __ptr_ring_consume(r))) |
538 | if (producer < size) |
539 | queue[producer++] = ptr; |
540 | else if (destroy) |
541 | @@ -372,6 +382,12 @@ static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue, |
542 | return old; |
543 | } |
544 | |
545 | +/* |
546 | + * Note: producer lock is nested within consumer lock, so if you |
547 | + * resize you must make sure all uses nest correctly. |
548 | + * In particular if you consume ring in interrupt or BH context, you must |
549 | + * disable interrupts/BH when doing so. |
550 | + */ |
551 | static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, |
552 | void (*destroy)(void *)) |
553 | { |
554 | @@ -382,17 +398,25 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, |
555 | if (!queue) |
556 | return -ENOMEM; |
557 | |
558 | - spin_lock_irqsave(&(r)->producer_lock, flags); |
559 | + spin_lock_irqsave(&(r)->consumer_lock, flags); |
560 | + spin_lock(&(r)->producer_lock); |
561 | |
562 | old = __ptr_ring_swap_queue(r, queue, size, gfp, destroy); |
563 | |
564 | - spin_unlock_irqrestore(&(r)->producer_lock, flags); |
565 | + spin_unlock(&(r)->producer_lock); |
566 | + spin_unlock_irqrestore(&(r)->consumer_lock, flags); |
567 | |
568 | kfree(old); |
569 | |
570 | return 0; |
571 | } |
572 | |
573 | +/* |
574 | + * Note: producer lock is nested within consumer lock, so if you |
575 | + * resize you must make sure all uses nest correctly. |
576 | + * In particular if you consume ring in interrupt or BH context, you must |
577 | + * disable interrupts/BH when doing so. |
578 | + */ |
579 | static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings, |
580 | int size, |
581 | gfp_t gfp, void (*destroy)(void *)) |
582 | @@ -412,10 +436,12 @@ static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings, |
583 | } |
584 | |
585 | for (i = 0; i < nrings; ++i) { |
586 | - spin_lock_irqsave(&(rings[i])->producer_lock, flags); |
587 | + spin_lock_irqsave(&(rings[i])->consumer_lock, flags); |
588 | + spin_lock(&(rings[i])->producer_lock); |
589 | queues[i] = __ptr_ring_swap_queue(rings[i], queues[i], |
590 | size, gfp, destroy); |
591 | - spin_unlock_irqrestore(&(rings[i])->producer_lock, flags); |
592 | + spin_unlock(&(rings[i])->producer_lock); |
593 | + spin_unlock_irqrestore(&(rings[i])->consumer_lock, flags); |
594 | } |
595 | |
596 | for (i = 0; i < nrings; ++i) |
597 | diff --git a/mm/backing-dev.c b/mm/backing-dev.c |
598 | index 8fde443f36d7..6ff2d7744223 100644 |
599 | --- a/mm/backing-dev.c |
600 | +++ b/mm/backing-dev.c |
601 | @@ -757,15 +757,20 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi) |
602 | if (!bdi->wb_congested) |
603 | return -ENOMEM; |
604 | |
605 | + atomic_set(&bdi->wb_congested->refcnt, 1); |
606 | + |
607 | err = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL); |
608 | if (err) { |
609 | - kfree(bdi->wb_congested); |
610 | + wb_congested_put(bdi->wb_congested); |
611 | return err; |
612 | } |
613 | return 0; |
614 | } |
615 | |
616 | -static void cgwb_bdi_destroy(struct backing_dev_info *bdi) { } |
617 | +static void cgwb_bdi_destroy(struct backing_dev_info *bdi) |
618 | +{ |
619 | + wb_congested_put(bdi->wb_congested); |
620 | +} |
621 | |
622 | #endif /* CONFIG_CGROUP_WRITEBACK */ |
623 | |
624 | diff --git a/net/core/neighbour.c b/net/core/neighbour.c |
625 | index 2ae929f9bd06..9901e5b75a05 100644 |
626 | --- a/net/core/neighbour.c |
627 | +++ b/net/core/neighbour.c |
628 | @@ -2927,7 +2927,8 @@ static void neigh_proc_update(struct ctl_table *ctl, int write) |
629 | return; |
630 | |
631 | set_bit(index, p->data_state); |
632 | - call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p); |
633 | + if (index == NEIGH_VAR_DELAY_PROBE_TIME) |
634 | + call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p); |
635 | if (!dev) /* NULL dev means this is default value */ |
636 | neigh_copy_dflt_parms(net, p, index); |
637 | } |
638 | diff --git a/net/dccp/input.c b/net/dccp/input.c |
639 | index ba347184bda9..8fedc2d49770 100644 |
640 | --- a/net/dccp/input.c |
641 | +++ b/net/dccp/input.c |
642 | @@ -606,7 +606,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, |
643 | if (inet_csk(sk)->icsk_af_ops->conn_request(sk, |
644 | skb) < 0) |
645 | return 1; |
646 | - goto discard; |
647 | + consume_skb(skb); |
648 | + return 0; |
649 | } |
650 | if (dh->dccph_type == DCCP_PKT_RESET) |
651 | goto discard; |
652 | diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c |
653 | index 65336f38a5d8..9826695ddfc6 100644 |
654 | --- a/net/ipv4/ip_sockglue.c |
655 | +++ b/net/ipv4/ip_sockglue.c |
656 | @@ -105,10 +105,10 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb, |
657 | if (skb->ip_summed != CHECKSUM_COMPLETE) |
658 | return; |
659 | |
660 | - if (offset != 0) |
661 | - csum = csum_sub(csum, |
662 | - csum_partial(skb_transport_header(skb) + tlen, |
663 | - offset, 0)); |
664 | + if (offset != 0) { |
665 | + int tend_off = skb_transport_offset(skb) + tlen; |
666 | + csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0)); |
667 | + } |
668 | |
669 | put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum); |
670 | } |
671 | diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c |
672 | index acbe61c7e683..160dc89335e2 100644 |
673 | --- a/net/irda/irqueue.c |
674 | +++ b/net/irda/irqueue.c |
675 | @@ -383,9 +383,6 @@ EXPORT_SYMBOL(hashbin_new); |
676 | * for deallocating this structure if it's complex. If not the user can |
677 | * just supply kfree, which should take care of the job. |
678 | */ |
679 | -#ifdef CONFIG_LOCKDEP |
680 | -static int hashbin_lock_depth = 0; |
681 | -#endif |
682 | int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) |
683 | { |
684 | irda_queue_t* queue; |
685 | @@ -396,22 +393,27 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) |
686 | IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;); |
687 | |
688 | /* Synchronize */ |
689 | - if ( hashbin->hb_type & HB_LOCK ) { |
690 | - spin_lock_irqsave_nested(&hashbin->hb_spinlock, flags, |
691 | - hashbin_lock_depth++); |
692 | - } |
693 | + if (hashbin->hb_type & HB_LOCK) |
694 | + spin_lock_irqsave(&hashbin->hb_spinlock, flags); |
695 | |
696 | /* |
697 | * Free the entries in the hashbin, TODO: use hashbin_clear when |
698 | * it has been shown to work |
699 | */ |
700 | for (i = 0; i < HASHBIN_SIZE; i ++ ) { |
701 | - queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); |
702 | - while (queue ) { |
703 | - if (free_func) |
704 | - (*free_func)(queue); |
705 | - queue = dequeue_first( |
706 | - (irda_queue_t**) &hashbin->hb_queue[i]); |
707 | + while (1) { |
708 | + queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); |
709 | + |
710 | + if (!queue) |
711 | + break; |
712 | + |
713 | + if (free_func) { |
714 | + if (hashbin->hb_type & HB_LOCK) |
715 | + spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); |
716 | + free_func(queue); |
717 | + if (hashbin->hb_type & HB_LOCK) |
718 | + spin_lock_irqsave(&hashbin->hb_spinlock, flags); |
719 | + } |
720 | } |
721 | } |
722 | |
723 | @@ -420,12 +422,8 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) |
724 | hashbin->magic = ~HB_MAGIC; |
725 | |
726 | /* Release lock */ |
727 | - if ( hashbin->hb_type & HB_LOCK) { |
728 | + if (hashbin->hb_type & HB_LOCK) |
729 | spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); |
730 | -#ifdef CONFIG_LOCKDEP |
731 | - hashbin_lock_depth--; |
732 | -#endif |
733 | - } |
734 | |
735 | /* |
736 | * Free the hashbin structure |
737 | diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c |
738 | index 7e08a4d3d77d..a646f3481240 100644 |
739 | --- a/net/kcm/kcmsock.c |
740 | +++ b/net/kcm/kcmsock.c |
741 | @@ -929,23 +929,25 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
742 | goto out_error; |
743 | } |
744 | |
745 | - /* New message, alloc head skb */ |
746 | - head = alloc_skb(0, sk->sk_allocation); |
747 | - while (!head) { |
748 | - kcm_push(kcm); |
749 | - err = sk_stream_wait_memory(sk, &timeo); |
750 | - if (err) |
751 | - goto out_error; |
752 | - |
753 | + if (msg_data_left(msg)) { |
754 | + /* New message, alloc head skb */ |
755 | head = alloc_skb(0, sk->sk_allocation); |
756 | - } |
757 | + while (!head) { |
758 | + kcm_push(kcm); |
759 | + err = sk_stream_wait_memory(sk, &timeo); |
760 | + if (err) |
761 | + goto out_error; |
762 | |
763 | - skb = head; |
764 | + head = alloc_skb(0, sk->sk_allocation); |
765 | + } |
766 | |
767 | - /* Set ip_summed to CHECKSUM_UNNECESSARY to avoid calling |
768 | - * csum_and_copy_from_iter from skb_do_copy_data_nocache. |
769 | - */ |
770 | - skb->ip_summed = CHECKSUM_UNNECESSARY; |
771 | + skb = head; |
772 | + |
773 | + /* Set ip_summed to CHECKSUM_UNNECESSARY to avoid calling |
774 | + * csum_and_copy_from_iter from skb_do_copy_data_nocache. |
775 | + */ |
776 | + skb->ip_summed = CHECKSUM_UNNECESSARY; |
777 | + } |
778 | |
779 | start: |
780 | while (msg_data_left(msg)) { |
781 | @@ -1018,10 +1020,12 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
782 | if (eor) { |
783 | bool not_busy = skb_queue_empty(&sk->sk_write_queue); |
784 | |
785 | - /* Message complete, queue it on send buffer */ |
786 | - __skb_queue_tail(&sk->sk_write_queue, head); |
787 | - kcm->seq_skb = NULL; |
788 | - KCM_STATS_INCR(kcm->stats.tx_msgs); |
789 | + if (head) { |
790 | + /* Message complete, queue it on send buffer */ |
791 | + __skb_queue_tail(&sk->sk_write_queue, head); |
792 | + kcm->seq_skb = NULL; |
793 | + KCM_STATS_INCR(kcm->stats.tx_msgs); |
794 | + } |
795 | |
796 | if (msg->msg_flags & MSG_BATCH) { |
797 | kcm->tx_wait_more = true; |
798 | @@ -1040,8 +1044,10 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
799 | } else { |
800 | /* Message not complete, save state */ |
801 | partial_message: |
802 | - kcm->seq_skb = head; |
803 | - kcm_tx_msg(head)->last_skb = skb; |
804 | + if (head) { |
805 | + kcm->seq_skb = head; |
806 | + kcm_tx_msg(head)->last_skb = skb; |
807 | + } |
808 | } |
809 | |
810 | KCM_STATS_ADD(kcm->stats.tx_bytes, copied); |
811 | diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c |
812 | index 3e821daf9dd4..8bc5a1bd2d45 100644 |
813 | --- a/net/llc/llc_conn.c |
814 | +++ b/net/llc/llc_conn.c |
815 | @@ -821,7 +821,10 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) |
816 | * another trick required to cope with how the PROCOM state |
817 | * machine works. -acme |
818 | */ |
819 | + skb_orphan(skb); |
820 | + sock_hold(sk); |
821 | skb->sk = sk; |
822 | + skb->destructor = sock_efree; |
823 | } |
824 | if (!sock_owned_by_user(sk)) |
825 | llc_conn_rcv(sk, skb); |
826 | diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c |
827 | index d0e1e804ebd7..5404d0d195cc 100644 |
828 | --- a/net/llc/llc_sap.c |
829 | +++ b/net/llc/llc_sap.c |
830 | @@ -290,7 +290,10 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb, |
831 | |
832 | ev->type = LLC_SAP_EV_TYPE_PDU; |
833 | ev->reason = 0; |
834 | + skb_orphan(skb); |
835 | + sock_hold(sk); |
836 | skb->sk = sk; |
837 | + skb->destructor = sock_efree; |
838 | llc_sap_state_process(sap, skb); |
839 | } |
840 | |
841 | diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c |
842 | index 7341adf7059d..6dc44d9b4190 100644 |
843 | --- a/net/netfilter/nf_conntrack_helper.c |
844 | +++ b/net/netfilter/nf_conntrack_helper.c |
845 | @@ -188,6 +188,26 @@ nf_ct_helper_ext_add(struct nf_conn *ct, |
846 | } |
847 | EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); |
848 | |
849 | +static struct nf_conntrack_helper * |
850 | +nf_ct_lookup_helper(struct nf_conn *ct, struct net *net) |
851 | +{ |
852 | + if (!net->ct.sysctl_auto_assign_helper) { |
853 | + if (net->ct.auto_assign_helper_warned) |
854 | + return NULL; |
855 | + if (!__nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple)) |
856 | + return NULL; |
857 | + pr_info("nf_conntrack: default automatic helper assignment " |
858 | + "has been turned off for security reasons and CT-based " |
859 | + " firewall rule not found. Use the iptables CT target " |
860 | + "to attach helpers instead.\n"); |
861 | + net->ct.auto_assign_helper_warned = 1; |
862 | + return NULL; |
863 | + } |
864 | + |
865 | + return __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); |
866 | +} |
867 | + |
868 | + |
869 | int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, |
870 | gfp_t flags) |
871 | { |
872 | @@ -213,21 +233,14 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, |
873 | } |
874 | |
875 | help = nfct_help(ct); |
876 | - if (net->ct.sysctl_auto_assign_helper && helper == NULL) { |
877 | - helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); |
878 | - if (unlikely(!net->ct.auto_assign_helper_warned && helper)) { |
879 | - pr_info("nf_conntrack: automatic helper " |
880 | - "assignment is deprecated and it will " |
881 | - "be removed soon. Use the iptables CT target " |
882 | - "to attach helpers instead.\n"); |
883 | - net->ct.auto_assign_helper_warned = true; |
884 | - } |
885 | - } |
886 | |
887 | if (helper == NULL) { |
888 | - if (help) |
889 | - RCU_INIT_POINTER(help->helper, NULL); |
890 | - return 0; |
891 | + helper = nf_ct_lookup_helper(ct, net); |
892 | + if (helper == NULL) { |
893 | + if (help) |
894 | + RCU_INIT_POINTER(help->helper, NULL); |
895 | + return 0; |
896 | + } |
897 | } |
898 | |
899 | if (help == NULL) { |
900 | diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c |
901 | index 458722b938c7..34de326b4f09 100644 |
902 | --- a/net/packet/af_packet.c |
903 | +++ b/net/packet/af_packet.c |
904 | @@ -1497,6 +1497,8 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po) |
905 | f->arr[f->num_members] = sk; |
906 | smp_wmb(); |
907 | f->num_members++; |
908 | + if (f->num_members == 1) |
909 | + dev_add_pack(&f->prot_hook); |
910 | spin_unlock(&f->lock); |
911 | } |
912 | |
913 | @@ -1513,6 +1515,8 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po) |
914 | BUG_ON(i >= f->num_members); |
915 | f->arr[i] = f->arr[f->num_members - 1]; |
916 | f->num_members--; |
917 | + if (f->num_members == 0) |
918 | + __dev_remove_pack(&f->prot_hook); |
919 | spin_unlock(&f->lock); |
920 | } |
921 | |
922 | @@ -1619,6 +1623,7 @@ static void fanout_release_data(struct packet_fanout *f) |
923 | |
924 | static int fanout_add(struct sock *sk, u16 id, u16 type_flags) |
925 | { |
926 | + struct packet_rollover *rollover = NULL; |
927 | struct packet_sock *po = pkt_sk(sk); |
928 | struct packet_fanout *f, *match; |
929 | u8 type = type_flags & 0xff; |
930 | @@ -1641,23 +1646,28 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) |
931 | return -EINVAL; |
932 | } |
933 | |
934 | + mutex_lock(&fanout_mutex); |
935 | + |
936 | + err = -EINVAL; |
937 | if (!po->running) |
938 | - return -EINVAL; |
939 | + goto out; |
940 | |
941 | + err = -EALREADY; |
942 | if (po->fanout) |
943 | - return -EALREADY; |
944 | + goto out; |
945 | |
946 | if (type == PACKET_FANOUT_ROLLOVER || |
947 | (type_flags & PACKET_FANOUT_FLAG_ROLLOVER)) { |
948 | - po->rollover = kzalloc(sizeof(*po->rollover), GFP_KERNEL); |
949 | - if (!po->rollover) |
950 | - return -ENOMEM; |
951 | - atomic_long_set(&po->rollover->num, 0); |
952 | - atomic_long_set(&po->rollover->num_huge, 0); |
953 | - atomic_long_set(&po->rollover->num_failed, 0); |
954 | + err = -ENOMEM; |
955 | + rollover = kzalloc(sizeof(*rollover), GFP_KERNEL); |
956 | + if (!rollover) |
957 | + goto out; |
958 | + atomic_long_set(&rollover->num, 0); |
959 | + atomic_long_set(&rollover->num_huge, 0); |
960 | + atomic_long_set(&rollover->num_failed, 0); |
961 | + po->rollover = rollover; |
962 | } |
963 | |
964 | - mutex_lock(&fanout_mutex); |
965 | match = NULL; |
966 | list_for_each_entry(f, &fanout_list, list) { |
967 | if (f->id == id && |
968 | @@ -1687,7 +1697,6 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) |
969 | match->prot_hook.func = packet_rcv_fanout; |
970 | match->prot_hook.af_packet_priv = match; |
971 | match->prot_hook.id_match = match_fanout_group; |
972 | - dev_add_pack(&match->prot_hook); |
973 | list_add(&match->list, &fanout_list); |
974 | } |
975 | err = -EINVAL; |
976 | @@ -1704,36 +1713,40 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) |
977 | } |
978 | } |
979 | out: |
980 | - mutex_unlock(&fanout_mutex); |
981 | - if (err) { |
982 | - kfree(po->rollover); |
983 | + if (err && rollover) { |
984 | + kfree(rollover); |
985 | po->rollover = NULL; |
986 | } |
987 | + mutex_unlock(&fanout_mutex); |
988 | return err; |
989 | } |
990 | |
991 | -static void fanout_release(struct sock *sk) |
992 | +/* If pkt_sk(sk)->fanout->sk_ref is zero, this function removes |
993 | + * pkt_sk(sk)->fanout from fanout_list and returns pkt_sk(sk)->fanout. |
994 | + * It is the responsibility of the caller to call fanout_release_data() and |
995 | + * free the returned packet_fanout (after synchronize_net()) |
996 | + */ |
997 | +static struct packet_fanout *fanout_release(struct sock *sk) |
998 | { |
999 | struct packet_sock *po = pkt_sk(sk); |
1000 | struct packet_fanout *f; |
1001 | |
1002 | + mutex_lock(&fanout_mutex); |
1003 | f = po->fanout; |
1004 | - if (!f) |
1005 | - return; |
1006 | + if (f) { |
1007 | + po->fanout = NULL; |
1008 | |
1009 | - mutex_lock(&fanout_mutex); |
1010 | - po->fanout = NULL; |
1011 | + if (atomic_dec_and_test(&f->sk_ref)) |
1012 | + list_del(&f->list); |
1013 | + else |
1014 | + f = NULL; |
1015 | |
1016 | - if (atomic_dec_and_test(&f->sk_ref)) { |
1017 | - list_del(&f->list); |
1018 | - dev_remove_pack(&f->prot_hook); |
1019 | - fanout_release_data(f); |
1020 | - kfree(f); |
1021 | + if (po->rollover) |
1022 | + kfree_rcu(po->rollover, rcu); |
1023 | } |
1024 | mutex_unlock(&fanout_mutex); |
1025 | |
1026 | - if (po->rollover) |
1027 | - kfree_rcu(po->rollover, rcu); |
1028 | + return f; |
1029 | } |
1030 | |
1031 | static bool packet_extra_vlan_len_allowed(const struct net_device *dev, |
1032 | @@ -2965,6 +2978,7 @@ static int packet_release(struct socket *sock) |
1033 | { |
1034 | struct sock *sk = sock->sk; |
1035 | struct packet_sock *po; |
1036 | + struct packet_fanout *f; |
1037 | struct net *net; |
1038 | union tpacket_req_u req_u; |
1039 | |
1040 | @@ -3004,9 +3018,14 @@ static int packet_release(struct socket *sock) |
1041 | packet_set_ring(sk, &req_u, 1, 1); |
1042 | } |
1043 | |
1044 | - fanout_release(sk); |
1045 | + f = fanout_release(sk); |
1046 | |
1047 | synchronize_net(); |
1048 | + |
1049 | + if (f) { |
1050 | + fanout_release_data(f); |
1051 | + kfree(f); |
1052 | + } |
1053 | /* |
1054 | * Now the socket is dead. No more input will appear. |
1055 | */ |
1056 | @@ -3958,7 +3977,6 @@ static int packet_notifier(struct notifier_block *this, |
1057 | } |
1058 | if (msg == NETDEV_UNREGISTER) { |
1059 | packet_cached_dev_reset(po); |
1060 | - fanout_release(sk); |
1061 | po->ifindex = -1; |
1062 | if (po->prot_hook.dev) |
1063 | dev_put(po->prot_hook.dev); |
1064 | diff --git a/net/socket.c b/net/socket.c |
1065 | index 73dc69f9681e..6bbccf05854f 100644 |
1066 | --- a/net/socket.c |
1067 | +++ b/net/socket.c |
1068 | @@ -2197,8 +2197,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, |
1069 | return err; |
1070 | |
1071 | err = sock_error(sock->sk); |
1072 | - if (err) |
1073 | + if (err) { |
1074 | + datagrams = err; |
1075 | goto out_put; |
1076 | + } |
1077 | |
1078 | entry = mmsg; |
1079 | compat_entry = (struct compat_mmsghdr __user *)mmsg; |