1 |
commit: f209e98096e70700cfc4d98580b2f817781c15b6 |
2 |
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
3 |
AuthorDate: Tue Apr 18 10:20:01 2017 +0000 |
4 |
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
5 |
CommitDate: Tue Apr 18 10:20:01 2017 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=f209e980 |
7 |
|
8 |
Linux patch 3.18.49 |
9 |
|
10 |
0000_README | 4 + |
11 |
1048_linux-3.18.49.patch | 10446 +++++++++++++++++++++++++++++++++++++++++++++ |
12 |
2 files changed, 10450 insertions(+) |
13 |
|
14 |
diff --git a/0000_README b/0000_README |
15 |
index 4676a64..4c41f0b 100644 |
16 |
--- a/0000_README |
17 |
+++ b/0000_README |
18 |
@@ -235,6 +235,10 @@ Patch: 1047_linux-3.18.48.patch |
19 |
From: http://www.kernel.org |
20 |
Desc: Linux 3.18.48 |
21 |
|
22 |
+Patch: 1048_linux-3.18.49.patch |
23 |
+From: http://www.kernel.org |
24 |
+Desc: Linux 3.18.49 |
25 |
+ |
26 |
Patch: 1500_XATTR_USER_PREFIX.patch |
27 |
From: https://bugs.gentoo.org/show_bug.cgi?id=470644 |
28 |
Desc: Support for namespace user.pax.* on tmpfs. |
29 |
|
30 |
diff --git a/1048_linux-3.18.49.patch b/1048_linux-3.18.49.patch |
31 |
new file mode 100644 |
32 |
index 0000000..d923bd5 |
33 |
--- /dev/null |
34 |
+++ b/1048_linux-3.18.49.patch |
35 |
@@ -0,0 +1,10446 @@ |
36 |
+diff --git a/Documentation/Makefile b/Documentation/Makefile |
37 |
+index bc0548201755..fc759598c4c9 100644 |
38 |
+--- a/Documentation/Makefile |
39 |
++++ b/Documentation/Makefile |
40 |
+@@ -1,4 +1,4 @@ |
41 |
+ subdir-y := accounting auxdisplay blackfin connector \ |
42 |
+- filesystems filesystems ia64 laptops mic misc-devices \ |
43 |
++ filesystems filesystems ia64 laptops misc-devices \ |
44 |
+ networking pcmcia prctl ptp spi timers vDSO video4linux \ |
45 |
+ watchdog |
46 |
+diff --git a/Documentation/mic/Makefile b/Documentation/mic/Makefile |
47 |
+deleted file mode 100644 |
48 |
+index a191d453badf..000000000000 |
49 |
+--- a/Documentation/mic/Makefile |
50 |
++++ /dev/null |
51 |
+@@ -1 +0,0 @@ |
52 |
+-subdir-y := mpssd |
53 |
+diff --git a/Documentation/mic/mpssd/.gitignore b/Documentation/mic/mpssd/.gitignore |
54 |
+deleted file mode 100644 |
55 |
+index 8b7c72f07c92..000000000000 |
56 |
+--- a/Documentation/mic/mpssd/.gitignore |
57 |
++++ /dev/null |
58 |
+@@ -1 +0,0 @@ |
59 |
+-mpssd |
60 |
+diff --git a/Documentation/mic/mpssd/Makefile b/Documentation/mic/mpssd/Makefile |
61 |
+deleted file mode 100644 |
62 |
+index 0f3156888048..000000000000 |
63 |
+--- a/Documentation/mic/mpssd/Makefile |
64 |
++++ /dev/null |
65 |
+@@ -1,19 +0,0 @@ |
66 |
+-# List of programs to build |
67 |
+-hostprogs-y := mpssd |
68 |
+- |
69 |
+-mpssd-objs := mpssd.o sysfs.o |
70 |
+- |
71 |
+-# Tell kbuild to always build the programs |
72 |
+-always := $(hostprogs-y) |
73 |
+- |
74 |
+-HOSTCFLAGS += -I$(objtree)/usr/include -I$(srctree)/tools/include |
75 |
+- |
76 |
+-ifdef DEBUG |
77 |
+-HOSTCFLAGS += -DDEBUG=$(DEBUG) |
78 |
+-endif |
79 |
+- |
80 |
+-HOSTLOADLIBES_mpssd := -lpthread |
81 |
+- |
82 |
+-install: |
83 |
+- install mpssd /usr/sbin/mpssd |
84 |
+- install micctrl /usr/sbin/micctrl |
85 |
+diff --git a/Documentation/mic/mpssd/micctrl b/Documentation/mic/mpssd/micctrl |
86 |
+deleted file mode 100755 |
87 |
+index 8f2629b41c5f..000000000000 |
88 |
+--- a/Documentation/mic/mpssd/micctrl |
89 |
++++ /dev/null |
90 |
+@@ -1,173 +0,0 @@ |
91 |
+-#!/bin/bash |
92 |
+-# Intel MIC Platform Software Stack (MPSS) |
93 |
+-# |
94 |
+-# Copyright(c) 2013 Intel Corporation. |
95 |
+-# |
96 |
+-# This program is free software; you can redistribute it and/or modify |
97 |
+-# it under the terms of the GNU General Public License, version 2, as |
98 |
+-# published by the Free Software Foundation. |
99 |
+-# |
100 |
+-# This program is distributed in the hope that it will be useful, but |
101 |
+-# WITHOUT ANY WARRANTY; without even the implied warranty of |
102 |
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
103 |
+-# General Public License for more details. |
104 |
+-# |
105 |
+-# The full GNU General Public License is included in this distribution in |
106 |
+-# the file called "COPYING". |
107 |
+-# |
108 |
+-# Intel MIC User Space Tools. |
109 |
+-# |
110 |
+-# micctrl - Controls MIC boot/start/stop. |
111 |
+-# |
112 |
+-# chkconfig: 2345 95 05 |
113 |
+-# description: start MPSS stack processing. |
114 |
+-# |
115 |
+-### BEGIN INIT INFO |
116 |
+-# Provides: micctrl |
117 |
+-### END INIT INFO |
118 |
+- |
119 |
+-# Source function library. |
120 |
+-. /etc/init.d/functions |
121 |
+- |
122 |
+-sysfs="/sys/class/mic" |
123 |
+- |
124 |
+-_status() |
125 |
+-{ |
126 |
+- f=$sysfs/$1 |
127 |
+- echo -e $1 state: "`cat $f/state`" shutdown_status: "`cat $f/shutdown_status`" |
128 |
+-} |
129 |
+- |
130 |
+-status() |
131 |
+-{ |
132 |
+- if [ "`echo $1 | head -c3`" == "mic" ]; then |
133 |
+- _status $1 |
134 |
+- return $? |
135 |
+- fi |
136 |
+- for f in $sysfs/* |
137 |
+- do |
138 |
+- _status `basename $f` |
139 |
+- RETVAL=$? |
140 |
+- [ $RETVAL -ne 0 ] && return $RETVAL |
141 |
+- done |
142 |
+- return 0 |
143 |
+-} |
144 |
+- |
145 |
+-_reset() |
146 |
+-{ |
147 |
+- f=$sysfs/$1 |
148 |
+- echo reset > $f/state |
149 |
+-} |
150 |
+- |
151 |
+-reset() |
152 |
+-{ |
153 |
+- if [ "`echo $1 | head -c3`" == "mic" ]; then |
154 |
+- _reset $1 |
155 |
+- return $? |
156 |
+- fi |
157 |
+- for f in $sysfs/* |
158 |
+- do |
159 |
+- _reset `basename $f` |
160 |
+- RETVAL=$? |
161 |
+- [ $RETVAL -ne 0 ] && return $RETVAL |
162 |
+- done |
163 |
+- return 0 |
164 |
+-} |
165 |
+- |
166 |
+-_boot() |
167 |
+-{ |
168 |
+- f=$sysfs/$1 |
169 |
+- echo "linux" > $f/bootmode |
170 |
+- echo "mic/uos.img" > $f/firmware |
171 |
+- echo "mic/$1.image" > $f/ramdisk |
172 |
+- echo "boot" > $f/state |
173 |
+-} |
174 |
+- |
175 |
+-boot() |
176 |
+-{ |
177 |
+- if [ "`echo $1 | head -c3`" == "mic" ]; then |
178 |
+- _boot $1 |
179 |
+- return $? |
180 |
+- fi |
181 |
+- for f in $sysfs/* |
182 |
+- do |
183 |
+- _boot `basename $f` |
184 |
+- RETVAL=$? |
185 |
+- [ $RETVAL -ne 0 ] && return $RETVAL |
186 |
+- done |
187 |
+- return 0 |
188 |
+-} |
189 |
+- |
190 |
+-_shutdown() |
191 |
+-{ |
192 |
+- f=$sysfs/$1 |
193 |
+- echo shutdown > $f/state |
194 |
+-} |
195 |
+- |
196 |
+-shutdown() |
197 |
+-{ |
198 |
+- if [ "`echo $1 | head -c3`" == "mic" ]; then |
199 |
+- _shutdown $1 |
200 |
+- return $? |
201 |
+- fi |
202 |
+- for f in $sysfs/* |
203 |
+- do |
204 |
+- _shutdown `basename $f` |
205 |
+- RETVAL=$? |
206 |
+- [ $RETVAL -ne 0 ] && return $RETVAL |
207 |
+- done |
208 |
+- return 0 |
209 |
+-} |
210 |
+- |
211 |
+-_wait() |
212 |
+-{ |
213 |
+- f=$sysfs/$1 |
214 |
+- while [ "`cat $f/state`" != "offline" -a "`cat $f/state`" != "online" ] |
215 |
+- do |
216 |
+- sleep 1 |
217 |
+- echo -e "Waiting for $1 to go offline" |
218 |
+- done |
219 |
+-} |
220 |
+- |
221 |
+-wait() |
222 |
+-{ |
223 |
+- if [ "`echo $1 | head -c3`" == "mic" ]; then |
224 |
+- _wait $1 |
225 |
+- return $? |
226 |
+- fi |
227 |
+- # Wait for the cards to go offline |
228 |
+- for f in $sysfs/* |
229 |
+- do |
230 |
+- _wait `basename $f` |
231 |
+- RETVAL=$? |
232 |
+- [ $RETVAL -ne 0 ] && return $RETVAL |
233 |
+- done |
234 |
+- return 0 |
235 |
+-} |
236 |
+- |
237 |
+-if [ ! -d "$sysfs" ]; then |
238 |
+- echo -e $"Module unloaded " |
239 |
+- exit 3 |
240 |
+-fi |
241 |
+- |
242 |
+-case $1 in |
243 |
+- -s) |
244 |
+- status $2 |
245 |
+- ;; |
246 |
+- -r) |
247 |
+- reset $2 |
248 |
+- ;; |
249 |
+- -b) |
250 |
+- boot $2 |
251 |
+- ;; |
252 |
+- -S) |
253 |
+- shutdown $2 |
254 |
+- ;; |
255 |
+- -w) |
256 |
+- wait $2 |
257 |
+- ;; |
258 |
+- *) |
259 |
+- echo $"Usage: $0 {-s (status) |-r (reset) |-b (boot) |-S (shutdown) |-w (wait)}" |
260 |
+- exit 2 |
261 |
+-esac |
262 |
+- |
263 |
+-exit $? |
264 |
+diff --git a/Documentation/mic/mpssd/mpss b/Documentation/mic/mpssd/mpss |
265 |
+deleted file mode 100755 |
266 |
+index cacbdb0aefb9..000000000000 |
267 |
+--- a/Documentation/mic/mpssd/mpss |
268 |
++++ /dev/null |
269 |
+@@ -1,202 +0,0 @@ |
270 |
+-#!/bin/bash |
271 |
+-# Intel MIC Platform Software Stack (MPSS) |
272 |
+-# |
273 |
+-# Copyright(c) 2013 Intel Corporation. |
274 |
+-# |
275 |
+-# This program is free software; you can redistribute it and/or modify |
276 |
+-# it under the terms of the GNU General Public License, version 2, as |
277 |
+-# published by the Free Software Foundation. |
278 |
+-# |
279 |
+-# This program is distributed in the hope that it will be useful, but |
280 |
+-# WITHOUT ANY WARRANTY; without even the implied warranty of |
281 |
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
282 |
+-# General Public License for more details. |
283 |
+-# |
284 |
+-# The full GNU General Public License is included in this distribution in |
285 |
+-# the file called "COPYING". |
286 |
+-# |
287 |
+-# Intel MIC User Space Tools. |
288 |
+-# |
289 |
+-# mpss Start mpssd. |
290 |
+-# |
291 |
+-# chkconfig: 2345 95 05 |
292 |
+-# description: start MPSS stack processing. |
293 |
+-# |
294 |
+-### BEGIN INIT INFO |
295 |
+-# Provides: mpss |
296 |
+-# Required-Start: |
297 |
+-# Required-Stop: |
298 |
+-# Short-Description: MPSS stack control |
299 |
+-# Description: MPSS stack control |
300 |
+-### END INIT INFO |
301 |
+- |
302 |
+-# Source function library. |
303 |
+-. /etc/init.d/functions |
304 |
+- |
305 |
+-exec=/usr/sbin/mpssd |
306 |
+-sysfs="/sys/class/mic" |
307 |
+- |
308 |
+-start() |
309 |
+-{ |
310 |
+- [ -x $exec ] || exit 5 |
311 |
+- |
312 |
+- if [ "`ps -e | awk '{print $4}' | grep mpssd | head -1`" = "mpssd" ]; then |
313 |
+- echo -e $"MPSSD already running! " |
314 |
+- success |
315 |
+- echo |
316 |
+- return 0 |
317 |
+- fi |
318 |
+- |
319 |
+- echo -e $"Starting MPSS Stack" |
320 |
+- echo -e $"Loading MIC_X100_DMA & MIC_HOST Modules" |
321 |
+- |
322 |
+- for f in "mic_host" "mic_x100_dma" |
323 |
+- do |
324 |
+- modprobe $f |
325 |
+- RETVAL=$? |
326 |
+- if [ $RETVAL -ne 0 ]; then |
327 |
+- failure |
328 |
+- echo |
329 |
+- return $RETVAL |
330 |
+- fi |
331 |
+- done |
332 |
+- |
333 |
+- # Start the daemon |
334 |
+- echo -n $"Starting MPSSD " |
335 |
+- $exec |
336 |
+- RETVAL=$? |
337 |
+- if [ $RETVAL -ne 0 ]; then |
338 |
+- failure |
339 |
+- echo |
340 |
+- return $RETVAL |
341 |
+- fi |
342 |
+- success |
343 |
+- echo |
344 |
+- |
345 |
+- sleep 5 |
346 |
+- |
347 |
+- # Boot the cards |
348 |
+- micctrl -b |
349 |
+- |
350 |
+- # Wait till ping works |
351 |
+- for f in $sysfs/* |
352 |
+- do |
353 |
+- count=100 |
354 |
+- ipaddr=`cat $f/cmdline` |
355 |
+- ipaddr=${ipaddr#*address,} |
356 |
+- ipaddr=`echo $ipaddr | cut -d, -f1 | cut -d\; -f1` |
357 |
+- while [ $count -ge 0 ] |
358 |
+- do |
359 |
+- echo -e "Pinging "`basename $f`" " |
360 |
+- ping -c 1 $ipaddr &> /dev/null |
361 |
+- RETVAL=$? |
362 |
+- if [ $RETVAL -eq 0 ]; then |
363 |
+- success |
364 |
+- break |
365 |
+- fi |
366 |
+- sleep 1 |
367 |
+- count=`expr $count - 1` |
368 |
+- done |
369 |
+- [ $RETVAL -ne 0 ] && failure || success |
370 |
+- echo |
371 |
+- done |
372 |
+- return $RETVAL |
373 |
+-} |
374 |
+- |
375 |
+-stop() |
376 |
+-{ |
377 |
+- echo -e $"Shutting down MPSS Stack: " |
378 |
+- |
379 |
+- # Bail out if module is unloaded |
380 |
+- if [ ! -d "$sysfs" ]; then |
381 |
+- echo -n $"Module unloaded " |
382 |
+- success |
383 |
+- echo |
384 |
+- return 0 |
385 |
+- fi |
386 |
+- |
387 |
+- # Shut down the cards. |
388 |
+- micctrl -S |
389 |
+- |
390 |
+- # Wait for the cards to go offline |
391 |
+- for f in $sysfs/* |
392 |
+- do |
393 |
+- while [ "`cat $f/state`" != "offline" ] |
394 |
+- do |
395 |
+- sleep 1 |
396 |
+- echo -e "Waiting for "`basename $f`" to go offline" |
397 |
+- done |
398 |
+- done |
399 |
+- |
400 |
+- # Display the status of the cards |
401 |
+- micctrl -s |
402 |
+- |
403 |
+- # Kill MPSSD now |
404 |
+- echo -n $"Killing MPSSD" |
405 |
+- killall -9 mpssd 2>/dev/null |
406 |
+- RETVAL=$? |
407 |
+- [ $RETVAL -ne 0 ] && failure || success |
408 |
+- echo |
409 |
+- return $RETVAL |
410 |
+-} |
411 |
+- |
412 |
+-restart() |
413 |
+-{ |
414 |
+- stop |
415 |
+- sleep 5 |
416 |
+- start |
417 |
+-} |
418 |
+- |
419 |
+-status() |
420 |
+-{ |
421 |
+- micctrl -s |
422 |
+- if [ "`ps -e | awk '{print $4}' | grep mpssd | head -n 1`" = "mpssd" ]; then |
423 |
+- echo "mpssd is running" |
424 |
+- else |
425 |
+- echo "mpssd is stopped" |
426 |
+- fi |
427 |
+- return 0 |
428 |
+-} |
429 |
+- |
430 |
+-unload() |
431 |
+-{ |
432 |
+- if [ ! -d "$sysfs" ]; then |
433 |
+- echo -n $"No MIC_HOST Module: " |
434 |
+- success |
435 |
+- echo |
436 |
+- return |
437 |
+- fi |
438 |
+- |
439 |
+- stop |
440 |
+- |
441 |
+- sleep 5 |
442 |
+- echo -n $"Removing MIC_HOST & MIC_X100_DMA Modules: " |
443 |
+- modprobe -r mic_host mic_x100_dma |
444 |
+- RETVAL=$? |
445 |
+- [ $RETVAL -ne 0 ] && failure || success |
446 |
+- echo |
447 |
+- return $RETVAL |
448 |
+-} |
449 |
+- |
450 |
+-case $1 in |
451 |
+- start) |
452 |
+- start |
453 |
+- ;; |
454 |
+- stop) |
455 |
+- stop |
456 |
+- ;; |
457 |
+- restart) |
458 |
+- restart |
459 |
+- ;; |
460 |
+- status) |
461 |
+- status |
462 |
+- ;; |
463 |
+- unload) |
464 |
+- unload |
465 |
+- ;; |
466 |
+- *) |
467 |
+- echo $"Usage: $0 {start|stop|restart|status|unload}" |
468 |
+- exit 2 |
469 |
+-esac |
470 |
+- |
471 |
+-exit $? |
472 |
+diff --git a/Documentation/mic/mpssd/mpssd.c b/Documentation/mic/mpssd/mpssd.c |
473 |
+deleted file mode 100644 |
474 |
+index 3c5c379fc29d..000000000000 |
475 |
+--- a/Documentation/mic/mpssd/mpssd.c |
476 |
++++ /dev/null |
477 |
+@@ -1,1728 +0,0 @@ |
478 |
+-/* |
479 |
+- * Intel MIC Platform Software Stack (MPSS) |
480 |
+- * |
481 |
+- * Copyright(c) 2013 Intel Corporation. |
482 |
+- * |
483 |
+- * This program is free software; you can redistribute it and/or modify |
484 |
+- * it under the terms of the GNU General Public License, version 2, as |
485 |
+- * published by the Free Software Foundation. |
486 |
+- * |
487 |
+- * This program is distributed in the hope that it will be useful, but |
488 |
+- * WITHOUT ANY WARRANTY; without even the implied warranty of |
489 |
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
490 |
+- * General Public License for more details. |
491 |
+- * |
492 |
+- * The full GNU General Public License is included in this distribution in |
493 |
+- * the file called "COPYING". |
494 |
+- * |
495 |
+- * Intel MIC User Space Tools. |
496 |
+- */ |
497 |
+- |
498 |
+-#define _GNU_SOURCE |
499 |
+- |
500 |
+-#include <stdlib.h> |
501 |
+-#include <fcntl.h> |
502 |
+-#include <getopt.h> |
503 |
+-#include <assert.h> |
504 |
+-#include <unistd.h> |
505 |
+-#include <stdbool.h> |
506 |
+-#include <signal.h> |
507 |
+-#include <poll.h> |
508 |
+-#include <features.h> |
509 |
+-#include <sys/types.h> |
510 |
+-#include <sys/stat.h> |
511 |
+-#include <sys/mman.h> |
512 |
+-#include <sys/socket.h> |
513 |
+-#include <linux/virtio_ring.h> |
514 |
+-#include <linux/virtio_net.h> |
515 |
+-#include <linux/virtio_console.h> |
516 |
+-#include <linux/virtio_blk.h> |
517 |
+-#include <linux/version.h> |
518 |
+-#include "mpssd.h" |
519 |
+-#include <linux/mic_ioctl.h> |
520 |
+-#include <linux/mic_common.h> |
521 |
+-#include <tools/endian.h> |
522 |
+- |
523 |
+-static void init_mic(struct mic_info *mic); |
524 |
+- |
525 |
+-static FILE *logfp; |
526 |
+-static struct mic_info mic_list; |
527 |
+- |
528 |
+-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
529 |
+- |
530 |
+-#define min_t(type, x, y) ({ \ |
531 |
+- type __min1 = (x); \ |
532 |
+- type __min2 = (y); \ |
533 |
+- __min1 < __min2 ? __min1 : __min2; }) |
534 |
+- |
535 |
+-/* align addr on a size boundary - adjust address up/down if needed */ |
536 |
+-#define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1))) |
537 |
+-#define _ALIGN_UP(addr, size) _ALIGN_DOWN(addr + size - 1, size) |
538 |
+- |
539 |
+-/* align addr on a size boundary - adjust address up if needed */ |
540 |
+-#define _ALIGN(addr, size) _ALIGN_UP(addr, size) |
541 |
+- |
542 |
+-/* to align the pointer to the (next) page boundary */ |
543 |
+-#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) |
544 |
+- |
545 |
+-#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) |
546 |
+- |
547 |
+-#define GSO_ENABLED 1 |
548 |
+-#define MAX_GSO_SIZE (64 * 1024) |
549 |
+-#define ETH_H_LEN 14 |
550 |
+-#define MAX_NET_PKT_SIZE (_ALIGN_UP(MAX_GSO_SIZE + ETH_H_LEN, 64)) |
551 |
+-#define MIC_DEVICE_PAGE_END 0x1000 |
552 |
+- |
553 |
+-#ifndef VIRTIO_NET_HDR_F_DATA_VALID |
554 |
+-#define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */ |
555 |
+-#endif |
556 |
+- |
557 |
+-static struct { |
558 |
+- struct mic_device_desc dd; |
559 |
+- struct mic_vqconfig vqconfig[2]; |
560 |
+- __u32 host_features, guest_acknowledgements; |
561 |
+- struct virtio_console_config cons_config; |
562 |
+-} virtcons_dev_page = { |
563 |
+- .dd = { |
564 |
+- .type = VIRTIO_ID_CONSOLE, |
565 |
+- .num_vq = ARRAY_SIZE(virtcons_dev_page.vqconfig), |
566 |
+- .feature_len = sizeof(virtcons_dev_page.host_features), |
567 |
+- .config_len = sizeof(virtcons_dev_page.cons_config), |
568 |
+- }, |
569 |
+- .vqconfig[0] = { |
570 |
+- .num = htole16(MIC_VRING_ENTRIES), |
571 |
+- }, |
572 |
+- .vqconfig[1] = { |
573 |
+- .num = htole16(MIC_VRING_ENTRIES), |
574 |
+- }, |
575 |
+-}; |
576 |
+- |
577 |
+-static struct { |
578 |
+- struct mic_device_desc dd; |
579 |
+- struct mic_vqconfig vqconfig[2]; |
580 |
+- __u32 host_features, guest_acknowledgements; |
581 |
+- struct virtio_net_config net_config; |
582 |
+-} virtnet_dev_page = { |
583 |
+- .dd = { |
584 |
+- .type = VIRTIO_ID_NET, |
585 |
+- .num_vq = ARRAY_SIZE(virtnet_dev_page.vqconfig), |
586 |
+- .feature_len = sizeof(virtnet_dev_page.host_features), |
587 |
+- .config_len = sizeof(virtnet_dev_page.net_config), |
588 |
+- }, |
589 |
+- .vqconfig[0] = { |
590 |
+- .num = htole16(MIC_VRING_ENTRIES), |
591 |
+- }, |
592 |
+- .vqconfig[1] = { |
593 |
+- .num = htole16(MIC_VRING_ENTRIES), |
594 |
+- }, |
595 |
+-#if GSO_ENABLED |
596 |
+- .host_features = htole32( |
597 |
+- 1 << VIRTIO_NET_F_CSUM | |
598 |
+- 1 << VIRTIO_NET_F_GSO | |
599 |
+- 1 << VIRTIO_NET_F_GUEST_TSO4 | |
600 |
+- 1 << VIRTIO_NET_F_GUEST_TSO6 | |
601 |
+- 1 << VIRTIO_NET_F_GUEST_ECN | |
602 |
+- 1 << VIRTIO_NET_F_GUEST_UFO), |
603 |
+-#else |
604 |
+- .host_features = 0, |
605 |
+-#endif |
606 |
+-}; |
607 |
+- |
608 |
+-static const char *mic_config_dir = "/etc/sysconfig/mic"; |
609 |
+-static const char *virtblk_backend = "VIRTBLK_BACKEND"; |
610 |
+-static struct { |
611 |
+- struct mic_device_desc dd; |
612 |
+- struct mic_vqconfig vqconfig[1]; |
613 |
+- __u32 host_features, guest_acknowledgements; |
614 |
+- struct virtio_blk_config blk_config; |
615 |
+-} virtblk_dev_page = { |
616 |
+- .dd = { |
617 |
+- .type = VIRTIO_ID_BLOCK, |
618 |
+- .num_vq = ARRAY_SIZE(virtblk_dev_page.vqconfig), |
619 |
+- .feature_len = sizeof(virtblk_dev_page.host_features), |
620 |
+- .config_len = sizeof(virtblk_dev_page.blk_config), |
621 |
+- }, |
622 |
+- .vqconfig[0] = { |
623 |
+- .num = htole16(MIC_VRING_ENTRIES), |
624 |
+- }, |
625 |
+- .host_features = |
626 |
+- htole32(1<<VIRTIO_BLK_F_SEG_MAX), |
627 |
+- .blk_config = { |
628 |
+- .seg_max = htole32(MIC_VRING_ENTRIES - 2), |
629 |
+- .capacity = htole64(0), |
630 |
+- } |
631 |
+-}; |
632 |
+- |
633 |
+-static char *myname; |
634 |
+- |
635 |
+-static int |
636 |
+-tap_configure(struct mic_info *mic, char *dev) |
637 |
+-{ |
638 |
+- pid_t pid; |
639 |
+- char *ifargv[7]; |
640 |
+- char ipaddr[IFNAMSIZ]; |
641 |
+- int ret = 0; |
642 |
+- |
643 |
+- pid = fork(); |
644 |
+- if (pid == 0) { |
645 |
+- ifargv[0] = "ip"; |
646 |
+- ifargv[1] = "link"; |
647 |
+- ifargv[2] = "set"; |
648 |
+- ifargv[3] = dev; |
649 |
+- ifargv[4] = "up"; |
650 |
+- ifargv[5] = NULL; |
651 |
+- mpsslog("Configuring %s\n", dev); |
652 |
+- ret = execvp("ip", ifargv); |
653 |
+- if (ret < 0) { |
654 |
+- mpsslog("%s execvp failed errno %s\n", |
655 |
+- mic->name, strerror(errno)); |
656 |
+- return ret; |
657 |
+- } |
658 |
+- } |
659 |
+- if (pid < 0) { |
660 |
+- mpsslog("%s fork failed errno %s\n", |
661 |
+- mic->name, strerror(errno)); |
662 |
+- return ret; |
663 |
+- } |
664 |
+- |
665 |
+- ret = waitpid(pid, NULL, 0); |
666 |
+- if (ret < 0) { |
667 |
+- mpsslog("%s waitpid failed errno %s\n", |
668 |
+- mic->name, strerror(errno)); |
669 |
+- return ret; |
670 |
+- } |
671 |
+- |
672 |
+- snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id); |
673 |
+- |
674 |
+- pid = fork(); |
675 |
+- if (pid == 0) { |
676 |
+- ifargv[0] = "ip"; |
677 |
+- ifargv[1] = "addr"; |
678 |
+- ifargv[2] = "add"; |
679 |
+- ifargv[3] = ipaddr; |
680 |
+- ifargv[4] = "dev"; |
681 |
+- ifargv[5] = dev; |
682 |
+- ifargv[6] = NULL; |
683 |
+- mpsslog("Configuring %s ipaddr %s\n", dev, ipaddr); |
684 |
+- ret = execvp("ip", ifargv); |
685 |
+- if (ret < 0) { |
686 |
+- mpsslog("%s execvp failed errno %s\n", |
687 |
+- mic->name, strerror(errno)); |
688 |
+- return ret; |
689 |
+- } |
690 |
+- } |
691 |
+- if (pid < 0) { |
692 |
+- mpsslog("%s fork failed errno %s\n", |
693 |
+- mic->name, strerror(errno)); |
694 |
+- return ret; |
695 |
+- } |
696 |
+- |
697 |
+- ret = waitpid(pid, NULL, 0); |
698 |
+- if (ret < 0) { |
699 |
+- mpsslog("%s waitpid failed errno %s\n", |
700 |
+- mic->name, strerror(errno)); |
701 |
+- return ret; |
702 |
+- } |
703 |
+- mpsslog("MIC name %s %s %d DONE!\n", |
704 |
+- mic->name, __func__, __LINE__); |
705 |
+- return 0; |
706 |
+-} |
707 |
+- |
708 |
+-static int tun_alloc(struct mic_info *mic, char *dev) |
709 |
+-{ |
710 |
+- struct ifreq ifr; |
711 |
+- int fd, err; |
712 |
+-#if GSO_ENABLED |
713 |
+- unsigned offload; |
714 |
+-#endif |
715 |
+- fd = open("/dev/net/tun", O_RDWR); |
716 |
+- if (fd < 0) { |
717 |
+- mpsslog("Could not open /dev/net/tun %s\n", strerror(errno)); |
718 |
+- goto done; |
719 |
+- } |
720 |
+- |
721 |
+- memset(&ifr, 0, sizeof(ifr)); |
722 |
+- |
723 |
+- ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR; |
724 |
+- if (*dev) |
725 |
+- strncpy(ifr.ifr_name, dev, IFNAMSIZ); |
726 |
+- |
727 |
+- err = ioctl(fd, TUNSETIFF, (void *)&ifr); |
728 |
+- if (err < 0) { |
729 |
+- mpsslog("%s %s %d TUNSETIFF failed %s\n", |
730 |
+- mic->name, __func__, __LINE__, strerror(errno)); |
731 |
+- close(fd); |
732 |
+- return err; |
733 |
+- } |
734 |
+-#if GSO_ENABLED |
735 |
+- offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | |
736 |
+- TUN_F_TSO_ECN | TUN_F_UFO; |
737 |
+- |
738 |
+- err = ioctl(fd, TUNSETOFFLOAD, offload); |
739 |
+- if (err < 0) { |
740 |
+- mpsslog("%s %s %d TUNSETOFFLOAD failed %s\n", |
741 |
+- mic->name, __func__, __LINE__, strerror(errno)); |
742 |
+- close(fd); |
743 |
+- return err; |
744 |
+- } |
745 |
+-#endif |
746 |
+- strcpy(dev, ifr.ifr_name); |
747 |
+- mpsslog("Created TAP %s\n", dev); |
748 |
+-done: |
749 |
+- return fd; |
750 |
+-} |
751 |
+- |
752 |
+-#define NET_FD_VIRTIO_NET 0 |
753 |
+-#define NET_FD_TUN 1 |
754 |
+-#define MAX_NET_FD 2 |
755 |
+- |
756 |
+-static void set_dp(struct mic_info *mic, int type, void *dp) |
757 |
+-{ |
758 |
+- switch (type) { |
759 |
+- case VIRTIO_ID_CONSOLE: |
760 |
+- mic->mic_console.console_dp = dp; |
761 |
+- return; |
762 |
+- case VIRTIO_ID_NET: |
763 |
+- mic->mic_net.net_dp = dp; |
764 |
+- return; |
765 |
+- case VIRTIO_ID_BLOCK: |
766 |
+- mic->mic_virtblk.block_dp = dp; |
767 |
+- return; |
768 |
+- } |
769 |
+- mpsslog("%s %s %d not found\n", mic->name, __func__, type); |
770 |
+- assert(0); |
771 |
+-} |
772 |
+- |
773 |
+-static void *get_dp(struct mic_info *mic, int type) |
774 |
+-{ |
775 |
+- switch (type) { |
776 |
+- case VIRTIO_ID_CONSOLE: |
777 |
+- return mic->mic_console.console_dp; |
778 |
+- case VIRTIO_ID_NET: |
779 |
+- return mic->mic_net.net_dp; |
780 |
+- case VIRTIO_ID_BLOCK: |
781 |
+- return mic->mic_virtblk.block_dp; |
782 |
+- } |
783 |
+- mpsslog("%s %s %d not found\n", mic->name, __func__, type); |
784 |
+- assert(0); |
785 |
+- return NULL; |
786 |
+-} |
787 |
+- |
788 |
+-static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type) |
789 |
+-{ |
790 |
+- struct mic_device_desc *d; |
791 |
+- int i; |
792 |
+- void *dp = get_dp(mic, type); |
793 |
+- |
794 |
+- for (i = sizeof(struct mic_bootparam); i < PAGE_SIZE; |
795 |
+- i += mic_total_desc_size(d)) { |
796 |
+- d = dp + i; |
797 |
+- |
798 |
+- /* End of list */ |
799 |
+- if (d->type == 0) |
800 |
+- break; |
801 |
+- |
802 |
+- if (d->type == -1) |
803 |
+- continue; |
804 |
+- |
805 |
+- mpsslog("%s %s d-> type %d d %p\n", |
806 |
+- mic->name, __func__, d->type, d); |
807 |
+- |
808 |
+- if (d->type == (__u8)type) |
809 |
+- return d; |
810 |
+- } |
811 |
+- mpsslog("%s %s %d not found\n", mic->name, __func__, type); |
812 |
+- assert(0); |
813 |
+- return NULL; |
814 |
+-} |
815 |
+- |
816 |
+-/* See comments in vhost.c for explanation of next_desc() */ |
817 |
+-static unsigned next_desc(struct vring_desc *desc) |
818 |
+-{ |
819 |
+- unsigned int next; |
820 |
+- |
821 |
+- if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT)) |
822 |
+- return -1U; |
823 |
+- next = le16toh(desc->next); |
824 |
+- return next; |
825 |
+-} |
826 |
+- |
827 |
+-/* Sum up all the IOVEC length */ |
828 |
+-static ssize_t |
829 |
+-sum_iovec_len(struct mic_copy_desc *copy) |
830 |
+-{ |
831 |
+- ssize_t sum = 0; |
832 |
+- int i; |
833 |
+- |
834 |
+- for (i = 0; i < copy->iovcnt; i++) |
835 |
+- sum += copy->iov[i].iov_len; |
836 |
+- return sum; |
837 |
+-} |
838 |
+- |
839 |
+-static inline void verify_out_len(struct mic_info *mic, |
840 |
+- struct mic_copy_desc *copy) |
841 |
+-{ |
842 |
+- if (copy->out_len != sum_iovec_len(copy)) { |
843 |
+- mpsslog("%s %s %d BUG copy->out_len 0x%x len 0x%zx\n", |
844 |
+- mic->name, __func__, __LINE__, |
845 |
+- copy->out_len, sum_iovec_len(copy)); |
846 |
+- assert(copy->out_len == sum_iovec_len(copy)); |
847 |
+- } |
848 |
+-} |
849 |
+- |
850 |
+-/* Display an iovec */ |
851 |
+-static void |
852 |
+-disp_iovec(struct mic_info *mic, struct mic_copy_desc *copy, |
853 |
+- const char *s, int line) |
854 |
+-{ |
855 |
+- int i; |
856 |
+- |
857 |
+- for (i = 0; i < copy->iovcnt; i++) |
858 |
+- mpsslog("%s %s %d copy->iov[%d] addr %p len 0x%zx\n", |
859 |
+- mic->name, s, line, i, |
860 |
+- copy->iov[i].iov_base, copy->iov[i].iov_len); |
861 |
+-} |
862 |
+- |
863 |
+-static inline __u16 read_avail_idx(struct mic_vring *vr) |
864 |
+-{ |
865 |
+- return ACCESS_ONCE(vr->info->avail_idx); |
866 |
+-} |
867 |
+- |
868 |
+-static inline void txrx_prepare(int type, bool tx, struct mic_vring *vr, |
869 |
+- struct mic_copy_desc *copy, ssize_t len) |
870 |
+-{ |
871 |
+- copy->vr_idx = tx ? 0 : 1; |
872 |
+- copy->update_used = true; |
873 |
+- if (type == VIRTIO_ID_NET) |
874 |
+- copy->iov[1].iov_len = len - sizeof(struct virtio_net_hdr); |
875 |
+- else |
876 |
+- copy->iov[0].iov_len = len; |
877 |
+-} |
878 |
+- |
879 |
+-/* Central API which triggers the copies */ |
880 |
+-static int |
881 |
+-mic_virtio_copy(struct mic_info *mic, int fd, |
882 |
+- struct mic_vring *vr, struct mic_copy_desc *copy) |
883 |
+-{ |
884 |
+- int ret; |
885 |
+- |
886 |
+- ret = ioctl(fd, MIC_VIRTIO_COPY_DESC, copy); |
887 |
+- if (ret) { |
888 |
+- mpsslog("%s %s %d errno %s ret %d\n", |
889 |
+- mic->name, __func__, __LINE__, |
890 |
+- strerror(errno), ret); |
891 |
+- } |
892 |
+- return ret; |
893 |
+-} |
894 |
+- |
895 |
+-/* |
896 |
+- * This initialization routine requires at least one |
897 |
+- * vring i.e. vr0. vr1 is optional. |
898 |
+- */ |
899 |
+-static void * |
900 |
+-init_vr(struct mic_info *mic, int fd, int type, |
901 |
+- struct mic_vring *vr0, struct mic_vring *vr1, int num_vq) |
902 |
+-{ |
903 |
+- int vr_size; |
904 |
+- char *va; |
905 |
+- |
906 |
+- vr_size = PAGE_ALIGN(vring_size(MIC_VRING_ENTRIES, |
907 |
+- MIC_VIRTIO_RING_ALIGN) + sizeof(struct _mic_vring_info)); |
908 |
+- va = mmap(NULL, MIC_DEVICE_PAGE_END + vr_size * num_vq, |
909 |
+- PROT_READ, MAP_SHARED, fd, 0); |
910 |
+- if (MAP_FAILED == va) { |
911 |
+- mpsslog("%s %s %d mmap failed errno %s\n", |
912 |
+- mic->name, __func__, __LINE__, |
913 |
+- strerror(errno)); |
914 |
+- goto done; |
915 |
+- } |
916 |
+- set_dp(mic, type, va); |
917 |
+- vr0->va = (struct mic_vring *)&va[MIC_DEVICE_PAGE_END]; |
918 |
+- vr0->info = vr0->va + |
919 |
+- vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN); |
920 |
+- vring_init(&vr0->vr, |
921 |
+- MIC_VRING_ENTRIES, vr0->va, MIC_VIRTIO_RING_ALIGN); |
922 |
+- mpsslog("%s %s vr0 %p vr0->info %p vr_size 0x%x vring 0x%x ", |
923 |
+- __func__, mic->name, vr0->va, vr0->info, vr_size, |
924 |
+- vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN)); |
925 |
+- mpsslog("magic 0x%x expected 0x%x\n", |
926 |
+- le32toh(vr0->info->magic), MIC_MAGIC + type); |
927 |
+- assert(le32toh(vr0->info->magic) == MIC_MAGIC + type); |
928 |
+- if (vr1) { |
929 |
+- vr1->va = (struct mic_vring *) |
930 |
+- &va[MIC_DEVICE_PAGE_END + vr_size]; |
931 |
+- vr1->info = vr1->va + vring_size(MIC_VRING_ENTRIES, |
932 |
+- MIC_VIRTIO_RING_ALIGN); |
933 |
+- vring_init(&vr1->vr, |
934 |
+- MIC_VRING_ENTRIES, vr1->va, MIC_VIRTIO_RING_ALIGN); |
935 |
+- mpsslog("%s %s vr1 %p vr1->info %p vr_size 0x%x vring 0x%x ", |
936 |
+- __func__, mic->name, vr1->va, vr1->info, vr_size, |
937 |
+- vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN)); |
938 |
+- mpsslog("magic 0x%x expected 0x%x\n", |
939 |
+- le32toh(vr1->info->magic), MIC_MAGIC + type + 1); |
940 |
+- assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1); |
941 |
+- } |
942 |
+-done: |
943 |
+- return va; |
944 |
+-} |
945 |
+- |
946 |
+-static void |
947 |
+-wait_for_card_driver(struct mic_info *mic, int fd, int type) |
948 |
+-{ |
949 |
+- struct pollfd pollfd; |
950 |
+- int err; |
951 |
+- struct mic_device_desc *desc = get_device_desc(mic, type); |
952 |
+- |
953 |
+- pollfd.fd = fd; |
954 |
+- mpsslog("%s %s Waiting .... desc-> type %d status 0x%x\n", |
955 |
+- mic->name, __func__, type, desc->status); |
956 |
+- while (1) { |
957 |
+- pollfd.events = POLLIN; |
958 |
+- pollfd.revents = 0; |
959 |
+- err = poll(&pollfd, 1, -1); |
960 |
+- if (err < 0) { |
961 |
+- mpsslog("%s %s poll failed %s\n", |
962 |
+- mic->name, __func__, strerror(errno)); |
963 |
+- continue; |
964 |
+- } |
965 |
+- |
966 |
+- if (pollfd.revents) { |
967 |
+- mpsslog("%s %s Waiting... desc-> type %d status 0x%x\n", |
968 |
+- mic->name, __func__, type, desc->status); |
969 |
+- if (desc->status & VIRTIO_CONFIG_S_DRIVER_OK) { |
970 |
+- mpsslog("%s %s poll.revents %d\n", |
971 |
+- mic->name, __func__, pollfd.revents); |
972 |
+- mpsslog("%s %s desc-> type %d status 0x%x\n", |
973 |
+- mic->name, __func__, type, |
974 |
+- desc->status); |
975 |
+- break; |
976 |
+- } |
977 |
+- } |
978 |
+- } |
979 |
+-} |
980 |
+- |
981 |
+-/* Spin till we have some descriptors */ |
982 |
+-static void |
983 |
+-spin_for_descriptors(struct mic_info *mic, struct mic_vring *vr) |
984 |
+-{ |
985 |
+- __u16 avail_idx = read_avail_idx(vr); |
986 |
+- |
987 |
+- while (avail_idx == le16toh(ACCESS_ONCE(vr->vr.avail->idx))) { |
988 |
+-#ifdef DEBUG |
989 |
+- mpsslog("%s %s waiting for desc avail %d info_avail %d\n", |
990 |
+- mic->name, __func__, |
991 |
+- le16toh(vr->vr.avail->idx), vr->info->avail_idx); |
992 |
+-#endif |
993 |
+- sched_yield(); |
994 |
+- } |
995 |
+-} |
996 |
+- |
997 |
+-static void * |
998 |
+-virtio_net(void *arg) |
999 |
+-{ |
1000 |
+- static __u8 vnet_hdr[2][sizeof(struct virtio_net_hdr)]; |
1001 |
+- static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __attribute__ ((aligned(64))); |
1002 |
+- struct iovec vnet_iov[2][2] = { |
1003 |
+- { { .iov_base = vnet_hdr[0], .iov_len = sizeof(vnet_hdr[0]) }, |
1004 |
+- { .iov_base = vnet_buf[0], .iov_len = sizeof(vnet_buf[0]) } }, |
1005 |
+- { { .iov_base = vnet_hdr[1], .iov_len = sizeof(vnet_hdr[1]) }, |
1006 |
+- { .iov_base = vnet_buf[1], .iov_len = sizeof(vnet_buf[1]) } }, |
1007 |
+- }; |
1008 |
+- struct iovec *iov0 = vnet_iov[0], *iov1 = vnet_iov[1]; |
1009 |
+- struct mic_info *mic = (struct mic_info *)arg; |
1010 |
+- char if_name[IFNAMSIZ]; |
1011 |
+- struct pollfd net_poll[MAX_NET_FD]; |
1012 |
+- struct mic_vring tx_vr, rx_vr; |
1013 |
+- struct mic_copy_desc copy; |
1014 |
+- struct mic_device_desc *desc; |
1015 |
+- int err; |
1016 |
+- |
1017 |
+- snprintf(if_name, IFNAMSIZ, "mic%d", mic->id); |
1018 |
+- mic->mic_net.tap_fd = tun_alloc(mic, if_name); |
1019 |
+- if (mic->mic_net.tap_fd < 0) |
1020 |
+- goto done; |
1021 |
+- |
1022 |
+- if (tap_configure(mic, if_name)) |
1023 |
+- goto done; |
1024 |
+- mpsslog("MIC name %s id %d\n", mic->name, mic->id); |
1025 |
+- |
1026 |
+- net_poll[NET_FD_VIRTIO_NET].fd = mic->mic_net.virtio_net_fd; |
1027 |
+- net_poll[NET_FD_VIRTIO_NET].events = POLLIN; |
1028 |
+- net_poll[NET_FD_TUN].fd = mic->mic_net.tap_fd; |
1029 |
+- net_poll[NET_FD_TUN].events = POLLIN; |
1030 |
+- |
1031 |
+- if (MAP_FAILED == init_vr(mic, mic->mic_net.virtio_net_fd, |
1032 |
+- VIRTIO_ID_NET, &tx_vr, &rx_vr, |
1033 |
+- virtnet_dev_page.dd.num_vq)) { |
1034 |
+- mpsslog("%s init_vr failed %s\n", |
1035 |
+- mic->name, strerror(errno)); |
1036 |
+- goto done; |
1037 |
+- } |
1038 |
+- |
1039 |
+- copy.iovcnt = 2; |
1040 |
+- desc = get_device_desc(mic, VIRTIO_ID_NET); |
1041 |
+- |
1042 |
+- while (1) { |
1043 |
+- ssize_t len; |
1044 |
+- |
1045 |
+- net_poll[NET_FD_VIRTIO_NET].revents = 0; |
1046 |
+- net_poll[NET_FD_TUN].revents = 0; |
1047 |
+- |
1048 |
+- /* Start polling for data from tap and virtio net */ |
1049 |
+- err = poll(net_poll, 2, -1); |
1050 |
+- if (err < 0) { |
1051 |
+- mpsslog("%s poll failed %s\n", |
1052 |
+- __func__, strerror(errno)); |
1053 |
+- continue; |
1054 |
+- } |
1055 |
+- if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) |
1056 |
+- wait_for_card_driver(mic, mic->mic_net.virtio_net_fd, |
1057 |
+- VIRTIO_ID_NET); |
1058 |
+- /* |
1059 |
+- * Check if there is data to be read from TUN and write to |
1060 |
+- * virtio net fd if there is. |
1061 |
+- */ |
1062 |
+- if (net_poll[NET_FD_TUN].revents & POLLIN) { |
1063 |
+- copy.iov = iov0; |
1064 |
+- len = readv(net_poll[NET_FD_TUN].fd, |
1065 |
+- copy.iov, copy.iovcnt); |
1066 |
+- if (len > 0) { |
1067 |
+- struct virtio_net_hdr *hdr |
1068 |
+- = (struct virtio_net_hdr *)vnet_hdr[0]; |
1069 |
+- |
1070 |
+- /* Disable checksums on the card since we are on |
1071 |
+- a reliable PCIe link */ |
1072 |
+- hdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID; |
1073 |
+-#ifdef DEBUG |
1074 |
+- mpsslog("%s %s %d hdr->flags 0x%x ", mic->name, |
1075 |
+- __func__, __LINE__, hdr->flags); |
1076 |
+- mpsslog("copy.out_len %d hdr->gso_type 0x%x\n", |
1077 |
+- copy.out_len, hdr->gso_type); |
1078 |
+-#endif |
1079 |
+-#ifdef DEBUG |
1080 |
+- disp_iovec(mic, copy, __func__, __LINE__); |
1081 |
+- mpsslog("%s %s %d read from tap 0x%lx\n", |
1082 |
+- mic->name, __func__, __LINE__, |
1083 |
+- len); |
1084 |
+-#endif |
1085 |
+- spin_for_descriptors(mic, &tx_vr); |
1086 |
+- txrx_prepare(VIRTIO_ID_NET, 1, &tx_vr, ©, |
1087 |
+- len); |
1088 |
+- |
1089 |
+- err = mic_virtio_copy(mic, |
1090 |
+- mic->mic_net.virtio_net_fd, &tx_vr, |
1091 |
+- ©); |
1092 |
+- if (err < 0) { |
1093 |
+- mpsslog("%s %s %d mic_virtio_copy %s\n", |
1094 |
+- mic->name, __func__, __LINE__, |
1095 |
+- strerror(errno)); |
1096 |
+- } |
1097 |
+- if (!err) |
1098 |
+- verify_out_len(mic, ©); |
1099 |
+-#ifdef DEBUG |
1100 |
+- disp_iovec(mic, copy, __func__, __LINE__); |
1101 |
+- mpsslog("%s %s %d wrote to net 0x%lx\n", |
1102 |
+- mic->name, __func__, __LINE__, |
1103 |
+- sum_iovec_len(©)); |
1104 |
+-#endif |
1105 |
+- /* Reinitialize IOV for next run */ |
1106 |
+- iov0[1].iov_len = MAX_NET_PKT_SIZE; |
1107 |
+- } else if (len < 0) { |
1108 |
+- disp_iovec(mic, ©, __func__, __LINE__); |
1109 |
+- mpsslog("%s %s %d read failed %s ", mic->name, |
1110 |
+- __func__, __LINE__, strerror(errno)); |
1111 |
+- mpsslog("cnt %d sum %zd\n", |
1112 |
+- copy.iovcnt, sum_iovec_len(©)); |
1113 |
+- } |
1114 |
+- } |
1115 |
+- |
1116 |
+- /* |
1117 |
+- * Check if there is data to be read from virtio net and |
1118 |
+- * write to TUN if there is. |
1119 |
+- */ |
1120 |
+- if (net_poll[NET_FD_VIRTIO_NET].revents & POLLIN) { |
1121 |
+- while (rx_vr.info->avail_idx != |
1122 |
+- le16toh(rx_vr.vr.avail->idx)) { |
1123 |
+- copy.iov = iov1; |
1124 |
+- txrx_prepare(VIRTIO_ID_NET, 0, &rx_vr, ©, |
1125 |
+- MAX_NET_PKT_SIZE |
1126 |
+- + sizeof(struct virtio_net_hdr)); |
1127 |
+- |
1128 |
+- err = mic_virtio_copy(mic, |
1129 |
+- mic->mic_net.virtio_net_fd, &rx_vr, |
1130 |
+- ©); |
1131 |
+- if (!err) { |
1132 |
+-#ifdef DEBUG |
1133 |
+- struct virtio_net_hdr *hdr |
1134 |
+- = (struct virtio_net_hdr *) |
1135 |
+- vnet_hdr[1]; |
1136 |
+- |
1137 |
+- mpsslog("%s %s %d hdr->flags 0x%x, ", |
1138 |
+- mic->name, __func__, __LINE__, |
1139 |
+- hdr->flags); |
1140 |
+- mpsslog("out_len %d gso_type 0x%x\n", |
1141 |
+- copy.out_len, |
1142 |
+- hdr->gso_type); |
1143 |
+-#endif |
1144 |
+- /* Set the correct output iov_len */ |
1145 |
+- iov1[1].iov_len = copy.out_len - |
1146 |
+- sizeof(struct virtio_net_hdr); |
1147 |
+- verify_out_len(mic, ©); |
1148 |
+-#ifdef DEBUG |
1149 |
+- disp_iovec(mic, copy, __func__, |
1150 |
+- __LINE__); |
1151 |
+- mpsslog("%s %s %d ", |
1152 |
+- mic->name, __func__, __LINE__); |
1153 |
+- mpsslog("read from net 0x%lx\n", |
1154 |
+- sum_iovec_len(copy)); |
1155 |
+-#endif |
1156 |
+- len = writev(net_poll[NET_FD_TUN].fd, |
1157 |
+- copy.iov, copy.iovcnt); |
1158 |
+- if (len != sum_iovec_len(©)) { |
1159 |
+- mpsslog("Tun write failed %s ", |
1160 |
+- strerror(errno)); |
1161 |
+- mpsslog("len 0x%zx ", len); |
1162 |
+- mpsslog("read_len 0x%zx\n", |
1163 |
+- sum_iovec_len(©)); |
1164 |
+- } else { |
1165 |
+-#ifdef DEBUG |
1166 |
+- disp_iovec(mic, ©, __func__, |
1167 |
+- __LINE__); |
1168 |
+- mpsslog("%s %s %d ", |
1169 |
+- mic->name, __func__, |
1170 |
+- __LINE__); |
1171 |
+- mpsslog("wrote to tap 0x%lx\n", |
1172 |
+- len); |
1173 |
+-#endif |
1174 |
+- } |
1175 |
+- } else { |
1176 |
+- mpsslog("%s %s %d mic_virtio_copy %s\n", |
1177 |
+- mic->name, __func__, __LINE__, |
1178 |
+- strerror(errno)); |
1179 |
+- break; |
1180 |
+- } |
1181 |
+- } |
1182 |
+- } |
1183 |
+- if (net_poll[NET_FD_VIRTIO_NET].revents & POLLERR) |
1184 |
+- mpsslog("%s: %s: POLLERR\n", __func__, mic->name); |
1185 |
+- } |
1186 |
+-done: |
1187 |
+- pthread_exit(NULL); |
1188 |
+-} |
1189 |
+- |
1190 |
+-/* virtio_console */ |
1191 |
+-#define VIRTIO_CONSOLE_FD 0 |
1192 |
+-#define MONITOR_FD (VIRTIO_CONSOLE_FD + 1) |
1193 |
+-#define MAX_CONSOLE_FD (MONITOR_FD + 1) /* must be the last one + 1 */ |
1194 |
+-#define MAX_BUFFER_SIZE PAGE_SIZE |
1195 |
+- |
1196 |
+-static void * |
1197 |
+-virtio_console(void *arg) |
1198 |
+-{ |
1199 |
+- static __u8 vcons_buf[2][PAGE_SIZE]; |
1200 |
+- struct iovec vcons_iov[2] = { |
1201 |
+- { .iov_base = vcons_buf[0], .iov_len = sizeof(vcons_buf[0]) }, |
1202 |
+- { .iov_base = vcons_buf[1], .iov_len = sizeof(vcons_buf[1]) }, |
1203 |
+- }; |
1204 |
+- struct iovec *iov0 = &vcons_iov[0], *iov1 = &vcons_iov[1]; |
1205 |
+- struct mic_info *mic = (struct mic_info *)arg; |
1206 |
+- int err; |
1207 |
+- struct pollfd console_poll[MAX_CONSOLE_FD]; |
1208 |
+- int pty_fd; |
1209 |
+- char *pts_name; |
1210 |
+- ssize_t len; |
1211 |
+- struct mic_vring tx_vr, rx_vr; |
1212 |
+- struct mic_copy_desc copy; |
1213 |
+- struct mic_device_desc *desc; |
1214 |
+- |
1215 |
+- pty_fd = posix_openpt(O_RDWR); |
1216 |
+- if (pty_fd < 0) { |
1217 |
+- mpsslog("can't open a pseudoterminal master device: %s\n", |
1218 |
+- strerror(errno)); |
1219 |
+- goto _return; |
1220 |
+- } |
1221 |
+- pts_name = ptsname(pty_fd); |
1222 |
+- if (pts_name == NULL) { |
1223 |
+- mpsslog("can't get pts name\n"); |
1224 |
+- goto _close_pty; |
1225 |
+- } |
1226 |
+- printf("%s console message goes to %s\n", mic->name, pts_name); |
1227 |
+- mpsslog("%s console message goes to %s\n", mic->name, pts_name); |
1228 |
+- err = grantpt(pty_fd); |
1229 |
+- if (err < 0) { |
1230 |
+- mpsslog("can't grant access: %s %s\n", |
1231 |
+- pts_name, strerror(errno)); |
1232 |
+- goto _close_pty; |
1233 |
+- } |
1234 |
+- err = unlockpt(pty_fd); |
1235 |
+- if (err < 0) { |
1236 |
+- mpsslog("can't unlock a pseudoterminal: %s %s\n", |
1237 |
+- pts_name, strerror(errno)); |
1238 |
+- goto _close_pty; |
1239 |
+- } |
1240 |
+- console_poll[MONITOR_FD].fd = pty_fd; |
1241 |
+- console_poll[MONITOR_FD].events = POLLIN; |
1242 |
+- |
1243 |
+- console_poll[VIRTIO_CONSOLE_FD].fd = mic->mic_console.virtio_console_fd; |
1244 |
+- console_poll[VIRTIO_CONSOLE_FD].events = POLLIN; |
1245 |
+- |
1246 |
+- if (MAP_FAILED == init_vr(mic, mic->mic_console.virtio_console_fd, |
1247 |
+- VIRTIO_ID_CONSOLE, &tx_vr, &rx_vr, |
1248 |
+- virtcons_dev_page.dd.num_vq)) { |
1249 |
+- mpsslog("%s init_vr failed %s\n", |
1250 |
+- mic->name, strerror(errno)); |
1251 |
+- goto _close_pty; |
1252 |
+- } |
1253 |
+- |
1254 |
+- copy.iovcnt = 1; |
1255 |
+- desc = get_device_desc(mic, VIRTIO_ID_CONSOLE); |
1256 |
+- |
1257 |
+- for (;;) { |
1258 |
+- console_poll[MONITOR_FD].revents = 0; |
1259 |
+- console_poll[VIRTIO_CONSOLE_FD].revents = 0; |
1260 |
+- err = poll(console_poll, MAX_CONSOLE_FD, -1); |
1261 |
+- if (err < 0) { |
1262 |
+- mpsslog("%s %d: poll failed: %s\n", __func__, __LINE__, |
1263 |
+- strerror(errno)); |
1264 |
+- continue; |
1265 |
+- } |
1266 |
+- if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) |
1267 |
+- wait_for_card_driver(mic, |
1268 |
+- mic->mic_console.virtio_console_fd, |
1269 |
+- VIRTIO_ID_CONSOLE); |
1270 |
+- |
1271 |
+- if (console_poll[MONITOR_FD].revents & POLLIN) { |
1272 |
+- copy.iov = iov0; |
1273 |
+- len = readv(pty_fd, copy.iov, copy.iovcnt); |
1274 |
+- if (len > 0) { |
1275 |
+-#ifdef DEBUG |
1276 |
+- disp_iovec(mic, copy, __func__, __LINE__); |
1277 |
+- mpsslog("%s %s %d read from tap 0x%lx\n", |
1278 |
+- mic->name, __func__, __LINE__, |
1279 |
+- len); |
1280 |
+-#endif |
1281 |
+- spin_for_descriptors(mic, &tx_vr); |
1282 |
+- txrx_prepare(VIRTIO_ID_CONSOLE, 1, &tx_vr, |
1283 |
+- ©, len); |
1284 |
+- |
1285 |
+- err = mic_virtio_copy(mic, |
1286 |
+- mic->mic_console.virtio_console_fd, |
1287 |
+- &tx_vr, ©); |
1288 |
+- if (err < 0) { |
1289 |
+- mpsslog("%s %s %d mic_virtio_copy %s\n", |
1290 |
+- mic->name, __func__, __LINE__, |
1291 |
+- strerror(errno)); |
1292 |
+- } |
1293 |
+- if (!err) |
1294 |
+- verify_out_len(mic, ©); |
1295 |
+-#ifdef DEBUG |
1296 |
+- disp_iovec(mic, copy, __func__, __LINE__); |
1297 |
+- mpsslog("%s %s %d wrote to net 0x%lx\n", |
1298 |
+- mic->name, __func__, __LINE__, |
1299 |
+- sum_iovec_len(copy)); |
1300 |
+-#endif |
1301 |
+- /* Reinitialize IOV for next run */ |
1302 |
+- iov0->iov_len = PAGE_SIZE; |
1303 |
+- } else if (len < 0) { |
1304 |
+- disp_iovec(mic, ©, __func__, __LINE__); |
1305 |
+- mpsslog("%s %s %d read failed %s ", |
1306 |
+- mic->name, __func__, __LINE__, |
1307 |
+- strerror(errno)); |
1308 |
+- mpsslog("cnt %d sum %zd\n", |
1309 |
+- copy.iovcnt, sum_iovec_len(©)); |
1310 |
+- } |
1311 |
+- } |
1312 |
+- |
1313 |
+- if (console_poll[VIRTIO_CONSOLE_FD].revents & POLLIN) { |
1314 |
+- while (rx_vr.info->avail_idx != |
1315 |
+- le16toh(rx_vr.vr.avail->idx)) { |
1316 |
+- copy.iov = iov1; |
1317 |
+- txrx_prepare(VIRTIO_ID_CONSOLE, 0, &rx_vr, |
1318 |
+- ©, PAGE_SIZE); |
1319 |
+- |
1320 |
+- err = mic_virtio_copy(mic, |
1321 |
+- mic->mic_console.virtio_console_fd, |
1322 |
+- &rx_vr, ©); |
1323 |
+- if (!err) { |
1324 |
+- /* Set the correct output iov_len */ |
1325 |
+- iov1->iov_len = copy.out_len; |
1326 |
+- verify_out_len(mic, ©); |
1327 |
+-#ifdef DEBUG |
1328 |
+- disp_iovec(mic, copy, __func__, |
1329 |
+- __LINE__); |
1330 |
+- mpsslog("%s %s %d ", |
1331 |
+- mic->name, __func__, __LINE__); |
1332 |
+- mpsslog("read from net 0x%lx\n", |
1333 |
+- sum_iovec_len(copy)); |
1334 |
+-#endif |
1335 |
+- len = writev(pty_fd, |
1336 |
+- copy.iov, copy.iovcnt); |
1337 |
+- if (len != sum_iovec_len(©)) { |
1338 |
+- mpsslog("Tun write failed %s ", |
1339 |
+- strerror(errno)); |
1340 |
+- mpsslog("len 0x%zx ", len); |
1341 |
+- mpsslog("read_len 0x%zx\n", |
1342 |
+- sum_iovec_len(©)); |
1343 |
+- } else { |
1344 |
+-#ifdef DEBUG |
1345 |
+- disp_iovec(mic, copy, __func__, |
1346 |
+- __LINE__); |
1347 |
+- mpsslog("%s %s %d ", |
1348 |
+- mic->name, __func__, |
1349 |
+- __LINE__); |
1350 |
+- mpsslog("wrote to tap 0x%lx\n", |
1351 |
+- len); |
1352 |
+-#endif |
1353 |
+- } |
1354 |
+- } else { |
1355 |
+- mpsslog("%s %s %d mic_virtio_copy %s\n", |
1356 |
+- mic->name, __func__, __LINE__, |
1357 |
+- strerror(errno)); |
1358 |
+- break; |
1359 |
+- } |
1360 |
+- } |
1361 |
+- } |
1362 |
+- if (console_poll[NET_FD_VIRTIO_NET].revents & POLLERR) |
1363 |
+- mpsslog("%s: %s: POLLERR\n", __func__, mic->name); |
1364 |
+- } |
1365 |
+-_close_pty: |
1366 |
+- close(pty_fd); |
1367 |
+-_return: |
1368 |
+- pthread_exit(NULL); |
1369 |
+-} |
1370 |
+- |
1371 |
+-static void |
1372 |
+-add_virtio_device(struct mic_info *mic, struct mic_device_desc *dd) |
1373 |
+-{ |
1374 |
+- char path[PATH_MAX]; |
1375 |
+- int fd, err; |
1376 |
+- |
1377 |
+- snprintf(path, PATH_MAX, "/dev/mic%d", mic->id); |
1378 |
+- fd = open(path, O_RDWR); |
1379 |
+- if (fd < 0) { |
1380 |
+- mpsslog("Could not open %s %s\n", path, strerror(errno)); |
1381 |
+- return; |
1382 |
+- } |
1383 |
+- |
1384 |
+- err = ioctl(fd, MIC_VIRTIO_ADD_DEVICE, dd); |
1385 |
+- if (err < 0) { |
1386 |
+- mpsslog("Could not add %d %s\n", dd->type, strerror(errno)); |
1387 |
+- close(fd); |
1388 |
+- return; |
1389 |
+- } |
1390 |
+- switch (dd->type) { |
1391 |
+- case VIRTIO_ID_NET: |
1392 |
+- mic->mic_net.virtio_net_fd = fd; |
1393 |
+- mpsslog("Added VIRTIO_ID_NET for %s\n", mic->name); |
1394 |
+- break; |
1395 |
+- case VIRTIO_ID_CONSOLE: |
1396 |
+- mic->mic_console.virtio_console_fd = fd; |
1397 |
+- mpsslog("Added VIRTIO_ID_CONSOLE for %s\n", mic->name); |
1398 |
+- break; |
1399 |
+- case VIRTIO_ID_BLOCK: |
1400 |
+- mic->mic_virtblk.virtio_block_fd = fd; |
1401 |
+- mpsslog("Added VIRTIO_ID_BLOCK for %s\n", mic->name); |
1402 |
+- break; |
1403 |
+- } |
1404 |
+-} |
1405 |
+- |
1406 |
+-static bool |
1407 |
+-set_backend_file(struct mic_info *mic) |
1408 |
+-{ |
1409 |
+- FILE *config; |
1410 |
+- char buff[PATH_MAX], *line, *evv, *p; |
1411 |
+- |
1412 |
+- snprintf(buff, PATH_MAX, "%s/mpssd%03d.conf", mic_config_dir, mic->id); |
1413 |
+- config = fopen(buff, "r"); |
1414 |
+- if (config == NULL) |
1415 |
+- return false; |
1416 |
+- do { /* look for "virtblk_backend=XXXX" */ |
1417 |
+- line = fgets(buff, PATH_MAX, config); |
1418 |
+- if (line == NULL) |
1419 |
+- break; |
1420 |
+- if (*line == '#') |
1421 |
+- continue; |
1422 |
+- p = strchr(line, '\n'); |
1423 |
+- if (p) |
1424 |
+- *p = '\0'; |
1425 |
+- } while (strncmp(line, virtblk_backend, strlen(virtblk_backend)) != 0); |
1426 |
+- fclose(config); |
1427 |
+- if (line == NULL) |
1428 |
+- return false; |
1429 |
+- evv = strchr(line, '='); |
1430 |
+- if (evv == NULL) |
1431 |
+- return false; |
1432 |
+- mic->mic_virtblk.backend_file = malloc(strlen(evv) + 1); |
1433 |
+- if (mic->mic_virtblk.backend_file == NULL) { |
1434 |
+- mpsslog("%s %d can't allocate memory\n", mic->name, mic->id); |
1435 |
+- return false; |
1436 |
+- } |
1437 |
+- strcpy(mic->mic_virtblk.backend_file, evv + 1); |
1438 |
+- return true; |
1439 |
+-} |
1440 |
+- |
1441 |
+-#define SECTOR_SIZE 512 |
1442 |
+-static bool |
1443 |
+-set_backend_size(struct mic_info *mic) |
1444 |
+-{ |
1445 |
+- mic->mic_virtblk.backend_size = lseek(mic->mic_virtblk.backend, 0, |
1446 |
+- SEEK_END); |
1447 |
+- if (mic->mic_virtblk.backend_size < 0) { |
1448 |
+- mpsslog("%s: can't seek: %s\n", |
1449 |
+- mic->name, mic->mic_virtblk.backend_file); |
1450 |
+- return false; |
1451 |
+- } |
1452 |
+- virtblk_dev_page.blk_config.capacity = |
1453 |
+- mic->mic_virtblk.backend_size / SECTOR_SIZE; |
1454 |
+- if ((mic->mic_virtblk.backend_size % SECTOR_SIZE) != 0) |
1455 |
+- virtblk_dev_page.blk_config.capacity++; |
1456 |
+- |
1457 |
+- virtblk_dev_page.blk_config.capacity = |
1458 |
+- htole64(virtblk_dev_page.blk_config.capacity); |
1459 |
+- |
1460 |
+- return true; |
1461 |
+-} |
1462 |
+- |
1463 |
+-static bool |
1464 |
+-open_backend(struct mic_info *mic) |
1465 |
+-{ |
1466 |
+- if (!set_backend_file(mic)) |
1467 |
+- goto _error_exit; |
1468 |
+- mic->mic_virtblk.backend = open(mic->mic_virtblk.backend_file, O_RDWR); |
1469 |
+- if (mic->mic_virtblk.backend < 0) { |
1470 |
+- mpsslog("%s: can't open: %s\n", mic->name, |
1471 |
+- mic->mic_virtblk.backend_file); |
1472 |
+- goto _error_free; |
1473 |
+- } |
1474 |
+- if (!set_backend_size(mic)) |
1475 |
+- goto _error_close; |
1476 |
+- mic->mic_virtblk.backend_addr = mmap(NULL, |
1477 |
+- mic->mic_virtblk.backend_size, |
1478 |
+- PROT_READ|PROT_WRITE, MAP_SHARED, |
1479 |
+- mic->mic_virtblk.backend, 0L); |
1480 |
+- if (mic->mic_virtblk.backend_addr == MAP_FAILED) { |
1481 |
+- mpsslog("%s: can't map: %s %s\n", |
1482 |
+- mic->name, mic->mic_virtblk.backend_file, |
1483 |
+- strerror(errno)); |
1484 |
+- goto _error_close; |
1485 |
+- } |
1486 |
+- return true; |
1487 |
+- |
1488 |
+- _error_close: |
1489 |
+- close(mic->mic_virtblk.backend); |
1490 |
+- _error_free: |
1491 |
+- free(mic->mic_virtblk.backend_file); |
1492 |
+- _error_exit: |
1493 |
+- return false; |
1494 |
+-} |
1495 |
+- |
1496 |
+-static void |
1497 |
+-close_backend(struct mic_info *mic) |
1498 |
+-{ |
1499 |
+- munmap(mic->mic_virtblk.backend_addr, mic->mic_virtblk.backend_size); |
1500 |
+- close(mic->mic_virtblk.backend); |
1501 |
+- free(mic->mic_virtblk.backend_file); |
1502 |
+-} |
1503 |
+- |
1504 |
+-static bool |
1505 |
+-start_virtblk(struct mic_info *mic, struct mic_vring *vring) |
1506 |
+-{ |
1507 |
+- if (((unsigned long)&virtblk_dev_page.blk_config % 8) != 0) { |
1508 |
+- mpsslog("%s: blk_config is not 8 byte aligned.\n", |
1509 |
+- mic->name); |
1510 |
+- return false; |
1511 |
+- } |
1512 |
+- add_virtio_device(mic, &virtblk_dev_page.dd); |
1513 |
+- if (MAP_FAILED == init_vr(mic, mic->mic_virtblk.virtio_block_fd, |
1514 |
+- VIRTIO_ID_BLOCK, vring, NULL, |
1515 |
+- virtblk_dev_page.dd.num_vq)) { |
1516 |
+- mpsslog("%s init_vr failed %s\n", |
1517 |
+- mic->name, strerror(errno)); |
1518 |
+- return false; |
1519 |
+- } |
1520 |
+- return true; |
1521 |
+-} |
1522 |
+- |
1523 |
+-static void |
1524 |
+-stop_virtblk(struct mic_info *mic) |
1525 |
+-{ |
1526 |
+- int vr_size, ret; |
1527 |
+- |
1528 |
+- vr_size = PAGE_ALIGN(vring_size(MIC_VRING_ENTRIES, |
1529 |
+- MIC_VIRTIO_RING_ALIGN) + sizeof(struct _mic_vring_info)); |
1530 |
+- ret = munmap(mic->mic_virtblk.block_dp, |
1531 |
+- MIC_DEVICE_PAGE_END + vr_size * virtblk_dev_page.dd.num_vq); |
1532 |
+- if (ret < 0) |
1533 |
+- mpsslog("%s munmap errno %d\n", mic->name, errno); |
1534 |
+- close(mic->mic_virtblk.virtio_block_fd); |
1535 |
+-} |
1536 |
+- |
1537 |
+-static __u8 |
1538 |
+-header_error_check(struct vring_desc *desc) |
1539 |
+-{ |
1540 |
+- if (le32toh(desc->len) != sizeof(struct virtio_blk_outhdr)) { |
1541 |
+- mpsslog("%s() %d: length is not sizeof(virtio_blk_outhd)\n", |
1542 |
+- __func__, __LINE__); |
1543 |
+- return -EIO; |
1544 |
+- } |
1545 |
+- if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT)) { |
1546 |
+- mpsslog("%s() %d: alone\n", |
1547 |
+- __func__, __LINE__); |
1548 |
+- return -EIO; |
1549 |
+- } |
1550 |
+- if (le16toh(desc->flags) & VRING_DESC_F_WRITE) { |
1551 |
+- mpsslog("%s() %d: not read\n", |
1552 |
+- __func__, __LINE__); |
1553 |
+- return -EIO; |
1554 |
+- } |
1555 |
+- return 0; |
1556 |
+-} |
1557 |
+- |
1558 |
+-static int |
1559 |
+-read_header(int fd, struct virtio_blk_outhdr *hdr, __u32 desc_idx) |
1560 |
+-{ |
1561 |
+- struct iovec iovec; |
1562 |
+- struct mic_copy_desc copy; |
1563 |
+- |
1564 |
+- iovec.iov_len = sizeof(*hdr); |
1565 |
+- iovec.iov_base = hdr; |
1566 |
+- copy.iov = &iovec; |
1567 |
+- copy.iovcnt = 1; |
1568 |
+- copy.vr_idx = 0; /* only one vring on virtio_block */ |
1569 |
+- copy.update_used = false; /* do not update used index */ |
1570 |
+- return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
1571 |
+-} |
1572 |
+- |
1573 |
+-static int |
1574 |
+-transfer_blocks(int fd, struct iovec *iovec, __u32 iovcnt) |
1575 |
+-{ |
1576 |
+- struct mic_copy_desc copy; |
1577 |
+- |
1578 |
+- copy.iov = iovec; |
1579 |
+- copy.iovcnt = iovcnt; |
1580 |
+- copy.vr_idx = 0; /* only one vring on virtio_block */ |
1581 |
+- copy.update_used = false; /* do not update used index */ |
1582 |
+- return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
1583 |
+-} |
1584 |
+- |
1585 |
+-static __u8 |
1586 |
+-status_error_check(struct vring_desc *desc) |
1587 |
+-{ |
1588 |
+- if (le32toh(desc->len) != sizeof(__u8)) { |
1589 |
+- mpsslog("%s() %d: length is not sizeof(status)\n", |
1590 |
+- __func__, __LINE__); |
1591 |
+- return -EIO; |
1592 |
+- } |
1593 |
+- return 0; |
1594 |
+-} |
1595 |
+- |
1596 |
+-static int |
1597 |
+-write_status(int fd, __u8 *status) |
1598 |
+-{ |
1599 |
+- struct iovec iovec; |
1600 |
+- struct mic_copy_desc copy; |
1601 |
+- |
1602 |
+- iovec.iov_base = status; |
1603 |
+- iovec.iov_len = sizeof(*status); |
1604 |
+- copy.iov = &iovec; |
1605 |
+- copy.iovcnt = 1; |
1606 |
+- copy.vr_idx = 0; /* only one vring on virtio_block */ |
1607 |
+- copy.update_used = true; /* Update used index */ |
1608 |
+- return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
1609 |
+-} |
1610 |
+- |
1611 |
+-static void * |
1612 |
+-virtio_block(void *arg) |
1613 |
+-{ |
1614 |
+- struct mic_info *mic = (struct mic_info *)arg; |
1615 |
+- int ret; |
1616 |
+- struct pollfd block_poll; |
1617 |
+- struct mic_vring vring; |
1618 |
+- __u16 avail_idx; |
1619 |
+- __u32 desc_idx; |
1620 |
+- struct vring_desc *desc; |
1621 |
+- struct iovec *iovec, *piov; |
1622 |
+- __u8 status; |
1623 |
+- __u32 buffer_desc_idx; |
1624 |
+- struct virtio_blk_outhdr hdr; |
1625 |
+- void *fos; |
1626 |
+- |
1627 |
+- for (;;) { /* forever */ |
1628 |
+- if (!open_backend(mic)) { /* No virtblk */ |
1629 |
+- for (mic->mic_virtblk.signaled = 0; |
1630 |
+- !mic->mic_virtblk.signaled;) |
1631 |
+- sleep(1); |
1632 |
+- continue; |
1633 |
+- } |
1634 |
+- |
1635 |
+- /* backend file is specified. */ |
1636 |
+- if (!start_virtblk(mic, &vring)) |
1637 |
+- goto _close_backend; |
1638 |
+- iovec = malloc(sizeof(*iovec) * |
1639 |
+- le32toh(virtblk_dev_page.blk_config.seg_max)); |
1640 |
+- if (!iovec) { |
1641 |
+- mpsslog("%s: can't alloc iovec: %s\n", |
1642 |
+- mic->name, strerror(ENOMEM)); |
1643 |
+- goto _stop_virtblk; |
1644 |
+- } |
1645 |
+- |
1646 |
+- block_poll.fd = mic->mic_virtblk.virtio_block_fd; |
1647 |
+- block_poll.events = POLLIN; |
1648 |
+- for (mic->mic_virtblk.signaled = 0; |
1649 |
+- !mic->mic_virtblk.signaled;) { |
1650 |
+- block_poll.revents = 0; |
1651 |
+- /* timeout in 1 sec to see signaled */ |
1652 |
+- ret = poll(&block_poll, 1, 1000); |
1653 |
+- if (ret < 0) { |
1654 |
+- mpsslog("%s %d: poll failed: %s\n", |
1655 |
+- __func__, __LINE__, |
1656 |
+- strerror(errno)); |
1657 |
+- continue; |
1658 |
+- } |
1659 |
+- |
1660 |
+- if (!(block_poll.revents & POLLIN)) { |
1661 |
+-#ifdef DEBUG |
1662 |
+- mpsslog("%s %d: block_poll.revents=0x%x\n", |
1663 |
+- __func__, __LINE__, block_poll.revents); |
1664 |
+-#endif |
1665 |
+- continue; |
1666 |
+- } |
1667 |
+- |
1668 |
+- /* POLLIN */ |
1669 |
+- while (vring.info->avail_idx != |
1670 |
+- le16toh(vring.vr.avail->idx)) { |
1671 |
+- /* read header element */ |
1672 |
+- avail_idx = |
1673 |
+- vring.info->avail_idx & |
1674 |
+- (vring.vr.num - 1); |
1675 |
+- desc_idx = le16toh( |
1676 |
+- vring.vr.avail->ring[avail_idx]); |
1677 |
+- desc = &vring.vr.desc[desc_idx]; |
1678 |
+-#ifdef DEBUG |
1679 |
+- mpsslog("%s() %d: avail_idx=%d ", |
1680 |
+- __func__, __LINE__, |
1681 |
+- vring.info->avail_idx); |
1682 |
+- mpsslog("vring.vr.num=%d desc=%p\n", |
1683 |
+- vring.vr.num, desc); |
1684 |
+-#endif |
1685 |
+- status = header_error_check(desc); |
1686 |
+- ret = read_header( |
1687 |
+- mic->mic_virtblk.virtio_block_fd, |
1688 |
+- &hdr, desc_idx); |
1689 |
+- if (ret < 0) { |
1690 |
+- mpsslog("%s() %d %s: ret=%d %s\n", |
1691 |
+- __func__, __LINE__, |
1692 |
+- mic->name, ret, |
1693 |
+- strerror(errno)); |
1694 |
+- break; |
1695 |
+- } |
1696 |
+- /* buffer element */ |
1697 |
+- piov = iovec; |
1698 |
+- status = 0; |
1699 |
+- fos = mic->mic_virtblk.backend_addr + |
1700 |
+- (hdr.sector * SECTOR_SIZE); |
1701 |
+- buffer_desc_idx = next_desc(desc); |
1702 |
+- desc_idx = buffer_desc_idx; |
1703 |
+- for (desc = &vring.vr.desc[buffer_desc_idx]; |
1704 |
+- desc->flags & VRING_DESC_F_NEXT; |
1705 |
+- desc_idx = next_desc(desc), |
1706 |
+- desc = &vring.vr.desc[desc_idx]) { |
1707 |
+- piov->iov_len = desc->len; |
1708 |
+- piov->iov_base = fos; |
1709 |
+- piov++; |
1710 |
+- fos += desc->len; |
1711 |
+- } |
1712 |
+- /* Returning NULLs for VIRTIO_BLK_T_GET_ID. */ |
1713 |
+- if (hdr.type & ~(VIRTIO_BLK_T_OUT | |
1714 |
+- VIRTIO_BLK_T_GET_ID)) { |
1715 |
+- /* |
1716 |
+- VIRTIO_BLK_T_IN - does not do |
1717 |
+- anything. Probably for documenting. |
1718 |
+- VIRTIO_BLK_T_SCSI_CMD - for |
1719 |
+- virtio_scsi. |
1720 |
+- VIRTIO_BLK_T_FLUSH - turned off in |
1721 |
+- config space. |
1722 |
+- VIRTIO_BLK_T_BARRIER - defined but not |
1723 |
+- used in anywhere. |
1724 |
+- */ |
1725 |
+- mpsslog("%s() %d: type %x ", |
1726 |
+- __func__, __LINE__, |
1727 |
+- hdr.type); |
1728 |
+- mpsslog("is not supported\n"); |
1729 |
+- status = -ENOTSUP; |
1730 |
+- |
1731 |
+- } else { |
1732 |
+- ret = transfer_blocks( |
1733 |
+- mic->mic_virtblk.virtio_block_fd, |
1734 |
+- iovec, |
1735 |
+- piov - iovec); |
1736 |
+- if (ret < 0 && |
1737 |
+- status != 0) |
1738 |
+- status = ret; |
1739 |
+- } |
1740 |
+- /* write status and update used pointer */ |
1741 |
+- if (status != 0) |
1742 |
+- status = status_error_check(desc); |
1743 |
+- ret = write_status( |
1744 |
+- mic->mic_virtblk.virtio_block_fd, |
1745 |
+- &status); |
1746 |
+-#ifdef DEBUG |
1747 |
+- mpsslog("%s() %d: write status=%d on desc=%p\n", |
1748 |
+- __func__, __LINE__, |
1749 |
+- status, desc); |
1750 |
+-#endif |
1751 |
+- } |
1752 |
+- } |
1753 |
+- free(iovec); |
1754 |
+-_stop_virtblk: |
1755 |
+- stop_virtblk(mic); |
1756 |
+-_close_backend: |
1757 |
+- close_backend(mic); |
1758 |
+- } /* forever */ |
1759 |
+- |
1760 |
+- pthread_exit(NULL); |
1761 |
+-} |
1762 |
+- |
1763 |
+-static void |
1764 |
+-reset(struct mic_info *mic) |
1765 |
+-{ |
1766 |
+-#define RESET_TIMEOUT 120 |
1767 |
+- int i = RESET_TIMEOUT; |
1768 |
+- setsysfs(mic->name, "state", "reset"); |
1769 |
+- while (i) { |
1770 |
+- char *state; |
1771 |
+- state = readsysfs(mic->name, "state"); |
1772 |
+- if (!state) |
1773 |
+- goto retry; |
1774 |
+- mpsslog("%s: %s %d state %s\n", |
1775 |
+- mic->name, __func__, __LINE__, state); |
1776 |
+- |
1777 |
+- /* |
1778 |
+- * If the shutdown was initiated by OSPM, the state stays |
1779 |
+- * in "suspended" which is also a valid condition for reset. |
1780 |
+- */ |
1781 |
+- if ((!strcmp(state, "offline")) || |
1782 |
+- (!strcmp(state, "suspended"))) { |
1783 |
+- free(state); |
1784 |
+- break; |
1785 |
+- } |
1786 |
+- free(state); |
1787 |
+-retry: |
1788 |
+- sleep(1); |
1789 |
+- i--; |
1790 |
+- } |
1791 |
+-} |
1792 |
+- |
1793 |
+-static int |
1794 |
+-get_mic_shutdown_status(struct mic_info *mic, char *shutdown_status) |
1795 |
+-{ |
1796 |
+- if (!strcmp(shutdown_status, "nop")) |
1797 |
+- return MIC_NOP; |
1798 |
+- if (!strcmp(shutdown_status, "crashed")) |
1799 |
+- return MIC_CRASHED; |
1800 |
+- if (!strcmp(shutdown_status, "halted")) |
1801 |
+- return MIC_HALTED; |
1802 |
+- if (!strcmp(shutdown_status, "poweroff")) |
1803 |
+- return MIC_POWER_OFF; |
1804 |
+- if (!strcmp(shutdown_status, "restart")) |
1805 |
+- return MIC_RESTART; |
1806 |
+- mpsslog("%s: BUG invalid status %s\n", mic->name, shutdown_status); |
1807 |
+- /* Invalid state */ |
1808 |
+- assert(0); |
1809 |
+-}; |
1810 |
+- |
1811 |
+-static int get_mic_state(struct mic_info *mic, char *state) |
1812 |
+-{ |
1813 |
+- if (!strcmp(state, "offline")) |
1814 |
+- return MIC_OFFLINE; |
1815 |
+- if (!strcmp(state, "online")) |
1816 |
+- return MIC_ONLINE; |
1817 |
+- if (!strcmp(state, "shutting_down")) |
1818 |
+- return MIC_SHUTTING_DOWN; |
1819 |
+- if (!strcmp(state, "reset_failed")) |
1820 |
+- return MIC_RESET_FAILED; |
1821 |
+- if (!strcmp(state, "suspending")) |
1822 |
+- return MIC_SUSPENDING; |
1823 |
+- if (!strcmp(state, "suspended")) |
1824 |
+- return MIC_SUSPENDED; |
1825 |
+- mpsslog("%s: BUG invalid state %s\n", mic->name, state); |
1826 |
+- /* Invalid state */ |
1827 |
+- assert(0); |
1828 |
+-}; |
1829 |
+- |
1830 |
+-static void mic_handle_shutdown(struct mic_info *mic) |
1831 |
+-{ |
1832 |
+-#define SHUTDOWN_TIMEOUT 60 |
1833 |
+- int i = SHUTDOWN_TIMEOUT, ret, stat = 0; |
1834 |
+- char *shutdown_status; |
1835 |
+- while (i) { |
1836 |
+- shutdown_status = readsysfs(mic->name, "shutdown_status"); |
1837 |
+- if (!shutdown_status) |
1838 |
+- continue; |
1839 |
+- mpsslog("%s: %s %d shutdown_status %s\n", |
1840 |
+- mic->name, __func__, __LINE__, shutdown_status); |
1841 |
+- switch (get_mic_shutdown_status(mic, shutdown_status)) { |
1842 |
+- case MIC_RESTART: |
1843 |
+- mic->restart = 1; |
1844 |
+- case MIC_HALTED: |
1845 |
+- case MIC_POWER_OFF: |
1846 |
+- case MIC_CRASHED: |
1847 |
+- free(shutdown_status); |
1848 |
+- goto reset; |
1849 |
+- default: |
1850 |
+- break; |
1851 |
+- } |
1852 |
+- free(shutdown_status); |
1853 |
+- sleep(1); |
1854 |
+- i--; |
1855 |
+- } |
1856 |
+-reset: |
1857 |
+- ret = kill(mic->pid, SIGTERM); |
1858 |
+- mpsslog("%s: %s %d kill pid %d ret %d\n", |
1859 |
+- mic->name, __func__, __LINE__, |
1860 |
+- mic->pid, ret); |
1861 |
+- if (!ret) { |
1862 |
+- ret = waitpid(mic->pid, &stat, |
1863 |
+- WIFSIGNALED(stat)); |
1864 |
+- mpsslog("%s: %s %d waitpid ret %d pid %d\n", |
1865 |
+- mic->name, __func__, __LINE__, |
1866 |
+- ret, mic->pid); |
1867 |
+- } |
1868 |
+- if (ret == mic->pid) |
1869 |
+- reset(mic); |
1870 |
+-} |
1871 |
+- |
1872 |
+-static void * |
1873 |
+-mic_config(void *arg) |
1874 |
+-{ |
1875 |
+- struct mic_info *mic = (struct mic_info *)arg; |
1876 |
+- char *state = NULL; |
1877 |
+- char pathname[PATH_MAX]; |
1878 |
+- int fd, ret; |
1879 |
+- struct pollfd ufds[1]; |
1880 |
+- char value[4096]; |
1881 |
+- |
1882 |
+- snprintf(pathname, PATH_MAX - 1, "%s/%s/%s", |
1883 |
+- MICSYSFSDIR, mic->name, "state"); |
1884 |
+- |
1885 |
+- fd = open(pathname, O_RDONLY); |
1886 |
+- if (fd < 0) { |
1887 |
+- mpsslog("%s: opening file %s failed %s\n", |
1888 |
+- mic->name, pathname, strerror(errno)); |
1889 |
+- goto error; |
1890 |
+- } |
1891 |
+- |
1892 |
+- do { |
1893 |
+- ret = lseek(fd, 0, SEEK_SET); |
1894 |
+- if (ret < 0) { |
1895 |
+- mpsslog("%s: Failed to seek to file start '%s': %s\n", |
1896 |
+- mic->name, pathname, strerror(errno)); |
1897 |
+- goto close_error1; |
1898 |
+- } |
1899 |
+- ret = read(fd, value, sizeof(value)); |
1900 |
+- if (ret < 0) { |
1901 |
+- mpsslog("%s: Failed to read sysfs entry '%s': %s\n", |
1902 |
+- mic->name, pathname, strerror(errno)); |
1903 |
+- goto close_error1; |
1904 |
+- } |
1905 |
+-retry: |
1906 |
+- state = readsysfs(mic->name, "state"); |
1907 |
+- if (!state) |
1908 |
+- goto retry; |
1909 |
+- mpsslog("%s: %s %d state %s\n", |
1910 |
+- mic->name, __func__, __LINE__, state); |
1911 |
+- switch (get_mic_state(mic, state)) { |
1912 |
+- case MIC_SHUTTING_DOWN: |
1913 |
+- mic_handle_shutdown(mic); |
1914 |
+- goto close_error; |
1915 |
+- case MIC_SUSPENDING: |
1916 |
+- mic->boot_on_resume = 1; |
1917 |
+- setsysfs(mic->name, "state", "suspend"); |
1918 |
+- mic_handle_shutdown(mic); |
1919 |
+- goto close_error; |
1920 |
+- case MIC_OFFLINE: |
1921 |
+- if (mic->boot_on_resume) { |
1922 |
+- setsysfs(mic->name, "state", "boot"); |
1923 |
+- mic->boot_on_resume = 0; |
1924 |
+- } |
1925 |
+- break; |
1926 |
+- default: |
1927 |
+- break; |
1928 |
+- } |
1929 |
+- free(state); |
1930 |
+- |
1931 |
+- ufds[0].fd = fd; |
1932 |
+- ufds[0].events = POLLERR | POLLPRI; |
1933 |
+- ret = poll(ufds, 1, -1); |
1934 |
+- if (ret < 0) { |
1935 |
+- mpsslog("%s: poll failed %s\n", |
1936 |
+- mic->name, strerror(errno)); |
1937 |
+- goto close_error1; |
1938 |
+- } |
1939 |
+- } while (1); |
1940 |
+-close_error: |
1941 |
+- free(state); |
1942 |
+-close_error1: |
1943 |
+- close(fd); |
1944 |
+-error: |
1945 |
+- init_mic(mic); |
1946 |
+- pthread_exit(NULL); |
1947 |
+-} |
1948 |
+- |
1949 |
+-static void |
1950 |
+-set_cmdline(struct mic_info *mic) |
1951 |
+-{ |
1952 |
+- char buffer[PATH_MAX]; |
1953 |
+- int len; |
1954 |
+- |
1955 |
+- len = snprintf(buffer, PATH_MAX, |
1956 |
+- "clocksource=tsc highres=off nohz=off "); |
1957 |
+- len += snprintf(buffer + len, PATH_MAX - len, |
1958 |
+- "cpufreq_on;corec6_off;pc3_off;pc6_off "); |
1959 |
+- len += snprintf(buffer + len, PATH_MAX - len, |
1960 |
+- "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0", |
1961 |
+- mic->id); |
1962 |
+- |
1963 |
+- setsysfs(mic->name, "cmdline", buffer); |
1964 |
+- mpsslog("%s: Command line: \"%s\"\n", mic->name, buffer); |
1965 |
+- snprintf(buffer, PATH_MAX, "172.31.%d.1", mic->id); |
1966 |
+- mpsslog("%s: IPADDR: \"%s\"\n", mic->name, buffer); |
1967 |
+-} |
1968 |
+- |
1969 |
+-static void |
1970 |
+-set_log_buf_info(struct mic_info *mic) |
1971 |
+-{ |
1972 |
+- int fd; |
1973 |
+- off_t len; |
1974 |
+- char system_map[] = "/lib/firmware/mic/System.map"; |
1975 |
+- char *map, *temp, log_buf[17] = {'\0'}; |
1976 |
+- |
1977 |
+- fd = open(system_map, O_RDONLY); |
1978 |
+- if (fd < 0) { |
1979 |
+- mpsslog("%s: Opening System.map failed: %d\n", |
1980 |
+- mic->name, errno); |
1981 |
+- return; |
1982 |
+- } |
1983 |
+- len = lseek(fd, 0, SEEK_END); |
1984 |
+- if (len < 0) { |
1985 |
+- mpsslog("%s: Reading System.map size failed: %d\n", |
1986 |
+- mic->name, errno); |
1987 |
+- close(fd); |
1988 |
+- return; |
1989 |
+- } |
1990 |
+- map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); |
1991 |
+- if (map == MAP_FAILED) { |
1992 |
+- mpsslog("%s: mmap of System.map failed: %d\n", |
1993 |
+- mic->name, errno); |
1994 |
+- close(fd); |
1995 |
+- return; |
1996 |
+- } |
1997 |
+- temp = strstr(map, "__log_buf"); |
1998 |
+- if (!temp) { |
1999 |
+- mpsslog("%s: __log_buf not found: %d\n", mic->name, errno); |
2000 |
+- munmap(map, len); |
2001 |
+- close(fd); |
2002 |
+- return; |
2003 |
+- } |
2004 |
+- strncpy(log_buf, temp - 19, 16); |
2005 |
+- setsysfs(mic->name, "log_buf_addr", log_buf); |
2006 |
+- mpsslog("%s: log_buf_addr: %s\n", mic->name, log_buf); |
2007 |
+- temp = strstr(map, "log_buf_len"); |
2008 |
+- if (!temp) { |
2009 |
+- mpsslog("%s: log_buf_len not found: %d\n", mic->name, errno); |
2010 |
+- munmap(map, len); |
2011 |
+- close(fd); |
2012 |
+- return; |
2013 |
+- } |
2014 |
+- strncpy(log_buf, temp - 19, 16); |
2015 |
+- setsysfs(mic->name, "log_buf_len", log_buf); |
2016 |
+- mpsslog("%s: log_buf_len: %s\n", mic->name, log_buf); |
2017 |
+- munmap(map, len); |
2018 |
+- close(fd); |
2019 |
+-} |
2020 |
+- |
2021 |
+-static void init_mic(struct mic_info *mic); |
2022 |
+- |
2023 |
+-static void |
2024 |
+-change_virtblk_backend(int x, siginfo_t *siginfo, void *p) |
2025 |
+-{ |
2026 |
+- struct mic_info *mic; |
2027 |
+- |
2028 |
+- for (mic = mic_list.next; mic != NULL; mic = mic->next) |
2029 |
+- mic->mic_virtblk.signaled = 1/* true */; |
2030 |
+-} |
2031 |
+- |
2032 |
+-static void |
2033 |
+-init_mic(struct mic_info *mic) |
2034 |
+-{ |
2035 |
+- struct sigaction ignore = { |
2036 |
+- .sa_flags = 0, |
2037 |
+- .sa_handler = SIG_IGN |
2038 |
+- }; |
2039 |
+- struct sigaction act = { |
2040 |
+- .sa_flags = SA_SIGINFO, |
2041 |
+- .sa_sigaction = change_virtblk_backend, |
2042 |
+- }; |
2043 |
+- char buffer[PATH_MAX]; |
2044 |
+- int err; |
2045 |
+- |
2046 |
+- /* |
2047 |
+- * Currently, one virtio block device is supported for each MIC card |
2048 |
+- * at a time. Any user (or test) can send a SIGUSR1 to the MIC daemon. |
2049 |
+- * The signal informs the virtio block backend about a change in the |
2050 |
+- * configuration file which specifies the virtio backend file name on |
2051 |
+- * the host. Virtio block backend then re-reads the configuration file |
2052 |
+- * and switches to the new block device. This signalling mechanism may |
2053 |
+- * not be required once multiple virtio block devices are supported by |
2054 |
+- * the MIC daemon. |
2055 |
+- */ |
2056 |
+- sigaction(SIGUSR1, &ignore, NULL); |
2057 |
+- |
2058 |
+- mic->pid = fork(); |
2059 |
+- switch (mic->pid) { |
2060 |
+- case 0: |
2061 |
+- set_log_buf_info(mic); |
2062 |
+- set_cmdline(mic); |
2063 |
+- add_virtio_device(mic, &virtcons_dev_page.dd); |
2064 |
+- add_virtio_device(mic, &virtnet_dev_page.dd); |
2065 |
+- err = pthread_create(&mic->mic_console.console_thread, NULL, |
2066 |
+- virtio_console, mic); |
2067 |
+- if (err) |
2068 |
+- mpsslog("%s virtcons pthread_create failed %s\n", |
2069 |
+- mic->name, strerror(err)); |
2070 |
+- err = pthread_create(&mic->mic_net.net_thread, NULL, |
2071 |
+- virtio_net, mic); |
2072 |
+- if (err) |
2073 |
+- mpsslog("%s virtnet pthread_create failed %s\n", |
2074 |
+- mic->name, strerror(err)); |
2075 |
+- err = pthread_create(&mic->mic_virtblk.block_thread, NULL, |
2076 |
+- virtio_block, mic); |
2077 |
+- if (err) |
2078 |
+- mpsslog("%s virtblk pthread_create failed %s\n", |
2079 |
+- mic->name, strerror(err)); |
2080 |
+- sigemptyset(&act.sa_mask); |
2081 |
+- err = sigaction(SIGUSR1, &act, NULL); |
2082 |
+- if (err) |
2083 |
+- mpsslog("%s sigaction SIGUSR1 failed %s\n", |
2084 |
+- mic->name, strerror(errno)); |
2085 |
+- while (1) |
2086 |
+- sleep(60); |
2087 |
+- case -1: |
2088 |
+- mpsslog("fork failed MIC name %s id %d errno %d\n", |
2089 |
+- mic->name, mic->id, errno); |
2090 |
+- break; |
2091 |
+- default: |
2092 |
+- if (mic->restart) { |
2093 |
+- snprintf(buffer, PATH_MAX, "boot"); |
2094 |
+- setsysfs(mic->name, "state", buffer); |
2095 |
+- mpsslog("%s restarting mic %d\n", |
2096 |
+- mic->name, mic->restart); |
2097 |
+- mic->restart = 0; |
2098 |
+- } |
2099 |
+- pthread_create(&mic->config_thread, NULL, mic_config, mic); |
2100 |
+- } |
2101 |
+-} |
2102 |
+- |
2103 |
+-static void |
2104 |
+-start_daemon(void) |
2105 |
+-{ |
2106 |
+- struct mic_info *mic; |
2107 |
+- |
2108 |
+- for (mic = mic_list.next; mic != NULL; mic = mic->next) |
2109 |
+- init_mic(mic); |
2110 |
+- |
2111 |
+- while (1) |
2112 |
+- sleep(60); |
2113 |
+-} |
2114 |
+- |
2115 |
+-static int |
2116 |
+-init_mic_list(void) |
2117 |
+-{ |
2118 |
+- struct mic_info *mic = &mic_list; |
2119 |
+- struct dirent *file; |
2120 |
+- DIR *dp; |
2121 |
+- int cnt = 0; |
2122 |
+- |
2123 |
+- dp = opendir(MICSYSFSDIR); |
2124 |
+- if (!dp) |
2125 |
+- return 0; |
2126 |
+- |
2127 |
+- while ((file = readdir(dp)) != NULL) { |
2128 |
+- if (!strncmp(file->d_name, "mic", 3)) { |
2129 |
+- mic->next = calloc(1, sizeof(struct mic_info)); |
2130 |
+- if (mic->next) { |
2131 |
+- mic = mic->next; |
2132 |
+- mic->id = atoi(&file->d_name[3]); |
2133 |
+- mic->name = malloc(strlen(file->d_name) + 16); |
2134 |
+- if (mic->name) |
2135 |
+- strcpy(mic->name, file->d_name); |
2136 |
+- mpsslog("MIC name %s id %d\n", mic->name, |
2137 |
+- mic->id); |
2138 |
+- cnt++; |
2139 |
+- } |
2140 |
+- } |
2141 |
+- } |
2142 |
+- |
2143 |
+- closedir(dp); |
2144 |
+- return cnt; |
2145 |
+-} |
2146 |
+- |
2147 |
+-void |
2148 |
+-mpsslog(char *format, ...) |
2149 |
+-{ |
2150 |
+- va_list args; |
2151 |
+- char buffer[4096]; |
2152 |
+- char ts[52], *ts1; |
2153 |
+- time_t t; |
2154 |
+- |
2155 |
+- if (logfp == NULL) |
2156 |
+- return; |
2157 |
+- |
2158 |
+- va_start(args, format); |
2159 |
+- vsprintf(buffer, format, args); |
2160 |
+- va_end(args); |
2161 |
+- |
2162 |
+- time(&t); |
2163 |
+- ts1 = ctime_r(&t, ts); |
2164 |
+- ts1[strlen(ts1) - 1] = '\0'; |
2165 |
+- fprintf(logfp, "%s: %s", ts1, buffer); |
2166 |
+- |
2167 |
+- fflush(logfp); |
2168 |
+-} |
2169 |
+- |
2170 |
+-int |
2171 |
+-main(int argc, char *argv[]) |
2172 |
+-{ |
2173 |
+- int cnt; |
2174 |
+- pid_t pid; |
2175 |
+- |
2176 |
+- myname = argv[0]; |
2177 |
+- |
2178 |
+- logfp = fopen(LOGFILE_NAME, "a+"); |
2179 |
+- if (!logfp) { |
2180 |
+- fprintf(stderr, "cannot open logfile '%s'\n", LOGFILE_NAME); |
2181 |
+- exit(1); |
2182 |
+- } |
2183 |
+- pid = fork(); |
2184 |
+- switch (pid) { |
2185 |
+- case 0: |
2186 |
+- break; |
2187 |
+- case -1: |
2188 |
+- exit(2); |
2189 |
+- default: |
2190 |
+- exit(0); |
2191 |
+- } |
2192 |
+- |
2193 |
+- mpsslog("MIC Daemon start\n"); |
2194 |
+- |
2195 |
+- cnt = init_mic_list(); |
2196 |
+- if (cnt == 0) { |
2197 |
+- mpsslog("MIC module not loaded\n"); |
2198 |
+- exit(3); |
2199 |
+- } |
2200 |
+- mpsslog("MIC found %d devices\n", cnt); |
2201 |
+- |
2202 |
+- start_daemon(); |
2203 |
+- |
2204 |
+- exit(0); |
2205 |
+-} |
2206 |
+diff --git a/Documentation/mic/mpssd/mpssd.h b/Documentation/mic/mpssd/mpssd.h |
2207 |
+deleted file mode 100644 |
2208 |
+index f5f18b15d9a0..000000000000 |
2209 |
+--- a/Documentation/mic/mpssd/mpssd.h |
2210 |
++++ /dev/null |
2211 |
+@@ -1,102 +0,0 @@ |
2212 |
+-/* |
2213 |
+- * Intel MIC Platform Software Stack (MPSS) |
2214 |
+- * |
2215 |
+- * Copyright(c) 2013 Intel Corporation. |
2216 |
+- * |
2217 |
+- * This program is free software; you can redistribute it and/or modify |
2218 |
+- * it under the terms of the GNU General Public License, version 2, as |
2219 |
+- * published by the Free Software Foundation. |
2220 |
+- * |
2221 |
+- * This program is distributed in the hope that it will be useful, but |
2222 |
+- * WITHOUT ANY WARRANTY; without even the implied warranty of |
2223 |
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2224 |
+- * General Public License for more details. |
2225 |
+- * |
2226 |
+- * The full GNU General Public License is included in this distribution in |
2227 |
+- * the file called "COPYING". |
2228 |
+- * |
2229 |
+- * Intel MIC User Space Tools. |
2230 |
+- */ |
2231 |
+-#ifndef _MPSSD_H_ |
2232 |
+-#define _MPSSD_H_ |
2233 |
+- |
2234 |
+-#include <stdio.h> |
2235 |
+-#include <stdlib.h> |
2236 |
+-#include <string.h> |
2237 |
+-#include <fcntl.h> |
2238 |
+-#include <unistd.h> |
2239 |
+-#include <dirent.h> |
2240 |
+-#include <libgen.h> |
2241 |
+-#include <pthread.h> |
2242 |
+-#include <stdarg.h> |
2243 |
+-#include <time.h> |
2244 |
+-#include <errno.h> |
2245 |
+-#include <sys/dir.h> |
2246 |
+-#include <sys/ioctl.h> |
2247 |
+-#include <sys/poll.h> |
2248 |
+-#include <sys/types.h> |
2249 |
+-#include <sys/socket.h> |
2250 |
+-#include <sys/stat.h> |
2251 |
+-#include <sys/types.h> |
2252 |
+-#include <sys/mman.h> |
2253 |
+-#include <sys/utsname.h> |
2254 |
+-#include <sys/wait.h> |
2255 |
+-#include <netinet/in.h> |
2256 |
+-#include <arpa/inet.h> |
2257 |
+-#include <netdb.h> |
2258 |
+-#include <pthread.h> |
2259 |
+-#include <signal.h> |
2260 |
+-#include <limits.h> |
2261 |
+-#include <syslog.h> |
2262 |
+-#include <getopt.h> |
2263 |
+-#include <net/if.h> |
2264 |
+-#include <linux/if_tun.h> |
2265 |
+-#include <linux/if_tun.h> |
2266 |
+-#include <linux/virtio_ids.h> |
2267 |
+- |
2268 |
+-#define MICSYSFSDIR "/sys/class/mic" |
2269 |
+-#define LOGFILE_NAME "/var/log/mpssd" |
2270 |
+-#define PAGE_SIZE 4096 |
2271 |
+- |
2272 |
+-struct mic_console_info { |
2273 |
+- pthread_t console_thread; |
2274 |
+- int virtio_console_fd; |
2275 |
+- void *console_dp; |
2276 |
+-}; |
2277 |
+- |
2278 |
+-struct mic_net_info { |
2279 |
+- pthread_t net_thread; |
2280 |
+- int virtio_net_fd; |
2281 |
+- int tap_fd; |
2282 |
+- void *net_dp; |
2283 |
+-}; |
2284 |
+- |
2285 |
+-struct mic_virtblk_info { |
2286 |
+- pthread_t block_thread; |
2287 |
+- int virtio_block_fd; |
2288 |
+- void *block_dp; |
2289 |
+- volatile sig_atomic_t signaled; |
2290 |
+- char *backend_file; |
2291 |
+- int backend; |
2292 |
+- void *backend_addr; |
2293 |
+- long backend_size; |
2294 |
+-}; |
2295 |
+- |
2296 |
+-struct mic_info { |
2297 |
+- int id; |
2298 |
+- char *name; |
2299 |
+- pthread_t config_thread; |
2300 |
+- pid_t pid; |
2301 |
+- struct mic_console_info mic_console; |
2302 |
+- struct mic_net_info mic_net; |
2303 |
+- struct mic_virtblk_info mic_virtblk; |
2304 |
+- int restart; |
2305 |
+- int boot_on_resume; |
2306 |
+- struct mic_info *next; |
2307 |
+-}; |
2308 |
+- |
2309 |
+-__attribute__((format(printf, 1, 2))) |
2310 |
+-void mpsslog(char *format, ...); |
2311 |
+-char *readsysfs(char *dir, char *entry); |
2312 |
+-int setsysfs(char *dir, char *entry, char *value); |
2313 |
+-#endif |
2314 |
+diff --git a/Documentation/mic/mpssd/sysfs.c b/Documentation/mic/mpssd/sysfs.c |
2315 |
+deleted file mode 100644 |
2316 |
+index 8dd326936083..000000000000 |
2317 |
+--- a/Documentation/mic/mpssd/sysfs.c |
2318 |
++++ /dev/null |
2319 |
+@@ -1,102 +0,0 @@ |
2320 |
+-/* |
2321 |
+- * Intel MIC Platform Software Stack (MPSS) |
2322 |
+- * |
2323 |
+- * Copyright(c) 2013 Intel Corporation. |
2324 |
+- * |
2325 |
+- * This program is free software; you can redistribute it and/or modify |
2326 |
+- * it under the terms of the GNU General Public License, version 2, as |
2327 |
+- * published by the Free Software Foundation. |
2328 |
+- * |
2329 |
+- * This program is distributed in the hope that it will be useful, but |
2330 |
+- * WITHOUT ANY WARRANTY; without even the implied warranty of |
2331 |
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2332 |
+- * General Public License for more details. |
2333 |
+- * |
2334 |
+- * The full GNU General Public License is included in this distribution in |
2335 |
+- * the file called "COPYING". |
2336 |
+- * |
2337 |
+- * Intel MIC User Space Tools. |
2338 |
+- */ |
2339 |
+- |
2340 |
+-#include "mpssd.h" |
2341 |
+- |
2342 |
+-#define PAGE_SIZE 4096 |
2343 |
+- |
2344 |
+-char * |
2345 |
+-readsysfs(char *dir, char *entry) |
2346 |
+-{ |
2347 |
+- char filename[PATH_MAX]; |
2348 |
+- char value[PAGE_SIZE]; |
2349 |
+- char *string = NULL; |
2350 |
+- int fd; |
2351 |
+- int len; |
2352 |
+- |
2353 |
+- if (dir == NULL) |
2354 |
+- snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry); |
2355 |
+- else |
2356 |
+- snprintf(filename, PATH_MAX, |
2357 |
+- "%s/%s/%s", MICSYSFSDIR, dir, entry); |
2358 |
+- |
2359 |
+- fd = open(filename, O_RDONLY); |
2360 |
+- if (fd < 0) { |
2361 |
+- mpsslog("Failed to open sysfs entry '%s': %s\n", |
2362 |
+- filename, strerror(errno)); |
2363 |
+- return NULL; |
2364 |
+- } |
2365 |
+- |
2366 |
+- len = read(fd, value, sizeof(value)); |
2367 |
+- if (len < 0) { |
2368 |
+- mpsslog("Failed to read sysfs entry '%s': %s\n", |
2369 |
+- filename, strerror(errno)); |
2370 |
+- goto readsys_ret; |
2371 |
+- } |
2372 |
+- if (len == 0) |
2373 |
+- goto readsys_ret; |
2374 |
+- |
2375 |
+- value[len - 1] = '\0'; |
2376 |
+- |
2377 |
+- string = malloc(strlen(value) + 1); |
2378 |
+- if (string) |
2379 |
+- strcpy(string, value); |
2380 |
+- |
2381 |
+-readsys_ret: |
2382 |
+- close(fd); |
2383 |
+- return string; |
2384 |
+-} |
2385 |
+- |
2386 |
+-int |
2387 |
+-setsysfs(char *dir, char *entry, char *value) |
2388 |
+-{ |
2389 |
+- char filename[PATH_MAX]; |
2390 |
+- char *oldvalue; |
2391 |
+- int fd, ret = 0; |
2392 |
+- |
2393 |
+- if (dir == NULL) |
2394 |
+- snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry); |
2395 |
+- else |
2396 |
+- snprintf(filename, PATH_MAX, "%s/%s/%s", |
2397 |
+- MICSYSFSDIR, dir, entry); |
2398 |
+- |
2399 |
+- oldvalue = readsysfs(dir, entry); |
2400 |
+- |
2401 |
+- fd = open(filename, O_RDWR); |
2402 |
+- if (fd < 0) { |
2403 |
+- ret = errno; |
2404 |
+- mpsslog("Failed to open sysfs entry '%s': %s\n", |
2405 |
+- filename, strerror(errno)); |
2406 |
+- goto done; |
2407 |
+- } |
2408 |
+- |
2409 |
+- if (!oldvalue || strcmp(value, oldvalue)) { |
2410 |
+- if (write(fd, value, strlen(value)) < 0) { |
2411 |
+- ret = errno; |
2412 |
+- mpsslog("Failed to write new sysfs entry '%s': %s\n", |
2413 |
+- filename, strerror(errno)); |
2414 |
+- } |
2415 |
+- } |
2416 |
+- close(fd); |
2417 |
+-done: |
2418 |
+- if (oldvalue) |
2419 |
+- free(oldvalue); |
2420 |
+- return ret; |
2421 |
+-} |
2422 |
+diff --git a/Documentation/networking/netlink_mmap.txt b/Documentation/networking/netlink_mmap.txt |
2423 |
+deleted file mode 100644 |
2424 |
+index c6af4bac5aa8..000000000000 |
2425 |
+--- a/Documentation/networking/netlink_mmap.txt |
2426 |
++++ /dev/null |
2427 |
+@@ -1,339 +0,0 @@ |
2428 |
+-This file documents how to use memory mapped I/O with netlink. |
2429 |
+- |
2430 |
+-Author: Patrick McHardy <kaber@×××××.net> |
2431 |
+- |
2432 |
+-Overview |
2433 |
+--------- |
2434 |
+- |
2435 |
+-Memory mapped netlink I/O can be used to increase throughput and decrease |
2436 |
+-overhead of unicast receive and transmit operations. Some netlink subsystems |
2437 |
+-require high throughput, these are mainly the netfilter subsystems |
2438 |
+-nfnetlink_queue and nfnetlink_log, but it can also help speed up large |
2439 |
+-dump operations of f.i. the routing database. |
2440 |
+- |
2441 |
+-Memory mapped netlink I/O used two circular ring buffers for RX and TX which |
2442 |
+-are mapped into the processes address space. |
2443 |
+- |
2444 |
+-The RX ring is used by the kernel to directly construct netlink messages into |
2445 |
+-user-space memory without copying them as done with regular socket I/O, |
2446 |
+-additionally as long as the ring contains messages no recvmsg() or poll() |
2447 |
+-syscalls have to be issued by user-space to get more message. |
2448 |
+- |
2449 |
+-The TX ring is used to process messages directly from user-space memory, the |
2450 |
+-kernel processes all messages contained in the ring using a single sendmsg() |
2451 |
+-call. |
2452 |
+- |
2453 |
+-Usage overview |
2454 |
+--------------- |
2455 |
+- |
2456 |
+-In order to use memory mapped netlink I/O, user-space needs three main changes: |
2457 |
+- |
2458 |
+-- ring setup |
2459 |
+-- conversion of the RX path to get messages from the ring instead of recvmsg() |
2460 |
+-- conversion of the TX path to construct messages into the ring |
2461 |
+- |
2462 |
+-Ring setup is done using setsockopt() to provide the ring parameters to the |
2463 |
+-kernel, then a call to mmap() to map the ring into the processes address space: |
2464 |
+- |
2465 |
+-- setsockopt(fd, SOL_NETLINK, NETLINK_RX_RING, ¶ms, sizeof(params)); |
2466 |
+-- setsockopt(fd, SOL_NETLINK, NETLINK_TX_RING, ¶ms, sizeof(params)); |
2467 |
+-- ring = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0) |
2468 |
+- |
2469 |
+-Usage of either ring is optional, but even if only the RX ring is used the |
2470 |
+-mapping still needs to be writable in order to update the frame status after |
2471 |
+-processing. |
2472 |
+- |
2473 |
+-Conversion of the reception path involves calling poll() on the file |
2474 |
+-descriptor, once the socket is readable the frames from the ring are |
2475 |
+-processed in order until no more messages are available, as indicated by |
2476 |
+-a status word in the frame header. |
2477 |
+- |
2478 |
+-On kernel side, in order to make use of memory mapped I/O on receive, the |
2479 |
+-originating netlink subsystem needs to support memory mapped I/O, otherwise |
2480 |
+-it will use an allocated socket buffer as usual and the contents will be |
2481 |
+- copied to the ring on transmission, nullifying most of the performance gains. |
2482 |
+-Dumps of kernel databases automatically support memory mapped I/O. |
2483 |
+- |
2484 |
+-Conversion of the transmit path involves changing message construction to |
2485 |
+-use memory from the TX ring instead of (usually) a buffer declared on the |
2486 |
+-stack and setting up the frame header appropriately. Optionally poll() can |
2487 |
+-be used to wait for free frames in the TX ring. |
2488 |
+- |
2489 |
+-Structured and definitions for using memory mapped I/O are contained in |
2490 |
+-<linux/netlink.h>. |
2491 |
+- |
2492 |
+-RX and TX rings |
2493 |
+----------------- |
2494 |
+- |
2495 |
+-Each ring contains a number of continuous memory blocks, containing frames of |
2496 |
+-fixed size dependent on the parameters used for ring setup. |
2497 |
+- |
2498 |
+-Ring: [ block 0 ] |
2499 |
+- [ frame 0 ] |
2500 |
+- [ frame 1 ] |
2501 |
+- [ block 1 ] |
2502 |
+- [ frame 2 ] |
2503 |
+- [ frame 3 ] |
2504 |
+- ... |
2505 |
+- [ block n ] |
2506 |
+- [ frame 2 * n ] |
2507 |
+- [ frame 2 * n + 1 ] |
2508 |
+- |
2509 |
+-The blocks are only visible to the kernel, from the point of view of user-space |
2510 |
+-the ring just contains the frames in a continuous memory zone. |
2511 |
+- |
2512 |
+-The ring parameters used for setting up the ring are defined as follows: |
2513 |
+- |
2514 |
+-struct nl_mmap_req { |
2515 |
+- unsigned int nm_block_size; |
2516 |
+- unsigned int nm_block_nr; |
2517 |
+- unsigned int nm_frame_size; |
2518 |
+- unsigned int nm_frame_nr; |
2519 |
+-}; |
2520 |
+- |
2521 |
+-Frames are grouped into blocks, where each block is a continuous region of memory |
2522 |
+-and holds nm_block_size / nm_frame_size frames. The total number of frames in |
2523 |
+-the ring is nm_frame_nr. The following invariants hold: |
2524 |
+- |
2525 |
+-- frames_per_block = nm_block_size / nm_frame_size |
2526 |
+- |
2527 |
+-- nm_frame_nr = frames_per_block * nm_block_nr |
2528 |
+- |
2529 |
+-Some parameters are constrained, specifically: |
2530 |
+- |
2531 |
+-- nm_block_size must be a multiple of the architectures memory page size. |
2532 |
+- The getpagesize() function can be used to get the page size. |
2533 |
+- |
2534 |
+-- nm_frame_size must be equal or larger to NL_MMAP_HDRLEN, IOW a frame must be |
2535 |
+- able to hold at least the frame header |
2536 |
+- |
2537 |
+-- nm_frame_size must be smaller or equal to nm_block_size |
2538 |
+- |
2539 |
+-- nm_frame_size must be a multiple of NL_MMAP_MSG_ALIGNMENT |
2540 |
+- |
2541 |
+-- nm_frame_nr must equal the actual number of frames as specified above. |
2542 |
+- |
2543 |
+-When the kernel can't allocate physically continuous memory for a ring block, |
2544 |
+-it will fall back to use physically discontinuous memory. This might affect |
2545 |
+-performance negatively, in order to avoid this the nm_frame_size parameter |
2546 |
+-should be chosen to be as small as possible for the required frame size and |
2547 |
+-the number of blocks should be increased instead. |
2548 |
+- |
2549 |
+-Ring frames |
2550 |
+------------- |
2551 |
+- |
2552 |
+-Each frames contain a frame header, consisting of a synchronization word and some |
2553 |
+-meta-data, and the message itself. |
2554 |
+- |
2555 |
+-Frame: [ header message ] |
2556 |
+- |
2557 |
+-The frame header is defined as follows: |
2558 |
+- |
2559 |
+-struct nl_mmap_hdr { |
2560 |
+- unsigned int nm_status; |
2561 |
+- unsigned int nm_len; |
2562 |
+- __u32 nm_group; |
2563 |
+- /* credentials */ |
2564 |
+- __u32 nm_pid; |
2565 |
+- __u32 nm_uid; |
2566 |
+- __u32 nm_gid; |
2567 |
+-}; |
2568 |
+- |
2569 |
+-- nm_status is used for synchronizing processing between the kernel and user- |
2570 |
+- space and specifies ownership of the frame as well as the operation to perform |
2571 |
+- |
2572 |
+-- nm_len contains the length of the message contained in the data area |
2573 |
+- |
2574 |
+-- nm_group specified the destination multicast group of message |
2575 |
+- |
2576 |
+-- nm_pid, nm_uid and nm_gid contain the netlink pid, UID and GID of the sending |
2577 |
+- process. These values correspond to the data available using SOCK_PASSCRED in |
2578 |
+- the SCM_CREDENTIALS cmsg. |
2579 |
+- |
2580 |
+-The possible values in the status word are: |
2581 |
+- |
2582 |
+-- NL_MMAP_STATUS_UNUSED: |
2583 |
+- RX ring: frame belongs to the kernel and contains no message |
2584 |
+- for user-space. Approriate action is to invoke poll() |
2585 |
+- to wait for new messages. |
2586 |
+- |
2587 |
+- TX ring: frame belongs to user-space and can be used for |
2588 |
+- message construction. |
2589 |
+- |
2590 |
+-- NL_MMAP_STATUS_RESERVED: |
2591 |
+- RX ring only: frame is currently used by the kernel for message |
2592 |
+- construction and contains no valid message yet. |
2593 |
+- Appropriate action is to invoke poll() to wait for |
2594 |
+- new messages. |
2595 |
+- |
2596 |
+-- NL_MMAP_STATUS_VALID: |
2597 |
+- RX ring: frame contains a valid message. Approriate action is |
2598 |
+- to process the message and release the frame back to |
2599 |
+- the kernel by setting the status to |
2600 |
+- NL_MMAP_STATUS_UNUSED or queue the frame by setting the |
2601 |
+- status to NL_MMAP_STATUS_SKIP. |
2602 |
+- |
2603 |
+- TX ring: the frame contains a valid message from user-space to |
2604 |
+- be processed by the kernel. After completing processing |
2605 |
+- the kernel will release the frame back to user-space by |
2606 |
+- setting the status to NL_MMAP_STATUS_UNUSED. |
2607 |
+- |
2608 |
+-- NL_MMAP_STATUS_COPY: |
2609 |
+- RX ring only: a message is ready to be processed but could not be |
2610 |
+- stored in the ring, either because it exceeded the |
2611 |
+- frame size or because the originating subsystem does |
2612 |
+- not support memory mapped I/O. Appropriate action is |
2613 |
+- to invoke recvmsg() to receive the message and release |
2614 |
+- the frame back to the kernel by setting the status to |
2615 |
+- NL_MMAP_STATUS_UNUSED. |
2616 |
+- |
2617 |
+-- NL_MMAP_STATUS_SKIP: |
2618 |
+- RX ring only: user-space queued the message for later processing, but |
2619 |
+- processed some messages following it in the ring. The |
2620 |
+- kernel should skip this frame when looking for unused |
2621 |
+- frames. |
2622 |
+- |
2623 |
+-The data area of a frame begins at a offset of NL_MMAP_HDRLEN relative to the |
2624 |
+-frame header. |
2625 |
+- |
2626 |
+-TX limitations |
2627 |
+--------------- |
2628 |
+- |
2629 |
+-Kernel processing usually involves validation of the message received by |
2630 |
+-user-space, then processing its contents. The kernel must assure that |
2631 |
+-userspace is not able to modify the message contents after they have been |
2632 |
+-validated. In order to do so, the message is copied from the ring frame |
2633 |
+-to an allocated buffer if either of these conditions is false: |
2634 |
+- |
2635 |
+-- only a single mapping of the ring exists |
2636 |
+-- the file descriptor is not shared between processes |
2637 |
+- |
2638 |
+-This means that for threaded programs, the kernel will fall back to copying. |
2639 |
+- |
2640 |
+-Example |
2641 |
+-------- |
2642 |
+- |
2643 |
+-Ring setup: |
2644 |
+- |
2645 |
+- unsigned int block_size = 16 * getpagesize(); |
2646 |
+- struct nl_mmap_req req = { |
2647 |
+- .nm_block_size = block_size, |
2648 |
+- .nm_block_nr = 64, |
2649 |
+- .nm_frame_size = 16384, |
2650 |
+- .nm_frame_nr = 64 * block_size / 16384, |
2651 |
+- }; |
2652 |
+- unsigned int ring_size; |
2653 |
+- void *rx_ring, *tx_ring; |
2654 |
+- |
2655 |
+- /* Configure ring parameters */ |
2656 |
+- if (setsockopt(fd, SOL_NETLINK, NETLINK_RX_RING, &req, sizeof(req)) < 0) |
2657 |
+- exit(1); |
2658 |
+- if (setsockopt(fd, SOL_NETLINK, NETLINK_TX_RING, &req, sizeof(req)) < 0) |
2659 |
+- exit(1) |
2660 |
+- |
2661 |
+- /* Calculate size of each individual ring */ |
2662 |
+- ring_size = req.nm_block_nr * req.nm_block_size; |
2663 |
+- |
2664 |
+- /* Map RX/TX rings. The TX ring is located after the RX ring */ |
2665 |
+- rx_ring = mmap(NULL, 2 * ring_size, PROT_READ | PROT_WRITE, |
2666 |
+- MAP_SHARED, fd, 0); |
2667 |
+- if ((long)rx_ring == -1L) |
2668 |
+- exit(1); |
2669 |
+- tx_ring = rx_ring + ring_size: |
2670 |
+- |
2671 |
+-Message reception: |
2672 |
+- |
2673 |
+-This example assumes some ring parameters of the ring setup are available. |
2674 |
+- |
2675 |
+- unsigned int frame_offset = 0; |
2676 |
+- struct nl_mmap_hdr *hdr; |
2677 |
+- struct nlmsghdr *nlh; |
2678 |
+- unsigned char buf[16384]; |
2679 |
+- ssize_t len; |
2680 |
+- |
2681 |
+- while (1) { |
2682 |
+- struct pollfd pfds[1]; |
2683 |
+- |
2684 |
+- pfds[0].fd = fd; |
2685 |
+- pfds[0].events = POLLIN | POLLERR; |
2686 |
+- pfds[0].revents = 0; |
2687 |
+- |
2688 |
+- if (poll(pfds, 1, -1) < 0 && errno != -EINTR) |
2689 |
+- exit(1); |
2690 |
+- |
2691 |
+- /* Check for errors. Error handling omitted */ |
2692 |
+- if (pfds[0].revents & POLLERR) |
2693 |
+- <handle error> |
2694 |
+- |
2695 |
+- /* If no new messages, poll again */ |
2696 |
+- if (!(pfds[0].revents & POLLIN)) |
2697 |
+- continue; |
2698 |
+- |
2699 |
+- /* Process all frames */ |
2700 |
+- while (1) { |
2701 |
+- /* Get next frame header */ |
2702 |
+- hdr = rx_ring + frame_offset; |
2703 |
+- |
2704 |
+- if (hdr->nm_status == NL_MMAP_STATUS_VALID) { |
2705 |
+- /* Regular memory mapped frame */ |
2706 |
+- nlh = (void *)hdr + NL_MMAP_HDRLEN; |
2707 |
+- len = hdr->nm_len; |
2708 |
+- |
2709 |
+- /* Release empty message immediately. May happen |
2710 |
+- * on error during message construction. |
2711 |
+- */ |
2712 |
+- if (len == 0) |
2713 |
+- goto release; |
2714 |
+- } else if (hdr->nm_status == NL_MMAP_STATUS_COPY) { |
2715 |
+- /* Frame queued to socket receive queue */ |
2716 |
+- len = recv(fd, buf, sizeof(buf), MSG_DONTWAIT); |
2717 |
+- if (len <= 0) |
2718 |
+- break; |
2719 |
+- nlh = buf; |
2720 |
+- } else |
2721 |
+- /* No more messages to process, continue polling */ |
2722 |
+- break; |
2723 |
+- |
2724 |
+- process_msg(nlh); |
2725 |
+-release: |
2726 |
+- /* Release frame back to the kernel */ |
2727 |
+- hdr->nm_status = NL_MMAP_STATUS_UNUSED; |
2728 |
+- |
2729 |
+- /* Advance frame offset to next frame */ |
2730 |
+- frame_offset = (frame_offset + frame_size) % ring_size; |
2731 |
+- } |
2732 |
+- } |
2733 |
+- |
2734 |
+-Message transmission: |
2735 |
+- |
2736 |
+-This example assumes some ring parameters of the ring setup are available. |
2737 |
+-A single message is constructed and transmitted, to send multiple messages |
2738 |
+-at once they would be constructed in consecutive frames before a final call |
2739 |
+-to sendto(). |
2740 |
+- |
2741 |
+- unsigned int frame_offset = 0; |
2742 |
+- struct nl_mmap_hdr *hdr; |
2743 |
+- struct nlmsghdr *nlh; |
2744 |
+- struct sockaddr_nl addr = { |
2745 |
+- .nl_family = AF_NETLINK, |
2746 |
+- }; |
2747 |
+- |
2748 |
+- hdr = tx_ring + frame_offset; |
2749 |
+- if (hdr->nm_status != NL_MMAP_STATUS_UNUSED) |
2750 |
+- /* No frame available. Use poll() to avoid. */ |
2751 |
+- exit(1); |
2752 |
+- |
2753 |
+- nlh = (void *)hdr + NL_MMAP_HDRLEN; |
2754 |
+- |
2755 |
+- /* Build message */ |
2756 |
+- build_message(nlh); |
2757 |
+- |
2758 |
+- /* Fill frame header: length and status need to be set */ |
2759 |
+- hdr->nm_len = nlh->nlmsg_len; |
2760 |
+- hdr->nm_status = NL_MMAP_STATUS_VALID; |
2761 |
+- |
2762 |
+- if (sendto(fd, NULL, 0, 0, &addr, sizeof(addr)) < 0) |
2763 |
+- exit(1); |
2764 |
+- |
2765 |
+- /* Advance frame offset to next frame */ |
2766 |
+- frame_offset = (frame_offset + frame_size) % ring_size; |
2767 |
+diff --git a/Makefile b/Makefile |
2768 |
+index 52d32f6bd7c5..252070fdf91c 100644 |
2769 |
+--- a/Makefile |
2770 |
++++ b/Makefile |
2771 |
+@@ -1,6 +1,6 @@ |
2772 |
+ VERSION = 3 |
2773 |
+ PATCHLEVEL = 18 |
2774 |
+-SUBLEVEL = 48 |
2775 |
++SUBLEVEL = 49 |
2776 |
+ EXTRAVERSION = |
2777 |
+ NAME = Diseased Newt |
2778 |
+ |
2779 |
+diff --git a/arch/arm/include/asm/floppy.h b/arch/arm/include/asm/floppy.h |
2780 |
+index f4882553fbb0..85a34cc8316a 100644 |
2781 |
+--- a/arch/arm/include/asm/floppy.h |
2782 |
++++ b/arch/arm/include/asm/floppy.h |
2783 |
+@@ -17,7 +17,7 @@ |
2784 |
+ |
2785 |
+ #define fd_outb(val,port) \ |
2786 |
+ do { \ |
2787 |
+- if ((port) == FD_DOR) \ |
2788 |
++ if ((port) == (u32)FD_DOR) \ |
2789 |
+ fd_setdor((val)); \ |
2790 |
+ else \ |
2791 |
+ outb((val),(port)); \ |
2792 |
+diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig |
2793 |
+index 48e16d98b2cc..6ecc67f3736b 100644 |
2794 |
+--- a/arch/mips/configs/ip27_defconfig |
2795 |
++++ b/arch/mips/configs/ip27_defconfig |
2796 |
+@@ -206,7 +206,6 @@ CONFIG_MLX4_EN=m |
2797 |
+ # CONFIG_MLX4_DEBUG is not set |
2798 |
+ CONFIG_TEHUTI=m |
2799 |
+ CONFIG_BNX2X=m |
2800 |
+-CONFIG_QLGE=m |
2801 |
+ CONFIG_SFC=m |
2802 |
+ CONFIG_BE2NET=m |
2803 |
+ CONFIG_LIBERTAS_THINFIRM=m |
2804 |
+diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S |
2805 |
+index 41a2fa1fa12e..c7953f2aca4f 100644 |
2806 |
+--- a/arch/mips/dec/int-handler.S |
2807 |
++++ b/arch/mips/dec/int-handler.S |
2808 |
+@@ -146,7 +146,25 @@ |
2809 |
+ /* |
2810 |
+ * Find irq with highest priority |
2811 |
+ */ |
2812 |
+- PTR_LA t1,cpu_mask_nr_tbl |
2813 |
++ # open coded PTR_LA t1, cpu_mask_nr_tbl |
2814 |
++#if (_MIPS_SZPTR == 32) |
2815 |
++ # open coded la t1, cpu_mask_nr_tbl |
2816 |
++ lui t1, %hi(cpu_mask_nr_tbl) |
2817 |
++ addiu t1, %lo(cpu_mask_nr_tbl) |
2818 |
++ |
2819 |
++#endif |
2820 |
++#if (_MIPS_SZPTR == 64) |
2821 |
++ # open coded dla t1, cpu_mask_nr_tbl |
2822 |
++ .set push |
2823 |
++ .set noat |
2824 |
++ lui t1, %highest(cpu_mask_nr_tbl) |
2825 |
++ lui AT, %hi(cpu_mask_nr_tbl) |
2826 |
++ daddiu t1, t1, %higher(cpu_mask_nr_tbl) |
2827 |
++ daddiu AT, AT, %lo(cpu_mask_nr_tbl) |
2828 |
++ dsll t1, 32 |
2829 |
++ daddu t1, t1, AT |
2830 |
++ .set pop |
2831 |
++#endif |
2832 |
+ 1: lw t2,(t1) |
2833 |
+ nop |
2834 |
+ and t2,t0 |
2835 |
+@@ -195,7 +213,25 @@ |
2836 |
+ /* |
2837 |
+ * Find irq with highest priority |
2838 |
+ */ |
2839 |
+- PTR_LA t1,asic_mask_nr_tbl |
2840 |
++ # open coded PTR_LA t1,asic_mask_nr_tbl |
2841 |
++#if (_MIPS_SZPTR == 32) |
2842 |
++ # open coded la t1, asic_mask_nr_tbl |
2843 |
++ lui t1, %hi(asic_mask_nr_tbl) |
2844 |
++ addiu t1, %lo(asic_mask_nr_tbl) |
2845 |
++ |
2846 |
++#endif |
2847 |
++#if (_MIPS_SZPTR == 64) |
2848 |
++ # open coded dla t1, asic_mask_nr_tbl |
2849 |
++ .set push |
2850 |
++ .set noat |
2851 |
++ lui t1, %highest(asic_mask_nr_tbl) |
2852 |
++ lui AT, %hi(asic_mask_nr_tbl) |
2853 |
++ daddiu t1, t1, %higher(asic_mask_nr_tbl) |
2854 |
++ daddiu AT, AT, %lo(asic_mask_nr_tbl) |
2855 |
++ dsll t1, 32 |
2856 |
++ daddu t1, t1, AT |
2857 |
++ .set pop |
2858 |
++#endif |
2859 |
+ 2: lw t2,(t1) |
2860 |
+ nop |
2861 |
+ and t2,t0 |
2862 |
+diff --git a/arch/mips/sgi-ip22/Platform b/arch/mips/sgi-ip22/Platform |
2863 |
+index b7a4b7e04c38..e8f6b3a42a48 100644 |
2864 |
+--- a/arch/mips/sgi-ip22/Platform |
2865 |
++++ b/arch/mips/sgi-ip22/Platform |
2866 |
+@@ -25,7 +25,7 @@ endif |
2867 |
+ # Simplified: what IP22 does at 128MB+ in ksegN, IP28 does at 512MB+ in xkphys |
2868 |
+ # |
2869 |
+ ifdef CONFIG_SGI_IP28 |
2870 |
+- ifeq ($(call cc-option-yn,-mr10k-cache-barrier=store), n) |
2871 |
++ ifeq ($(call cc-option-yn,-march=r10000 -mr10k-cache-barrier=store), n) |
2872 |
+ $(error gcc doesn't support needed option -mr10k-cache-barrier=store) |
2873 |
+ endif |
2874 |
+ endif |
2875 |
+diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c |
2876 |
+index 54651fc2d412..51b667316605 100644 |
2877 |
+--- a/arch/powerpc/lib/sstep.c |
2878 |
++++ b/arch/powerpc/lib/sstep.c |
2879 |
+@@ -1806,8 +1806,6 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) |
2880 |
+ goto instr_done; |
2881 |
+ |
2882 |
+ case LARX: |
2883 |
+- if (regs->msr & MSR_LE) |
2884 |
+- return 0; |
2885 |
+ if (op.ea & (size - 1)) |
2886 |
+ break; /* can't handle misaligned */ |
2887 |
+ err = -EFAULT; |
2888 |
+@@ -1829,8 +1827,6 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) |
2889 |
+ goto ldst_done; |
2890 |
+ |
2891 |
+ case STCX: |
2892 |
+- if (regs->msr & MSR_LE) |
2893 |
+- return 0; |
2894 |
+ if (op.ea & (size - 1)) |
2895 |
+ break; /* can't handle misaligned */ |
2896 |
+ err = -EFAULT; |
2897 |
+@@ -1854,8 +1850,6 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) |
2898 |
+ goto ldst_done; |
2899 |
+ |
2900 |
+ case LOAD: |
2901 |
+- if (regs->msr & MSR_LE) |
2902 |
+- return 0; |
2903 |
+ err = read_mem(®s->gpr[op.reg], op.ea, size, regs); |
2904 |
+ if (!err) { |
2905 |
+ if (op.type & SIGNEXT) |
2906 |
+@@ -1866,8 +1860,6 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) |
2907 |
+ goto ldst_done; |
2908 |
+ |
2909 |
+ case LOAD_FP: |
2910 |
+- if (regs->msr & MSR_LE) |
2911 |
+- return 0; |
2912 |
+ if (size == 4) |
2913 |
+ err = do_fp_load(op.reg, do_lfs, op.ea, size, regs); |
2914 |
+ else |
2915 |
+@@ -1876,15 +1868,11 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) |
2916 |
+ |
2917 |
+ #ifdef CONFIG_ALTIVEC |
2918 |
+ case LOAD_VMX: |
2919 |
+- if (regs->msr & MSR_LE) |
2920 |
+- return 0; |
2921 |
+ err = do_vec_load(op.reg, do_lvx, op.ea & ~0xfUL, regs); |
2922 |
+ goto ldst_done; |
2923 |
+ #endif |
2924 |
+ #ifdef CONFIG_VSX |
2925 |
+ case LOAD_VSX: |
2926 |
+- if (regs->msr & MSR_LE) |
2927 |
+- return 0; |
2928 |
+ err = do_vsx_load(op.reg, do_lxvd2x, op.ea, regs); |
2929 |
+ goto ldst_done; |
2930 |
+ #endif |
2931 |
+@@ -1907,8 +1895,6 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) |
2932 |
+ goto instr_done; |
2933 |
+ |
2934 |
+ case STORE: |
2935 |
+- if (regs->msr & MSR_LE) |
2936 |
+- return 0; |
2937 |
+ if ((op.type & UPDATE) && size == sizeof(long) && |
2938 |
+ op.reg == 1 && op.update_reg == 1 && |
2939 |
+ !(regs->msr & MSR_PR) && |
2940 |
+@@ -1920,8 +1906,6 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) |
2941 |
+ goto ldst_done; |
2942 |
+ |
2943 |
+ case STORE_FP: |
2944 |
+- if (regs->msr & MSR_LE) |
2945 |
+- return 0; |
2946 |
+ if (size == 4) |
2947 |
+ err = do_fp_store(op.reg, do_stfs, op.ea, size, regs); |
2948 |
+ else |
2949 |
+@@ -1930,15 +1914,11 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) |
2950 |
+ |
2951 |
+ #ifdef CONFIG_ALTIVEC |
2952 |
+ case STORE_VMX: |
2953 |
+- if (regs->msr & MSR_LE) |
2954 |
+- return 0; |
2955 |
+ err = do_vec_store(op.reg, do_stvx, op.ea & ~0xfUL, regs); |
2956 |
+ goto ldst_done; |
2957 |
+ #endif |
2958 |
+ #ifdef CONFIG_VSX |
2959 |
+ case STORE_VSX: |
2960 |
+- if (regs->msr & MSR_LE) |
2961 |
+- return 0; |
2962 |
+ err = do_vsx_store(op.reg, do_stxvd2x, op.ea, regs); |
2963 |
+ goto ldst_done; |
2964 |
+ #endif |
2965 |
+diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h |
2966 |
+index d559bdb03d18..2006b955ea91 100644 |
2967 |
+--- a/arch/s390/include/asm/processor.h |
2968 |
++++ b/arch/s390/include/asm/processor.h |
2969 |
+@@ -74,7 +74,8 @@ extern void execve_tail(void); |
2970 |
+ |
2971 |
+ #else /* CONFIG_64BIT */ |
2972 |
+ |
2973 |
+-#define TASK_SIZE_OF(tsk) ((tsk)->mm->context.asce_limit) |
2974 |
++#define TASK_SIZE_OF(tsk) ((tsk)->mm ? \ |
2975 |
++ (tsk)->mm->context.asce_limit : TASK_MAX_SIZE) |
2976 |
+ #define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \ |
2977 |
+ (1UL << 30) : (1UL << 41)) |
2978 |
+ #define TASK_SIZE TASK_SIZE_OF(current) |
2979 |
+diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c |
2980 |
+index e80d9ff9a56d..ec3b505238cb 100644 |
2981 |
+--- a/arch/s390/kernel/setup.c |
2982 |
++++ b/arch/s390/kernel/setup.c |
2983 |
+@@ -822,10 +822,10 @@ static void __init setup_randomness(void) |
2984 |
+ { |
2985 |
+ struct sysinfo_3_2_2 *vmms; |
2986 |
+ |
2987 |
+- vmms = (struct sysinfo_3_2_2 *) alloc_page(GFP_KERNEL); |
2988 |
+- if (vmms && stsi(vmms, 3, 2, 2) == 0 && vmms->count) |
2989 |
+- add_device_randomness(&vmms, vmms->count); |
2990 |
+- free_page((unsigned long) vmms); |
2991 |
++ vmms = (struct sysinfo_3_2_2 *) memblock_alloc(PAGE_SIZE, PAGE_SIZE); |
2992 |
++ if (stsi(vmms, 3, 2, 2) == 0 && vmms->count) |
2993 |
++ add_device_randomness(&vmms->vm, sizeof(vmms->vm[0]) * vmms->count); |
2994 |
++ memblock_free((unsigned long) vmms, PAGE_SIZE); |
2995 |
+ } |
2996 |
+ |
2997 |
+ /* |
2998 |
+diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c |
2999 |
+index 49e4d64ff74d..0ce029c73ca3 100644 |
3000 |
+--- a/arch/s390/kvm/kvm-s390.c |
3001 |
++++ b/arch/s390/kvm/kvm-s390.c |
3002 |
+@@ -207,6 +207,9 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, |
3003 |
+ struct kvm_memory_slot *memslot; |
3004 |
+ int is_dirty = 0; |
3005 |
+ |
3006 |
++ if (kvm_is_ucontrol(kvm)) |
3007 |
++ return -EINVAL; |
3008 |
++ |
3009 |
+ mutex_lock(&kvm->slots_lock); |
3010 |
+ |
3011 |
+ r = -EINVAL; |
3012 |
+diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c |
3013 |
+index 35fde2a24751..d0f59879cdca 100644 |
3014 |
+--- a/arch/s390/mm/pgtable.c |
3015 |
++++ b/arch/s390/mm/pgtable.c |
3016 |
+@@ -1358,11 +1358,28 @@ EXPORT_SYMBOL_GPL(s390_enable_skey); |
3017 |
+ */ |
3018 |
+ bool gmap_test_and_clear_dirty(unsigned long address, struct gmap *gmap) |
3019 |
+ { |
3020 |
++ pgd_t *pgd; |
3021 |
++ pud_t *pud; |
3022 |
++ pmd_t *pmd; |
3023 |
+ pte_t *pte; |
3024 |
+ spinlock_t *ptl; |
3025 |
+ bool dirty = false; |
3026 |
+ |
3027 |
+- pte = get_locked_pte(gmap->mm, address, &ptl); |
3028 |
++ pgd = pgd_offset(gmap->mm, address); |
3029 |
++ pud = pud_alloc(gmap->mm, pgd, address); |
3030 |
++ if (!pud) |
3031 |
++ return false; |
3032 |
++ pmd = pmd_alloc(gmap->mm, pud, address); |
3033 |
++ if (!pmd) |
3034 |
++ return false; |
3035 |
++ /* We can't run guests backed by huge pages, but userspace can |
3036 |
++ * still set them up and then try to migrate them without any |
3037 |
++ * migration support. |
3038 |
++ */ |
3039 |
++ if (pmd_large(*pmd)) |
3040 |
++ return true; |
3041 |
++ |
3042 |
++ pte = pte_alloc_map_lock(gmap->mm, pmd, address, &ptl); |
3043 |
+ if (unlikely(!pte)) |
3044 |
+ return false; |
3045 |
+ |
3046 |
+diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c |
3047 |
+index de1d72e3ec59..2f5cd2f62a2b 100644 |
3048 |
+--- a/arch/x86/crypto/ghash-clmulni-intel_glue.c |
3049 |
++++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c |
3050 |
+@@ -218,6 +218,29 @@ static int ghash_async_final(struct ahash_request *req) |
3051 |
+ } |
3052 |
+ } |
3053 |
+ |
3054 |
++static int ghash_async_import(struct ahash_request *req, const void *in) |
3055 |
++{ |
3056 |
++ struct ahash_request *cryptd_req = ahash_request_ctx(req); |
3057 |
++ struct shash_desc *desc = cryptd_shash_desc(cryptd_req); |
3058 |
++ struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); |
3059 |
++ |
3060 |
++ ghash_async_init(req); |
3061 |
++ memcpy(dctx, in, sizeof(*dctx)); |
3062 |
++ return 0; |
3063 |
++ |
3064 |
++} |
3065 |
++ |
3066 |
++static int ghash_async_export(struct ahash_request *req, void *out) |
3067 |
++{ |
3068 |
++ struct ahash_request *cryptd_req = ahash_request_ctx(req); |
3069 |
++ struct shash_desc *desc = cryptd_shash_desc(cryptd_req); |
3070 |
++ struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); |
3071 |
++ |
3072 |
++ memcpy(out, dctx, sizeof(*dctx)); |
3073 |
++ return 0; |
3074 |
++ |
3075 |
++} |
3076 |
++ |
3077 |
+ static int ghash_async_digest(struct ahash_request *req) |
3078 |
+ { |
3079 |
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); |
3080 |
+@@ -285,8 +308,11 @@ static struct ahash_alg ghash_async_alg = { |
3081 |
+ .final = ghash_async_final, |
3082 |
+ .setkey = ghash_async_setkey, |
3083 |
+ .digest = ghash_async_digest, |
3084 |
++ .export = ghash_async_export, |
3085 |
++ .import = ghash_async_import, |
3086 |
+ .halg = { |
3087 |
+ .digestsize = GHASH_DIGEST_SIZE, |
3088 |
++ .statesize = sizeof(struct ghash_desc_ctx), |
3089 |
+ .base = { |
3090 |
+ .cra_name = "ghash", |
3091 |
+ .cra_driver_name = "ghash-clmulni", |
3092 |
+diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h |
3093 |
+index 8e046ade1c88..504be087d682 100644 |
3094 |
+--- a/arch/x86/include/asm/uaccess.h |
3095 |
++++ b/arch/x86/include/asm/uaccess.h |
3096 |
+@@ -329,7 +329,7 @@ do { \ |
3097 |
+ #define __get_user_asm_u64(x, ptr, retval, errret) \ |
3098 |
+ __get_user_asm(x, ptr, retval, "q", "", "=r", errret) |
3099 |
+ #define __get_user_asm_ex_u64(x, ptr) \ |
3100 |
+- __get_user_asm_ex(x, ptr, "q", "", "=r") |
3101 |
++ __get_user_asm_ex(x, ptr, "q", "", "=&r") |
3102 |
+ #endif |
3103 |
+ |
3104 |
+ #define __get_user_size(x, ptr, size, retval, errret) \ |
3105 |
+@@ -372,13 +372,13 @@ do { \ |
3106 |
+ __chk_user_ptr(ptr); \ |
3107 |
+ switch (size) { \ |
3108 |
+ case 1: \ |
3109 |
+- __get_user_asm_ex(x, ptr, "b", "b", "=q"); \ |
3110 |
++ __get_user_asm_ex(x, ptr, "b", "b", "=&q"); \ |
3111 |
+ break; \ |
3112 |
+ case 2: \ |
3113 |
+- __get_user_asm_ex(x, ptr, "w", "w", "=r"); \ |
3114 |
++ __get_user_asm_ex(x, ptr, "w", "w", "=&r"); \ |
3115 |
+ break; \ |
3116 |
+ case 4: \ |
3117 |
+- __get_user_asm_ex(x, ptr, "l", "k", "=r"); \ |
3118 |
++ __get_user_asm_ex(x, ptr, "l", "k", "=&r"); \ |
3119 |
+ break; \ |
3120 |
+ case 8: \ |
3121 |
+ __get_user_asm_ex_u64(x, ptr); \ |
3122 |
+@@ -396,7 +396,7 @@ do { \ |
3123 |
+ " jmp 2b\n" \ |
3124 |
+ ".previous\n" \ |
3125 |
+ _ASM_EXTABLE_EX(1b, 3b) \ |
3126 |
+- : ltype(x) : "m" (__m(addr))) |
3127 |
++ : ltype(x) : "m" (__m(addr)), "0" (0)) |
3128 |
+ |
3129 |
+ #define __put_user_nocheck(x, ptr, size) \ |
3130 |
+ ({ \ |
3131 |
+diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c |
3132 |
+index 06370ccea9e9..b70097e7f37a 100644 |
3133 |
+--- a/arch/xtensa/kernel/setup.c |
3134 |
++++ b/arch/xtensa/kernel/setup.c |
3135 |
+@@ -133,6 +133,8 @@ static int __init parse_tag_initrd(const bp_tag_t* tag) |
3136 |
+ |
3137 |
+ __tagtable(BP_TAG_INITRD, parse_tag_initrd); |
3138 |
+ |
3139 |
++#endif /* CONFIG_BLK_DEV_INITRD */ |
3140 |
++ |
3141 |
+ #ifdef CONFIG_OF |
3142 |
+ |
3143 |
+ static int __init parse_tag_fdt(const bp_tag_t *tag) |
3144 |
+@@ -145,8 +147,6 @@ __tagtable(BP_TAG_FDT, parse_tag_fdt); |
3145 |
+ |
3146 |
+ #endif /* CONFIG_OF */ |
3147 |
+ |
3148 |
+-#endif /* CONFIG_BLK_DEV_INITRD */ |
3149 |
+- |
3150 |
+ static int __init parse_tag_cmdline(const bp_tag_t* tag) |
3151 |
+ { |
3152 |
+ strlcpy(command_line, (char *)(tag->data), COMMAND_LINE_SIZE); |
3153 |
+diff --git a/crypto/Makefile b/crypto/Makefile |
3154 |
+index 1445b9100c05..ea11cf871ebc 100644 |
3155 |
+--- a/crypto/Makefile |
3156 |
++++ b/crypto/Makefile |
3157 |
+@@ -47,6 +47,7 @@ obj-$(CONFIG_CRYPTO_SHA1) += sha1_generic.o |
3158 |
+ obj-$(CONFIG_CRYPTO_SHA256) += sha256_generic.o |
3159 |
+ obj-$(CONFIG_CRYPTO_SHA512) += sha512_generic.o |
3160 |
+ obj-$(CONFIG_CRYPTO_WP512) += wp512.o |
3161 |
++CFLAGS_wp512.o := $(call cc-option,-fno-schedule-insns) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149 |
3162 |
+ obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o |
3163 |
+ obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o |
3164 |
+ obj-$(CONFIG_CRYPTO_ECB) += ecb.o |
3165 |
+@@ -68,6 +69,7 @@ obj-$(CONFIG_CRYPTO_BLOWFISH_COMMON) += blowfish_common.o |
3166 |
+ obj-$(CONFIG_CRYPTO_TWOFISH) += twofish_generic.o |
3167 |
+ obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o |
3168 |
+ obj-$(CONFIG_CRYPTO_SERPENT) += serpent_generic.o |
3169 |
++CFLAGS_serpent_generic.o := $(call cc-option,-fsched-pressure) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149 |
3170 |
+ obj-$(CONFIG_CRYPTO_AES) += aes_generic.o |
3171 |
+ obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia_generic.o |
3172 |
+ obj-$(CONFIG_CRYPTO_CAST_COMMON) += cast_common.o |
3173 |
+diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c |
3174 |
+index df99445a899a..9eb8174aa58c 100644 |
3175 |
+--- a/crypto/algif_hash.c |
3176 |
++++ b/crypto/algif_hash.c |
3177 |
+@@ -195,7 +195,7 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags) |
3178 |
+ struct alg_sock *ask = alg_sk(sk); |
3179 |
+ struct hash_ctx *ctx = ask->private; |
3180 |
+ struct ahash_request *req = &ctx->req; |
3181 |
+- char state[crypto_ahash_statesize(crypto_ahash_reqtfm(req))]; |
3182 |
++ char state[crypto_ahash_statesize(crypto_ahash_reqtfm(req)) ? : 1]; |
3183 |
+ struct sock *sk2; |
3184 |
+ struct alg_sock *ask2; |
3185 |
+ struct hash_ctx *ctx2; |
3186 |
+diff --git a/crypto/cryptd.c b/crypto/cryptd.c |
3187 |
+index be367e43ffe8..fb0d140065e2 100644 |
3188 |
+--- a/crypto/cryptd.c |
3189 |
++++ b/crypto/cryptd.c |
3190 |
+@@ -606,6 +606,7 @@ static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, |
3191 |
+ inst->alg.halg.base.cra_flags = CRYPTO_ALG_ASYNC; |
3192 |
+ |
3193 |
+ inst->alg.halg.digestsize = salg->digestsize; |
3194 |
++ inst->alg.halg.statesize = salg->statesize; |
3195 |
+ inst->alg.halg.base.cra_ctxsize = sizeof(struct cryptd_hash_ctx); |
3196 |
+ |
3197 |
+ inst->alg.halg.base.cra_init = cryptd_hash_init_tfm; |
3198 |
+diff --git a/crypto/mcryptd.c b/crypto/mcryptd.c |
3199 |
+index a8e870444ea9..02a1c10fa909 100644 |
3200 |
+--- a/crypto/mcryptd.c |
3201 |
++++ b/crypto/mcryptd.c |
3202 |
+@@ -505,6 +505,7 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, |
3203 |
+ inst->alg.halg.base.cra_flags = CRYPTO_ALG_ASYNC; |
3204 |
+ |
3205 |
+ inst->alg.halg.digestsize = salg->digestsize; |
3206 |
++ inst->alg.halg.statesize = salg->statesize; |
3207 |
+ inst->alg.halg.base.cra_ctxsize = sizeof(struct mcryptd_hash_ctx); |
3208 |
+ |
3209 |
+ inst->alg.halg.base.cra_init = mcryptd_hash_init_tfm; |
3210 |
+diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c |
3211 |
+index 973c185c9cfe..a31b282de8e0 100644 |
3212 |
+--- a/drivers/block/drbd/drbd_main.c |
3213 |
++++ b/drivers/block/drbd/drbd_main.c |
3214 |
+@@ -1802,7 +1802,7 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock, |
3215 |
+ * do we need to block DRBD_SIG if sock == &meta.socket ?? |
3216 |
+ * otherwise wake_asender() might interrupt some send_*Ack ! |
3217 |
+ */ |
3218 |
+- rv = kernel_sendmsg(sock, &msg, &iov, 1, size); |
3219 |
++ rv = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len); |
3220 |
+ if (rv == -EAGAIN) { |
3221 |
+ if (we_should_drop_the_connection(connection, sock)) |
3222 |
+ break; |
3223 |
+diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c |
3224 |
+index 036969223c16..0b4b67b859e2 100644 |
3225 |
+--- a/drivers/bluetooth/ath3k.c |
3226 |
++++ b/drivers/bluetooth/ath3k.c |
3227 |
+@@ -94,6 +94,7 @@ static const struct usb_device_id ath3k_table[] = { |
3228 |
+ { USB_DEVICE(0x04CA, 0x300f) }, |
3229 |
+ { USB_DEVICE(0x04CA, 0x3010) }, |
3230 |
+ { USB_DEVICE(0x04CA, 0x3014) }, |
3231 |
++ { USB_DEVICE(0x04CA, 0x3018) }, |
3232 |
+ { USB_DEVICE(0x0930, 0x0219) }, |
3233 |
+ { USB_DEVICE(0x0930, 0x0220) }, |
3234 |
+ { USB_DEVICE(0x0930, 0x0227) }, |
3235 |
+@@ -160,6 +161,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { |
3236 |
+ { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 }, |
3237 |
+ { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, |
3238 |
+ { USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 }, |
3239 |
++ { USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 }, |
3240 |
+ { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, |
3241 |
+ { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, |
3242 |
+ { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 }, |
3243 |
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c |
3244 |
+index 2dd73a3e95a2..ce9a00a5c5ca 100644 |
3245 |
+--- a/drivers/bluetooth/btusb.c |
3246 |
++++ b/drivers/bluetooth/btusb.c |
3247 |
+@@ -186,6 +186,7 @@ static const struct usb_device_id blacklist_table[] = { |
3248 |
+ { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 }, |
3249 |
+ { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, |
3250 |
+ { USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 }, |
3251 |
++ { USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 }, |
3252 |
+ { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, |
3253 |
+ { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, |
3254 |
+ { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 }, |
3255 |
+diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c |
3256 |
+index 810c51d92b99..30672a3df8a9 100644 |
3257 |
+--- a/drivers/gpu/drm/ast/ast_post.c |
3258 |
++++ b/drivers/gpu/drm/ast/ast_post.c |
3259 |
+@@ -58,13 +58,9 @@ bool ast_is_vga_enabled(struct drm_device *dev) |
3260 |
+ /* TODO 1180 */ |
3261 |
+ } else { |
3262 |
+ ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT); |
3263 |
+- if (ch) { |
3264 |
+- ast_open_key(ast); |
3265 |
+- ch = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff); |
3266 |
+- return ch & 0x04; |
3267 |
+- } |
3268 |
++ return !!(ch & 0x01); |
3269 |
+ } |
3270 |
+- return 0; |
3271 |
++ return false; |
3272 |
+ } |
3273 |
+ |
3274 |
+ static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff }; |
3275 |
+@@ -375,8 +371,8 @@ void ast_post_gpu(struct drm_device *dev) |
3276 |
+ pci_write_config_dword(ast->dev->pdev, 0x04, reg); |
3277 |
+ |
3278 |
+ ast_enable_vga(dev); |
3279 |
+- ast_enable_mmio(dev); |
3280 |
+ ast_open_key(ast); |
3281 |
++ ast_enable_mmio(dev); |
3282 |
+ ast_set_def_ext_reg(dev); |
3283 |
+ |
3284 |
+ if (ast->chip == AST2300 || ast->chip == AST2400) |
3285 |
+@@ -1630,12 +1626,44 @@ static void ast_init_dram_2300(struct drm_device *dev) |
3286 |
+ temp |= 0x73; |
3287 |
+ ast_write32(ast, 0x12008, temp); |
3288 |
+ |
3289 |
++ param.dram_freq = 396; |
3290 |
+ param.dram_type = AST_DDR3; |
3291 |
++ temp = ast_mindwm(ast, 0x1e6e2070); |
3292 |
+ if (temp & 0x01000000) |
3293 |
+ param.dram_type = AST_DDR2; |
3294 |
+- param.dram_chipid = ast->dram_type; |
3295 |
+- param.dram_freq = ast->mclk; |
3296 |
+- param.vram_size = ast->vram_size; |
3297 |
++ switch (temp & 0x18000000) { |
3298 |
++ case 0: |
3299 |
++ param.dram_chipid = AST_DRAM_512Mx16; |
3300 |
++ break; |
3301 |
++ default: |
3302 |
++ case 0x08000000: |
3303 |
++ param.dram_chipid = AST_DRAM_1Gx16; |
3304 |
++ break; |
3305 |
++ case 0x10000000: |
3306 |
++ param.dram_chipid = AST_DRAM_2Gx16; |
3307 |
++ break; |
3308 |
++ case 0x18000000: |
3309 |
++ param.dram_chipid = AST_DRAM_4Gx16; |
3310 |
++ break; |
3311 |
++ } |
3312 |
++ switch (temp & 0x0c) { |
3313 |
++ default: |
3314 |
++ case 0x00: |
3315 |
++ param.vram_size = AST_VIDMEM_SIZE_8M; |
3316 |
++ break; |
3317 |
++ |
3318 |
++ case 0x04: |
3319 |
++ param.vram_size = AST_VIDMEM_SIZE_16M; |
3320 |
++ break; |
3321 |
++ |
3322 |
++ case 0x08: |
3323 |
++ param.vram_size = AST_VIDMEM_SIZE_32M; |
3324 |
++ break; |
3325 |
++ |
3326 |
++ case 0x0c: |
3327 |
++ param.vram_size = AST_VIDMEM_SIZE_64M; |
3328 |
++ break; |
3329 |
++ } |
3330 |
+ |
3331 |
+ if (param.dram_type == AST_DDR3) { |
3332 |
+ get_ddr3_info(ast, ¶m); |
3333 |
+diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c |
3334 |
+index 4c9f972eaa07..ba64d23b90a7 100644 |
3335 |
+--- a/drivers/gpu/drm/exynos/exynos_drm_core.c |
3336 |
++++ b/drivers/gpu/drm/exynos/exynos_drm_core.c |
3337 |
+@@ -141,7 +141,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file) |
3338 |
+ return 0; |
3339 |
+ |
3340 |
+ err: |
3341 |
+- list_for_each_entry_reverse(subdrv, &subdrv->list, list) { |
3342 |
++ list_for_each_entry_continue_reverse(subdrv, &exynos_drm_subdrv_list, list) { |
3343 |
+ if (subdrv->close) |
3344 |
+ subdrv->close(dev, subdrv->dev, file); |
3345 |
+ } |
3346 |
+diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c |
3347 |
+index 7370202c2022..4ca35798b0b2 100644 |
3348 |
+--- a/drivers/gpu/drm/ttm/ttm_bo.c |
3349 |
++++ b/drivers/gpu/drm/ttm/ttm_bo.c |
3350 |
+@@ -1617,7 +1617,6 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink) |
3351 |
+ struct ttm_buffer_object *bo; |
3352 |
+ int ret = -EBUSY; |
3353 |
+ int put_count; |
3354 |
+- uint32_t swap_placement = (TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM); |
3355 |
+ |
3356 |
+ spin_lock(&glob->lru_lock); |
3357 |
+ list_for_each_entry(bo, &glob->swap_lru, swap) { |
3358 |
+@@ -1653,7 +1652,8 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink) |
3359 |
+ if (unlikely(ret != 0)) |
3360 |
+ goto out; |
3361 |
+ |
3362 |
+- if ((bo->mem.placement & swap_placement) != swap_placement) { |
3363 |
++ if (bo->mem.mem_type != TTM_PL_SYSTEM || |
3364 |
++ bo->ttm->caching_state != tt_cached) { |
3365 |
+ struct ttm_mem_reg evict_mem; |
3366 |
+ |
3367 |
+ evict_mem = bo->mem; |
3368 |
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h |
3369 |
+index 984e43cb83f0..213f616e7a1f 100644 |
3370 |
+--- a/drivers/hid/hid-ids.h |
3371 |
++++ b/drivers/hid/hid-ids.h |
3372 |
+@@ -168,6 +168,7 @@ |
3373 |
+ #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 |
3374 |
+ #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 |
3375 |
+ #define USB_DEVICE_ID_ATEN_CS682 0x2213 |
3376 |
++#define USB_DEVICE_ID_ATEN_CS692 0x8021 |
3377 |
+ |
3378 |
+ #define USB_VENDOR_ID_ATMEL 0x03eb |
3379 |
+ #define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c |
3380 |
+diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c |
3381 |
+index f7dd36e4fcb3..999dff00b214 100644 |
3382 |
+--- a/drivers/hid/usbhid/hid-quirks.c |
3383 |
++++ b/drivers/hid/usbhid/hid-quirks.c |
3384 |
+@@ -61,6 +61,7 @@ static const struct hid_blacklist { |
3385 |
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, |
3386 |
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, |
3387 |
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682, HID_QUIRK_NOGET }, |
3388 |
++ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692, HID_QUIRK_NOGET }, |
3389 |
+ { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK, HID_QUIRK_NOGET }, |
3390 |
+ { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET }, |
3391 |
+ { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET }, |
3392 |
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c |
3393 |
+index 933efcea0d03..cdf0a78e0c99 100644 |
3394 |
+--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c |
3395 |
++++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c |
3396 |
+@@ -1478,12 +1478,14 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, |
3397 |
+ |
3398 |
+ ret = ipoib_set_mode(dev, buf); |
3399 |
+ |
3400 |
+- rtnl_unlock(); |
3401 |
+- |
3402 |
+- if (!ret) |
3403 |
+- return count; |
3404 |
++ /* The assumption is that the function ipoib_set_mode returned |
3405 |
++ * with the rtnl held by it, if not the value -EBUSY returned, |
3406 |
++ * then no need to rtnl_unlock |
3407 |
++ */ |
3408 |
++ if (ret != -EBUSY) |
3409 |
++ rtnl_unlock(); |
3410 |
+ |
3411 |
+- return ret; |
3412 |
++ return (!ret || ret == -EBUSY) ? count : ret; |
3413 |
+ } |
3414 |
+ |
3415 |
+ static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode); |
3416 |
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c |
3417 |
+index 58b5aa3b6f2d..483ddbd1bdc8 100644 |
3418 |
+--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c |
3419 |
++++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c |
3420 |
+@@ -236,8 +236,7 @@ int ipoib_set_mode(struct net_device *dev, const char *buf) |
3421 |
+ priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; |
3422 |
+ |
3423 |
+ ipoib_flush_paths(dev); |
3424 |
+- rtnl_lock(); |
3425 |
+- return 0; |
3426 |
++ return (!rtnl_trylock()) ? -EBUSY : 0; |
3427 |
+ } |
3428 |
+ |
3429 |
+ if (!strcmp(buf, "datagram\n")) { |
3430 |
+@@ -246,8 +245,7 @@ int ipoib_set_mode(struct net_device *dev, const char *buf) |
3431 |
+ dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu)); |
3432 |
+ rtnl_unlock(); |
3433 |
+ ipoib_flush_paths(dev); |
3434 |
+- rtnl_lock(); |
3435 |
+- return 0; |
3436 |
++ return (!rtnl_trylock()) ? -EBUSY : 0; |
3437 |
+ } |
3438 |
+ |
3439 |
+ return -EINVAL; |
3440 |
+diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c |
3441 |
+index 8d9ba0c3827c..94ab494a6ade 100644 |
3442 |
+--- a/drivers/input/serio/gscps2.c |
3443 |
++++ b/drivers/input/serio/gscps2.c |
3444 |
+@@ -40,7 +40,6 @@ |
3445 |
+ MODULE_AUTHOR("Laurent Canet <canetl@×××××.fr>, Thibaut Varene <varenet@××××××××××××.org>, Helge Deller <deller@×××.de>"); |
3446 |
+ MODULE_DESCRIPTION("HP GSC PS2 port driver"); |
3447 |
+ MODULE_LICENSE("GPL"); |
3448 |
+-MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl); |
3449 |
+ |
3450 |
+ #define PFX "gscps2.c: " |
3451 |
+ |
3452 |
+@@ -439,6 +438,7 @@ static struct parisc_device_id gscps2_device_tbl[] = { |
3453 |
+ #endif |
3454 |
+ { 0, } /* 0 terminated list */ |
3455 |
+ }; |
3456 |
++MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl); |
3457 |
+ |
3458 |
+ static struct parisc_driver parisc_ps2_driver = { |
3459 |
+ .name = "gsc_ps2", |
3460 |
+diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c |
3461 |
+index 8a0643ae1fd9..6b78e131f6dd 100644 |
3462 |
+--- a/drivers/iommu/dmar.c |
3463 |
++++ b/drivers/iommu/dmar.c |
3464 |
+@@ -317,7 +317,9 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb, |
3465 |
+ struct pci_dev *pdev = to_pci_dev(data); |
3466 |
+ struct dmar_pci_notify_info *info; |
3467 |
+ |
3468 |
+- /* Only care about add/remove events for physical functions */ |
3469 |
++ /* Only care about add/remove events for physical functions. |
3470 |
++ * For VFs we actually do the lookup based on the corresponding |
3471 |
++ * PF in device_to_iommu() anyway. */ |
3472 |
+ if (pdev->is_virtfn) |
3473 |
+ return NOTIFY_DONE; |
3474 |
+ if (action != BUS_NOTIFY_ADD_DEVICE && action != BUS_NOTIFY_DEL_DEVICE) |
3475 |
+diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c |
3476 |
+index 3d1fc736a420..1689632e4e92 100644 |
3477 |
+--- a/drivers/iommu/intel-iommu.c |
3478 |
++++ b/drivers/iommu/intel-iommu.c |
3479 |
+@@ -696,7 +696,13 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf |
3480 |
+ int i; |
3481 |
+ |
3482 |
+ if (dev_is_pci(dev)) { |
3483 |
++ struct pci_dev *pf_pdev; |
3484 |
++ |
3485 |
+ pdev = to_pci_dev(dev); |
3486 |
++ /* VFs aren't listed in scope tables; we need to look up |
3487 |
++ * the PF instead to find the IOMMU. */ |
3488 |
++ pf_pdev = pci_physfn(pdev); |
3489 |
++ dev = &pf_pdev->dev; |
3490 |
+ segment = pci_domain_nr(pdev->bus); |
3491 |
+ } else if (ACPI_COMPANION(dev)) |
3492 |
+ dev = &ACPI_COMPANION(dev)->dev; |
3493 |
+@@ -709,6 +715,13 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf |
3494 |
+ for_each_active_dev_scope(drhd->devices, |
3495 |
+ drhd->devices_cnt, i, tmp) { |
3496 |
+ if (tmp == dev) { |
3497 |
++ /* For a VF use its original BDF# not that of the PF |
3498 |
++ * which we used for the IOMMU lookup. Strictly speaking |
3499 |
++ * we could do this for all PCI devices; we only need to |
3500 |
++ * get the BDF# from the scope table for ACPI matches. */ |
3501 |
++ if (pdev->is_virtfn) |
3502 |
++ goto got_pdev; |
3503 |
++ |
3504 |
+ *bus = drhd->devices[i].bus; |
3505 |
+ *devfn = drhd->devices[i].devfn; |
3506 |
+ goto out; |
3507 |
+diff --git a/drivers/md/dm.c b/drivers/md/dm.c |
3508 |
+index 042114fbd200..fb07be386287 100644 |
3509 |
+--- a/drivers/md/dm.c |
3510 |
++++ b/drivers/md/dm.c |
3511 |
+@@ -1300,11 +1300,62 @@ void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors) |
3512 |
+ } |
3513 |
+ EXPORT_SYMBOL_GPL(dm_accept_partial_bio); |
3514 |
+ |
3515 |
++/* |
3516 |
++ * Flush current->bio_list when the target map method blocks. |
3517 |
++ * This fixes deadlocks in snapshot and possibly in other targets. |
3518 |
++ */ |
3519 |
++struct dm_offload { |
3520 |
++ struct blk_plug plug; |
3521 |
++ struct blk_plug_cb cb; |
3522 |
++}; |
3523 |
++ |
3524 |
++static void flush_current_bio_list(struct blk_plug_cb *cb, bool from_schedule) |
3525 |
++{ |
3526 |
++ struct dm_offload *o = container_of(cb, struct dm_offload, cb); |
3527 |
++ struct bio_list list; |
3528 |
++ struct bio *bio; |
3529 |
++ |
3530 |
++ INIT_LIST_HEAD(&o->cb.list); |
3531 |
++ |
3532 |
++ if (unlikely(!current->bio_list)) |
3533 |
++ return; |
3534 |
++ |
3535 |
++ list = *current->bio_list; |
3536 |
++ bio_list_init(current->bio_list); |
3537 |
++ |
3538 |
++ while ((bio = bio_list_pop(&list))) { |
3539 |
++ struct bio_set *bs = bio->bi_pool; |
3540 |
++ if (unlikely(!bs) || bs == fs_bio_set) { |
3541 |
++ bio_list_add(current->bio_list, bio); |
3542 |
++ continue; |
3543 |
++ } |
3544 |
++ |
3545 |
++ spin_lock(&bs->rescue_lock); |
3546 |
++ bio_list_add(&bs->rescue_list, bio); |
3547 |
++ queue_work(bs->rescue_workqueue, &bs->rescue_work); |
3548 |
++ spin_unlock(&bs->rescue_lock); |
3549 |
++ } |
3550 |
++} |
3551 |
++ |
3552 |
++static void dm_offload_start(struct dm_offload *o) |
3553 |
++{ |
3554 |
++ blk_start_plug(&o->plug); |
3555 |
++ o->cb.callback = flush_current_bio_list; |
3556 |
++ list_add(&o->cb.list, ¤t->plug->cb_list); |
3557 |
++} |
3558 |
++ |
3559 |
++static void dm_offload_end(struct dm_offload *o) |
3560 |
++{ |
3561 |
++ list_del(&o->cb.list); |
3562 |
++ blk_finish_plug(&o->plug); |
3563 |
++} |
3564 |
++ |
3565 |
+ static void __map_bio(struct dm_target_io *tio) |
3566 |
+ { |
3567 |
+ int r; |
3568 |
+ sector_t sector; |
3569 |
+ struct mapped_device *md; |
3570 |
++ struct dm_offload o; |
3571 |
+ struct bio *clone = &tio->clone; |
3572 |
+ struct dm_target *ti = tio->ti; |
3573 |
+ |
3574 |
+@@ -1317,7 +1368,11 @@ static void __map_bio(struct dm_target_io *tio) |
3575 |
+ */ |
3576 |
+ atomic_inc(&tio->io->io_count); |
3577 |
+ sector = clone->bi_iter.bi_sector; |
3578 |
++ |
3579 |
++ dm_offload_start(&o); |
3580 |
+ r = ti->type->map(ti, clone); |
3581 |
++ dm_offload_end(&o); |
3582 |
++ |
3583 |
+ if (r == DM_MAPIO_REMAPPED) { |
3584 |
+ /* the bio has been remapped so dispatch it */ |
3585 |
+ |
3586 |
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c |
3587 |
+index 644f9e576736..3e4def3c2b9f 100644 |
3588 |
+--- a/drivers/md/raid10.c |
3589 |
++++ b/drivers/md/raid10.c |
3590 |
+@@ -1171,6 +1171,8 @@ static void __make_request(struct mddev *mddev, struct bio *bio) |
3591 |
+ int max_sectors; |
3592 |
+ int sectors; |
3593 |
+ |
3594 |
++ md_write_start(mddev, bio); |
3595 |
++ |
3596 |
+ /* |
3597 |
+ * Register the new request and wait if the reconstruction |
3598 |
+ * thread has put up a bar for new requests. |
3599 |
+@@ -1556,8 +1558,6 @@ static void make_request(struct mddev *mddev, struct bio *bio) |
3600 |
+ return; |
3601 |
+ } |
3602 |
+ |
3603 |
+- md_write_start(mddev, bio); |
3604 |
+- |
3605 |
+ do { |
3606 |
+ |
3607 |
+ /* |
3608 |
+diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c |
3609 |
+index 605b090c618b..b128624c56b8 100644 |
3610 |
+--- a/drivers/media/usb/dvb-usb/dib0700_core.c |
3611 |
++++ b/drivers/media/usb/dvb-usb/dib0700_core.c |
3612 |
+@@ -680,7 +680,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) |
3613 |
+ struct dvb_usb_device *d = purb->context; |
3614 |
+ struct dib0700_rc_response *poll_reply; |
3615 |
+ enum rc_type protocol; |
3616 |
+- u32 uninitialized_var(keycode); |
3617 |
++ u32 keycode; |
3618 |
+ u8 toggle; |
3619 |
+ |
3620 |
+ deb_info("%s()\n", __func__); |
3621 |
+@@ -722,7 +722,8 @@ static void dib0700_rc_urb_completion(struct urb *purb) |
3622 |
+ poll_reply->nec.data == 0x00 && |
3623 |
+ poll_reply->nec.not_data == 0xff) { |
3624 |
+ poll_reply->data_state = 2; |
3625 |
+- break; |
3626 |
++ rc_repeat(d->rc_dev); |
3627 |
++ goto resubmit; |
3628 |
+ } |
3629 |
+ |
3630 |
+ if ((poll_reply->nec.data ^ poll_reply->nec.not_data) != 0xff) { |
3631 |
+diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c |
3632 |
+index 744ca5cacc9b..cf54420f943d 100644 |
3633 |
+--- a/drivers/mtd/maps/pmcmsp-flash.c |
3634 |
++++ b/drivers/mtd/maps/pmcmsp-flash.c |
3635 |
+@@ -139,15 +139,13 @@ static int __init init_msp_flash(void) |
3636 |
+ } |
3637 |
+ |
3638 |
+ msp_maps[i].bankwidth = 1; |
3639 |
+- msp_maps[i].name = kmalloc(7, GFP_KERNEL); |
3640 |
++ msp_maps[i].name = kstrndup(flash_name, 7, GFP_KERNEL); |
3641 |
+ if (!msp_maps[i].name) { |
3642 |
+ iounmap(msp_maps[i].virt); |
3643 |
+ kfree(msp_parts[i]); |
3644 |
+ goto cleanup_loop; |
3645 |
+ } |
3646 |
+ |
3647 |
+- msp_maps[i].name = strncpy(msp_maps[i].name, flash_name, 7); |
3648 |
+- |
3649 |
+ for (j = 0; j < pcnt; j++) { |
3650 |
+ part_name[5] = '0' + i; |
3651 |
+ part_name[7] = '0' + j; |
3652 |
+diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c |
3653 |
+index 9d38605717a0..303f69149439 100644 |
3654 |
+--- a/drivers/mtd/ubi/fastmap.c |
3655 |
++++ b/drivers/mtd/ubi/fastmap.c |
3656 |
+@@ -446,10 +446,11 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, |
3657 |
+ unsigned long long ec = be64_to_cpu(ech->ec); |
3658 |
+ unmap_peb(ai, pnum); |
3659 |
+ dbg_bld("Adding PEB to free: %i", pnum); |
3660 |
++ |
3661 |
+ if (err == UBI_IO_FF_BITFLIPS) |
3662 |
+- add_aeb(ai, free, pnum, ec, 1); |
3663 |
+- else |
3664 |
+- add_aeb(ai, free, pnum, ec, 0); |
3665 |
++ scrub = 1; |
3666 |
++ |
3667 |
++ add_aeb(ai, free, pnum, ec, scrub); |
3668 |
+ continue; |
3669 |
+ } else if (err == 0 || err == UBI_IO_BITFLIPS) { |
3670 |
+ dbg_bld("Found non empty PEB:%i in pool", pnum); |
3671 |
+diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c |
3672 |
+index 56022d647837..f0cab2d3532f 100644 |
3673 |
+--- a/drivers/net/ethernet/mellanox/mlx4/cq.c |
3674 |
++++ b/drivers/net/ethernet/mellanox/mlx4/cq.c |
3675 |
+@@ -56,13 +56,19 @@ void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn) |
3676 |
+ { |
3677 |
+ struct mlx4_cq *cq; |
3678 |
+ |
3679 |
++ rcu_read_lock(); |
3680 |
+ cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree, |
3681 |
+ cqn & (dev->caps.num_cqs - 1)); |
3682 |
++ rcu_read_unlock(); |
3683 |
++ |
3684 |
+ if (!cq) { |
3685 |
+ mlx4_dbg(dev, "Completion event for bogus CQ %08x\n", cqn); |
3686 |
+ return; |
3687 |
+ } |
3688 |
+ |
3689 |
++ /* Acessing the CQ outside of rcu_read_lock is safe, because |
3690 |
++ * the CQ is freed only after interrupt handling is completed. |
3691 |
++ */ |
3692 |
+ ++cq->arm_sn; |
3693 |
+ |
3694 |
+ cq->comp(cq); |
3695 |
+@@ -73,23 +79,19 @@ void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type) |
3696 |
+ struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table; |
3697 |
+ struct mlx4_cq *cq; |
3698 |
+ |
3699 |
+- spin_lock(&cq_table->lock); |
3700 |
+- |
3701 |
++ rcu_read_lock(); |
3702 |
+ cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1)); |
3703 |
+- if (cq) |
3704 |
+- atomic_inc(&cq->refcount); |
3705 |
+- |
3706 |
+- spin_unlock(&cq_table->lock); |
3707 |
++ rcu_read_unlock(); |
3708 |
+ |
3709 |
+ if (!cq) { |
3710 |
+- mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn); |
3711 |
++ mlx4_dbg(dev, "Async event for bogus CQ %08x\n", cqn); |
3712 |
+ return; |
3713 |
+ } |
3714 |
+ |
3715 |
++ /* Acessing the CQ outside of rcu_read_lock is safe, because |
3716 |
++ * the CQ is freed only after interrupt handling is completed. |
3717 |
++ */ |
3718 |
+ cq->event(cq, event_type); |
3719 |
+- |
3720 |
+- if (atomic_dec_and_test(&cq->refcount)) |
3721 |
+- complete(&cq->free); |
3722 |
+ } |
3723 |
+ |
3724 |
+ static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, |
3725 |
+@@ -256,9 +258,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, |
3726 |
+ if (err) |
3727 |
+ return err; |
3728 |
+ |
3729 |
+- spin_lock_irq(&cq_table->lock); |
3730 |
++ spin_lock(&cq_table->lock); |
3731 |
+ err = radix_tree_insert(&cq_table->tree, cq->cqn, cq); |
3732 |
+- spin_unlock_irq(&cq_table->lock); |
3733 |
++ spin_unlock(&cq_table->lock); |
3734 |
+ if (err) |
3735 |
+ goto err_icm; |
3736 |
+ |
3737 |
+@@ -297,9 +299,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, |
3738 |
+ return 0; |
3739 |
+ |
3740 |
+ err_radix: |
3741 |
+- spin_lock_irq(&cq_table->lock); |
3742 |
++ spin_lock(&cq_table->lock); |
3743 |
+ radix_tree_delete(&cq_table->tree, cq->cqn); |
3744 |
+- spin_unlock_irq(&cq_table->lock); |
3745 |
++ spin_unlock(&cq_table->lock); |
3746 |
+ |
3747 |
+ err_icm: |
3748 |
+ mlx4_cq_free_icm(dev, cq->cqn); |
3749 |
+@@ -314,16 +316,16 @@ void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq) |
3750 |
+ struct mlx4_cq_table *cq_table = &priv->cq_table; |
3751 |
+ int err; |
3752 |
+ |
3753 |
++ spin_lock(&cq_table->lock); |
3754 |
++ radix_tree_delete(&cq_table->tree, cq->cqn); |
3755 |
++ spin_unlock(&cq_table->lock); |
3756 |
++ |
3757 |
+ err = mlx4_HW2SW_CQ(dev, NULL, cq->cqn); |
3758 |
+ if (err) |
3759 |
+ mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn); |
3760 |
+ |
3761 |
+ synchronize_irq(priv->eq_table.eq[cq->vector].irq); |
3762 |
+ |
3763 |
+- spin_lock_irq(&cq_table->lock); |
3764 |
+- radix_tree_delete(&cq_table->tree, cq->cqn); |
3765 |
+- spin_unlock_irq(&cq_table->lock); |
3766 |
+- |
3767 |
+ if (atomic_dec_and_test(&cq->refcount)) |
3768 |
+ complete(&cq->free); |
3769 |
+ wait_for_completion(&cq->free); |
3770 |
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c |
3771 |
+index 5bbb59dce4d5..c175938d9717 100644 |
3772 |
+--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c |
3773 |
++++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c |
3774 |
+@@ -438,8 +438,14 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv) |
3775 |
+ ring->cqn = priv->rx_cq[ring_ind]->mcq.cqn; |
3776 |
+ |
3777 |
+ ring->stride = stride; |
3778 |
+- if (ring->stride <= TXBB_SIZE) |
3779 |
++ if (ring->stride <= TXBB_SIZE) { |
3780 |
++ /* Stamp first unused send wqe */ |
3781 |
++ __be32 *ptr = (__be32 *)ring->buf; |
3782 |
++ __be32 stamp = cpu_to_be32(1 << STAMP_SHIFT); |
3783 |
++ *ptr = stamp; |
3784 |
++ /* Move pointer to start of rx section */ |
3785 |
+ ring->buf += TXBB_SIZE; |
3786 |
++ } |
3787 |
+ |
3788 |
+ ring->log_stride = ffs(ring->stride) - 1; |
3789 |
+ ring->buf_size = ring->size * ring->stride; |
3790 |
+@@ -501,8 +507,11 @@ void mlx4_en_recover_from_oom(struct mlx4_en_priv *priv) |
3791 |
+ return; |
3792 |
+ |
3793 |
+ for (ring = 0; ring < priv->rx_ring_num; ring++) { |
3794 |
+- if (mlx4_en_is_ring_empty(priv->rx_ring[ring])) |
3795 |
++ if (mlx4_en_is_ring_empty(priv->rx_ring[ring])) { |
3796 |
++ local_bh_disable(); |
3797 |
+ napi_reschedule(&priv->rx_cq[ring]->napi); |
3798 |
++ local_bh_enable(); |
3799 |
++ } |
3800 |
+ } |
3801 |
+ } |
3802 |
+ |
3803 |
+diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c |
3804 |
+index e57df91bad06..fbb0c02276f9 100644 |
3805 |
+--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c |
3806 |
++++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c |
3807 |
+@@ -2769,6 +2769,9 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave, |
3808 |
+ put_res(dev, slave, srqn, RES_SRQ); |
3809 |
+ qp->srq = srq; |
3810 |
+ } |
3811 |
++ |
3812 |
++ /* Save param3 for dynamic changes from VST back to VGT */ |
3813 |
++ qp->param3 = qpc->param3; |
3814 |
+ put_res(dev, slave, rcqn, RES_CQ); |
3815 |
+ put_res(dev, slave, mtt_base, RES_MTT); |
3816 |
+ res_end_move(dev, slave, RES_QP, qpn); |
3817 |
+@@ -3531,7 +3534,6 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave, |
3818 |
+ int qpn = vhcr->in_modifier & 0x7fffff; |
3819 |
+ struct res_qp *qp; |
3820 |
+ u8 orig_sched_queue; |
3821 |
+- __be32 orig_param3 = qpc->param3; |
3822 |
+ u8 orig_vlan_control = qpc->pri_path.vlan_control; |
3823 |
+ u8 orig_fvl_rx = qpc->pri_path.fvl_rx; |
3824 |
+ u8 orig_pri_path_fl = qpc->pri_path.fl; |
3825 |
+@@ -3572,7 +3574,6 @@ out: |
3826 |
+ */ |
3827 |
+ if (!err) { |
3828 |
+ qp->sched_queue = orig_sched_queue; |
3829 |
+- qp->param3 = orig_param3; |
3830 |
+ qp->vlan_control = orig_vlan_control; |
3831 |
+ qp->fvl_rx = orig_fvl_rx; |
3832 |
+ qp->pri_path_fl = orig_pri_path_fl; |
3833 |
+diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c |
3834 |
+index 6cc3cf6f17c8..9a289e79e8a7 100644 |
3835 |
+--- a/drivers/net/ethernet/smsc/smc91x.c |
3836 |
++++ b/drivers/net/ethernet/smsc/smc91x.c |
3837 |
+@@ -535,7 +535,7 @@ static inline void smc_rcv(struct net_device *dev) |
3838 |
+ #define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags) |
3839 |
+ #define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags) |
3840 |
+ #else |
3841 |
+-#define smc_special_trylock(lock, flags) (flags == flags) |
3842 |
++#define smc_special_trylock(lock, flags) ((void)flags, true) |
3843 |
+ #define smc_special_lock(lock, flags) do { flags = 0; } while (0) |
3844 |
+ #define smc_special_unlock(lock, flags) do { flags = 0; } while (0) |
3845 |
+ #endif |
3846 |
+diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c |
3847 |
+index dd9430043536..cf5ce371ec21 100644 |
3848 |
+--- a/drivers/net/ethernet/ti/cpmac.c |
3849 |
++++ b/drivers/net/ethernet/ti/cpmac.c |
3850 |
+@@ -1235,7 +1235,7 @@ int cpmac_init(void) |
3851 |
+ goto fail_alloc; |
3852 |
+ } |
3853 |
+ |
3854 |
+-#warning FIXME: unhardcode gpio&reset bits |
3855 |
++ /* FIXME: unhardcode gpio&reset bits */ |
3856 |
+ ar7_gpio_disable(26); |
3857 |
+ ar7_gpio_disable(27); |
3858 |
+ ar7_device_reset(AR7_RESET_BIT_CPMAC_LO); |
3859 |
+diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c |
3860 |
+index 59282dd2d9e0..2dc89582575a 100644 |
3861 |
+--- a/drivers/net/vxlan.c |
3862 |
++++ b/drivers/net/vxlan.c |
3863 |
+@@ -2260,7 +2260,7 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) |
3864 |
+ |
3865 |
+ if (data[IFLA_VXLAN_ID]) { |
3866 |
+ __u32 id = nla_get_u32(data[IFLA_VXLAN_ID]); |
3867 |
+- if (id >= VXLAN_VID_MASK) |
3868 |
++ if (id >= VXLAN_N_VID) |
3869 |
+ return -ERANGE; |
3870 |
+ } |
3871 |
+ |
3872 |
+diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c |
3873 |
+index 966497d10c6e..f3c64b38f1d3 100644 |
3874 |
+--- a/drivers/pwm/core.c |
3875 |
++++ b/drivers/pwm/core.c |
3876 |
+@@ -293,6 +293,8 @@ int pwmchip_remove(struct pwm_chip *chip) |
3877 |
+ unsigned int i; |
3878 |
+ int ret = 0; |
3879 |
+ |
3880 |
++ pwmchip_sysfs_unexport_children(chip); |
3881 |
++ |
3882 |
+ mutex_lock(&pwm_lock); |
3883 |
+ |
3884 |
+ for (i = 0; i < chip->npwm; i++) { |
3885 |
+diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c |
3886 |
+index 4bd0c639e16d..6c88e1adf637 100644 |
3887 |
+--- a/drivers/pwm/sysfs.c |
3888 |
++++ b/drivers/pwm/sysfs.c |
3889 |
+@@ -340,6 +340,24 @@ void pwmchip_sysfs_unexport(struct pwm_chip *chip) |
3890 |
+ } |
3891 |
+ } |
3892 |
+ |
3893 |
++void pwmchip_sysfs_unexport_children(struct pwm_chip *chip) |
3894 |
++{ |
3895 |
++ struct device *parent; |
3896 |
++ unsigned int i; |
3897 |
++ |
3898 |
++ parent = class_find_device(&pwm_class, NULL, chip, |
3899 |
++ pwmchip_sysfs_match); |
3900 |
++ if (!parent) |
3901 |
++ return; |
3902 |
++ |
3903 |
++ for (i = 0; i < chip->npwm; i++) { |
3904 |
++ struct pwm_device *pwm = &chip->pwms[i]; |
3905 |
++ |
3906 |
++ if (test_bit(PWMF_EXPORTED, &pwm->flags)) |
3907 |
++ pwm_unexport_child(parent, pwm); |
3908 |
++ } |
3909 |
++} |
3910 |
++ |
3911 |
+ static int __init pwm_sysfs_init(void) |
3912 |
+ { |
3913 |
+ return class_register(&pwm_class); |
3914 |
+diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c |
3915 |
+index 5d06253c2a7a..30e9fbbff051 100644 |
3916 |
+--- a/drivers/s390/cio/qdio_thinint.c |
3917 |
++++ b/drivers/s390/cio/qdio_thinint.c |
3918 |
+@@ -147,11 +147,11 @@ static inline void tiqdio_call_inq_handlers(struct qdio_irq *irq) |
3919 |
+ struct qdio_q *q; |
3920 |
+ int i; |
3921 |
+ |
3922 |
+- for_each_input_queue(irq, q, i) { |
3923 |
+- if (!references_shared_dsci(irq) && |
3924 |
+- has_multiple_inq_on_dsci(irq)) |
3925 |
+- xchg(q->irq_ptr->dsci, 0); |
3926 |
++ if (!references_shared_dsci(irq) && |
3927 |
++ has_multiple_inq_on_dsci(irq)) |
3928 |
++ xchg(irq->dsci, 0); |
3929 |
+ |
3930 |
++ for_each_input_queue(irq, q, i) { |
3931 |
+ if (q->u.in.queue_start_poll) { |
3932 |
+ /* skip if polling is enabled or already in work */ |
3933 |
+ if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED, |
3934 |
+diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c |
3935 |
+index 89215d44d83f..f054d8dee013 100644 |
3936 |
+--- a/drivers/scsi/mvsas/mv_sas.c |
3937 |
++++ b/drivers/scsi/mvsas/mv_sas.c |
3938 |
+@@ -737,8 +737,8 @@ static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf |
3939 |
+ mv_dprintk("device %016llx not ready.\n", |
3940 |
+ SAS_ADDR(dev->sas_addr)); |
3941 |
+ |
3942 |
+- rc = SAS_PHY_DOWN; |
3943 |
+- return rc; |
3944 |
++ rc = SAS_PHY_DOWN; |
3945 |
++ return rc; |
3946 |
+ } |
3947 |
+ tei.port = dev->port->lldd_port; |
3948 |
+ if (tei.port && !tei.port->port_attached && !tmf) { |
3949 |
+diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c |
3950 |
+index ad4f5790a76f..658d640022be 100644 |
3951 |
+--- a/drivers/staging/android/ashmem.c |
3952 |
++++ b/drivers/staging/android/ashmem.c |
3953 |
+@@ -392,6 +392,7 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) |
3954 |
+ ret = PTR_ERR(vmfile); |
3955 |
+ goto out; |
3956 |
+ } |
3957 |
++ vmfile->f_mode |= FMODE_LSEEK; |
3958 |
+ asma->file = vmfile; |
3959 |
+ } |
3960 |
+ get_file(asma->file); |
3961 |
+diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c |
3962 |
+index c69c40d69d5c..2186380a6f51 100644 |
3963 |
+--- a/drivers/staging/android/binder.c |
3964 |
++++ b/drivers/staging/android/binder.c |
3965 |
+@@ -998,7 +998,7 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) |
3966 |
+ |
3967 |
+ |
3968 |
+ static struct binder_ref *binder_get_ref(struct binder_proc *proc, |
3969 |
+- uint32_t desc) |
3970 |
++ u32 desc, bool need_strong_ref) |
3971 |
+ { |
3972 |
+ struct rb_node *n = proc->refs_by_desc.rb_node; |
3973 |
+ struct binder_ref *ref; |
3974 |
+@@ -1006,12 +1006,16 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc, |
3975 |
+ while (n) { |
3976 |
+ ref = rb_entry(n, struct binder_ref, rb_node_desc); |
3977 |
+ |
3978 |
+- if (desc < ref->desc) |
3979 |
++ if (desc < ref->desc) { |
3980 |
+ n = n->rb_left; |
3981 |
+- else if (desc > ref->desc) |
3982 |
++ } else if (desc > ref->desc) { |
3983 |
+ n = n->rb_right; |
3984 |
+- else |
3985 |
++ } else if (need_strong_ref && !ref->strong) { |
3986 |
++ binder_user_error("tried to use weak ref as strong ref\n"); |
3987 |
++ return NULL; |
3988 |
++ } else { |
3989 |
+ return ref; |
3990 |
++ } |
3991 |
+ } |
3992 |
+ return NULL; |
3993 |
+ } |
3994 |
+@@ -1281,7 +1285,10 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, |
3995 |
+ } break; |
3996 |
+ case BINDER_TYPE_HANDLE: |
3997 |
+ case BINDER_TYPE_WEAK_HANDLE: { |
3998 |
+- struct binder_ref *ref = binder_get_ref(proc, fp->handle); |
3999 |
++ struct binder_ref *ref; |
4000 |
++ |
4001 |
++ ref = binder_get_ref(proc, fp->handle, |
4002 |
++ fp->type == BINDER_TYPE_HANDLE); |
4003 |
+ |
4004 |
+ if (ref == NULL) { |
4005 |
+ pr_err("transaction release %d bad handle %d\n", |
4006 |
+@@ -1375,7 +1382,7 @@ static void binder_transaction(struct binder_proc *proc, |
4007 |
+ if (tr->target.handle) { |
4008 |
+ struct binder_ref *ref; |
4009 |
+ |
4010 |
+- ref = binder_get_ref(proc, tr->target.handle); |
4011 |
++ ref = binder_get_ref(proc, tr->target.handle, true); |
4012 |
+ if (ref == NULL) { |
4013 |
+ binder_user_error("%d:%d got transaction to invalid handle\n", |
4014 |
+ proc->pid, thread->pid); |
4015 |
+@@ -1556,7 +1563,9 @@ static void binder_transaction(struct binder_proc *proc, |
4016 |
+ fp->type = BINDER_TYPE_HANDLE; |
4017 |
+ else |
4018 |
+ fp->type = BINDER_TYPE_WEAK_HANDLE; |
4019 |
++ fp->binder = 0; |
4020 |
+ fp->handle = ref->desc; |
4021 |
++ fp->cookie = 0; |
4022 |
+ binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE, |
4023 |
+ &thread->todo); |
4024 |
+ |
4025 |
+@@ -1568,7 +1577,10 @@ static void binder_transaction(struct binder_proc *proc, |
4026 |
+ } break; |
4027 |
+ case BINDER_TYPE_HANDLE: |
4028 |
+ case BINDER_TYPE_WEAK_HANDLE: { |
4029 |
+- struct binder_ref *ref = binder_get_ref(proc, fp->handle); |
4030 |
++ struct binder_ref *ref; |
4031 |
++ |
4032 |
++ ref = binder_get_ref(proc, fp->handle, |
4033 |
++ fp->type == BINDER_TYPE_HANDLE); |
4034 |
+ |
4035 |
+ if (ref == NULL) { |
4036 |
+ binder_user_error("%d:%d got transaction with invalid handle, %d\n", |
4037 |
+@@ -1598,7 +1610,9 @@ static void binder_transaction(struct binder_proc *proc, |
4038 |
+ return_error = BR_FAILED_REPLY; |
4039 |
+ goto err_binder_get_ref_for_node_failed; |
4040 |
+ } |
4041 |
++ fp->binder = 0; |
4042 |
+ fp->handle = new_ref->desc; |
4043 |
++ fp->cookie = 0; |
4044 |
+ binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL); |
4045 |
+ trace_binder_transaction_ref_to_ref(t, ref, |
4046 |
+ new_ref); |
4047 |
+@@ -1645,6 +1659,7 @@ static void binder_transaction(struct binder_proc *proc, |
4048 |
+ binder_debug(BINDER_DEBUG_TRANSACTION, |
4049 |
+ " fd %d -> %d\n", fp->handle, target_fd); |
4050 |
+ /* TODO: fput? */ |
4051 |
++ fp->binder = 0; |
4052 |
+ fp->handle = target_fd; |
4053 |
+ } break; |
4054 |
+ |
4055 |
+@@ -1767,7 +1782,9 @@ static int binder_thread_write(struct binder_proc *proc, |
4056 |
+ ref->desc); |
4057 |
+ } |
4058 |
+ } else |
4059 |
+- ref = binder_get_ref(proc, target); |
4060 |
++ ref = binder_get_ref(proc, target, |
4061 |
++ cmd == BC_ACQUIRE || |
4062 |
++ cmd == BC_RELEASE); |
4063 |
+ if (ref == NULL) { |
4064 |
+ binder_user_error("%d:%d refcount change on invalid ref %d\n", |
4065 |
+ proc->pid, thread->pid, target); |
4066 |
+@@ -1963,7 +1980,7 @@ static int binder_thread_write(struct binder_proc *proc, |
4067 |
+ if (get_user(cookie, (binder_uintptr_t __user *)ptr)) |
4068 |
+ return -EFAULT; |
4069 |
+ ptr += sizeof(binder_uintptr_t); |
4070 |
+- ref = binder_get_ref(proc, target); |
4071 |
++ ref = binder_get_ref(proc, target, false); |
4072 |
+ if (ref == NULL) { |
4073 |
+ binder_user_error("%d:%d %s invalid ref %d\n", |
4074 |
+ proc->pid, thread->pid, |
4075 |
+diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c |
4076 |
+index b6bd609c3655..3559e1d19c3a 100644 |
4077 |
+--- a/drivers/staging/iio/impedance-analyzer/ad5933.c |
4078 |
++++ b/drivers/staging/iio/impedance-analyzer/ad5933.c |
4079 |
+@@ -647,6 +647,7 @@ static void ad5933_work(struct work_struct *work) |
4080 |
+ struct iio_dev *indio_dev = i2c_get_clientdata(st->client); |
4081 |
+ signed short buf[2]; |
4082 |
+ unsigned char status; |
4083 |
++ int ret; |
4084 |
+ |
4085 |
+ mutex_lock(&indio_dev->mlock); |
4086 |
+ if (st->state == AD5933_CTRL_INIT_START_FREQ) { |
4087 |
+@@ -654,19 +655,22 @@ static void ad5933_work(struct work_struct *work) |
4088 |
+ ad5933_cmd(st, AD5933_CTRL_START_SWEEP); |
4089 |
+ st->state = AD5933_CTRL_START_SWEEP; |
4090 |
+ schedule_delayed_work(&st->work, st->poll_time_jiffies); |
4091 |
+- mutex_unlock(&indio_dev->mlock); |
4092 |
+- return; |
4093 |
++ goto out; |
4094 |
+ } |
4095 |
+ |
4096 |
+- ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status); |
4097 |
++ ret = ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status); |
4098 |
++ if (ret) |
4099 |
++ goto out; |
4100 |
+ |
4101 |
+ if (status & AD5933_STAT_DATA_VALID) { |
4102 |
+ int scan_count = bitmap_weight(indio_dev->active_scan_mask, |
4103 |
+ indio_dev->masklength); |
4104 |
+- ad5933_i2c_read(st->client, |
4105 |
++ ret = ad5933_i2c_read(st->client, |
4106 |
+ test_bit(1, indio_dev->active_scan_mask) ? |
4107 |
+ AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA, |
4108 |
+ scan_count * 2, (u8 *)buf); |
4109 |
++ if (ret) |
4110 |
++ goto out; |
4111 |
+ |
4112 |
+ if (scan_count == 2) { |
4113 |
+ buf[0] = be16_to_cpu(buf[0]); |
4114 |
+@@ -678,8 +682,7 @@ static void ad5933_work(struct work_struct *work) |
4115 |
+ } else { |
4116 |
+ /* no data available - try again later */ |
4117 |
+ schedule_delayed_work(&st->work, st->poll_time_jiffies); |
4118 |
+- mutex_unlock(&indio_dev->mlock); |
4119 |
+- return; |
4120 |
++ goto out; |
4121 |
+ } |
4122 |
+ |
4123 |
+ if (status & AD5933_STAT_SWEEP_DONE) { |
4124 |
+@@ -691,7 +694,7 @@ static void ad5933_work(struct work_struct *work) |
4125 |
+ ad5933_cmd(st, AD5933_CTRL_INC_FREQ); |
4126 |
+ schedule_delayed_work(&st->work, st->poll_time_jiffies); |
4127 |
+ } |
4128 |
+- |
4129 |
++out: |
4130 |
+ mutex_unlock(&indio_dev->mlock); |
4131 |
+ } |
4132 |
+ |
4133 |
+diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c |
4134 |
+index f56f1db15bad..3f631c067f54 100644 |
4135 |
+--- a/drivers/staging/nvec/nvec_ps2.c |
4136 |
++++ b/drivers/staging/nvec/nvec_ps2.c |
4137 |
+@@ -106,13 +106,12 @@ static int nvec_mouse_probe(struct platform_device *pdev) |
4138 |
+ { |
4139 |
+ struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); |
4140 |
+ struct serio *ser_dev; |
4141 |
+- char mouse_reset[] = { NVEC_PS2, SEND_COMMAND, PSMOUSE_RST, 3 }; |
4142 |
+ |
4143 |
+ ser_dev = devm_kzalloc(&pdev->dev, sizeof(struct serio), GFP_KERNEL); |
4144 |
+ if (ser_dev == NULL) |
4145 |
+ return -ENOMEM; |
4146 |
+ |
4147 |
+- ser_dev->id.type = SERIO_PS_PSTHRU; |
4148 |
++ ser_dev->id.type = SERIO_8042; |
4149 |
+ ser_dev->write = ps2_sendcommand; |
4150 |
+ ser_dev->start = ps2_startstreaming; |
4151 |
+ ser_dev->stop = ps2_stopstreaming; |
4152 |
+@@ -127,9 +126,6 @@ static int nvec_mouse_probe(struct platform_device *pdev) |
4153 |
+ |
4154 |
+ serio_register_port(ser_dev); |
4155 |
+ |
4156 |
+- /* mouse reset */ |
4157 |
+- nvec_write_async(nvec, mouse_reset, sizeof(mouse_reset)); |
4158 |
+- |
4159 |
+ return 0; |
4160 |
+ } |
4161 |
+ |
4162 |
+diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c |
4163 |
+index 644ddb841d9f..6d1e2f746ab4 100644 |
4164 |
+--- a/drivers/tty/n_hdlc.c |
4165 |
++++ b/drivers/tty/n_hdlc.c |
4166 |
+@@ -114,7 +114,7 @@ |
4167 |
+ #define DEFAULT_TX_BUF_COUNT 3 |
4168 |
+ |
4169 |
+ struct n_hdlc_buf { |
4170 |
+- struct n_hdlc_buf *link; |
4171 |
++ struct list_head list_item; |
4172 |
+ int count; |
4173 |
+ char buf[1]; |
4174 |
+ }; |
4175 |
+@@ -122,8 +122,7 @@ struct n_hdlc_buf { |
4176 |
+ #define N_HDLC_BUF_SIZE (sizeof(struct n_hdlc_buf) + maxframe) |
4177 |
+ |
4178 |
+ struct n_hdlc_buf_list { |
4179 |
+- struct n_hdlc_buf *head; |
4180 |
+- struct n_hdlc_buf *tail; |
4181 |
++ struct list_head list; |
4182 |
+ int count; |
4183 |
+ spinlock_t spinlock; |
4184 |
+ }; |
4185 |
+@@ -136,7 +135,6 @@ struct n_hdlc_buf_list { |
4186 |
+ * @backup_tty - TTY to use if tty gets closed |
4187 |
+ * @tbusy - reentrancy flag for tx wakeup code |
4188 |
+ * @woke_up - FIXME: describe this field |
4189 |
+- * @tbuf - currently transmitting tx buffer |
4190 |
+ * @tx_buf_list - list of pending transmit frame buffers |
4191 |
+ * @rx_buf_list - list of received frame buffers |
4192 |
+ * @tx_free_buf_list - list unused transmit frame buffers |
4193 |
+@@ -149,7 +147,6 @@ struct n_hdlc { |
4194 |
+ struct tty_struct *backup_tty; |
4195 |
+ int tbusy; |
4196 |
+ int woke_up; |
4197 |
+- struct n_hdlc_buf *tbuf; |
4198 |
+ struct n_hdlc_buf_list tx_buf_list; |
4199 |
+ struct n_hdlc_buf_list rx_buf_list; |
4200 |
+ struct n_hdlc_buf_list tx_free_buf_list; |
4201 |
+@@ -159,7 +156,8 @@ struct n_hdlc { |
4202 |
+ /* |
4203 |
+ * HDLC buffer list manipulation functions |
4204 |
+ */ |
4205 |
+-static void n_hdlc_buf_list_init(struct n_hdlc_buf_list *list); |
4206 |
++static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list, |
4207 |
++ struct n_hdlc_buf *buf); |
4208 |
+ static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, |
4209 |
+ struct n_hdlc_buf *buf); |
4210 |
+ static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list); |
4211 |
+@@ -209,16 +207,9 @@ static void flush_tx_queue(struct tty_struct *tty) |
4212 |
+ { |
4213 |
+ struct n_hdlc *n_hdlc = tty2n_hdlc(tty); |
4214 |
+ struct n_hdlc_buf *buf; |
4215 |
+- unsigned long flags; |
4216 |
+ |
4217 |
+ while ((buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list))) |
4218 |
+ n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, buf); |
4219 |
+- spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); |
4220 |
+- if (n_hdlc->tbuf) { |
4221 |
+- n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, n_hdlc->tbuf); |
4222 |
+- n_hdlc->tbuf = NULL; |
4223 |
+- } |
4224 |
+- spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); |
4225 |
+ } |
4226 |
+ |
4227 |
+ static struct tty_ldisc_ops n_hdlc_ldisc = { |
4228 |
+@@ -284,7 +275,6 @@ static void n_hdlc_release(struct n_hdlc *n_hdlc) |
4229 |
+ } else |
4230 |
+ break; |
4231 |
+ } |
4232 |
+- kfree(n_hdlc->tbuf); |
4233 |
+ kfree(n_hdlc); |
4234 |
+ |
4235 |
+ } /* end of n_hdlc_release() */ |
4236 |
+@@ -403,13 +393,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) |
4237 |
+ n_hdlc->woke_up = 0; |
4238 |
+ spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); |
4239 |
+ |
4240 |
+- /* get current transmit buffer or get new transmit */ |
4241 |
+- /* buffer from list of pending transmit buffers */ |
4242 |
+- |
4243 |
+- tbuf = n_hdlc->tbuf; |
4244 |
+- if (!tbuf) |
4245 |
+- tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list); |
4246 |
+- |
4247 |
++ tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list); |
4248 |
+ while (tbuf) { |
4249 |
+ if (debuglevel >= DEBUG_LEVEL_INFO) |
4250 |
+ printk("%s(%d)sending frame %p, count=%d\n", |
4251 |
+@@ -421,7 +405,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) |
4252 |
+ |
4253 |
+ /* rollback was possible and has been done */ |
4254 |
+ if (actual == -ERESTARTSYS) { |
4255 |
+- n_hdlc->tbuf = tbuf; |
4256 |
++ n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf); |
4257 |
+ break; |
4258 |
+ } |
4259 |
+ /* if transmit error, throw frame away by */ |
4260 |
+@@ -436,10 +420,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) |
4261 |
+ |
4262 |
+ /* free current transmit buffer */ |
4263 |
+ n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf); |
4264 |
+- |
4265 |
+- /* this tx buffer is done */ |
4266 |
+- n_hdlc->tbuf = NULL; |
4267 |
+- |
4268 |
++ |
4269 |
+ /* wait up sleeping writers */ |
4270 |
+ wake_up_interruptible(&tty->write_wait); |
4271 |
+ |
4272 |
+@@ -449,10 +430,12 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) |
4273 |
+ if (debuglevel >= DEBUG_LEVEL_INFO) |
4274 |
+ printk("%s(%d)frame %p pending\n", |
4275 |
+ __FILE__,__LINE__,tbuf); |
4276 |
+- |
4277 |
+- /* buffer not accepted by driver */ |
4278 |
+- /* set this buffer as pending buffer */ |
4279 |
+- n_hdlc->tbuf = tbuf; |
4280 |
++ |
4281 |
++ /* |
4282 |
++ * the buffer was not accepted by driver, |
4283 |
++ * return it back into tx queue |
4284 |
++ */ |
4285 |
++ n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf); |
4286 |
+ break; |
4287 |
+ } |
4288 |
+ } |
4289 |
+@@ -750,7 +733,8 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, |
4290 |
+ int error = 0; |
4291 |
+ int count; |
4292 |
+ unsigned long flags; |
4293 |
+- |
4294 |
++ struct n_hdlc_buf *buf = NULL; |
4295 |
++ |
4296 |
+ if (debuglevel >= DEBUG_LEVEL_INFO) |
4297 |
+ printk("%s(%d)n_hdlc_tty_ioctl() called %d\n", |
4298 |
+ __FILE__,__LINE__,cmd); |
4299 |
+@@ -764,8 +748,10 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, |
4300 |
+ /* report count of read data available */ |
4301 |
+ /* in next available frame (if any) */ |
4302 |
+ spin_lock_irqsave(&n_hdlc->rx_buf_list.spinlock,flags); |
4303 |
+- if (n_hdlc->rx_buf_list.head) |
4304 |
+- count = n_hdlc->rx_buf_list.head->count; |
4305 |
++ buf = list_first_entry_or_null(&n_hdlc->rx_buf_list.list, |
4306 |
++ struct n_hdlc_buf, list_item); |
4307 |
++ if (buf) |
4308 |
++ count = buf->count; |
4309 |
+ else |
4310 |
+ count = 0; |
4311 |
+ spin_unlock_irqrestore(&n_hdlc->rx_buf_list.spinlock,flags); |
4312 |
+@@ -777,8 +763,10 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, |
4313 |
+ count = tty_chars_in_buffer(tty); |
4314 |
+ /* add size of next output frame in queue */ |
4315 |
+ spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags); |
4316 |
+- if (n_hdlc->tx_buf_list.head) |
4317 |
+- count += n_hdlc->tx_buf_list.head->count; |
4318 |
++ buf = list_first_entry_or_null(&n_hdlc->tx_buf_list.list, |
4319 |
++ struct n_hdlc_buf, list_item); |
4320 |
++ if (buf) |
4321 |
++ count += buf->count; |
4322 |
+ spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock,flags); |
4323 |
+ error = put_user(count, (int __user *)arg); |
4324 |
+ break; |
4325 |
+@@ -826,14 +814,14 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, |
4326 |
+ poll_wait(filp, &tty->write_wait, wait); |
4327 |
+ |
4328 |
+ /* set bits for operations that won't block */ |
4329 |
+- if (n_hdlc->rx_buf_list.head) |
4330 |
++ if (!list_empty(&n_hdlc->rx_buf_list.list)) |
4331 |
+ mask |= POLLIN | POLLRDNORM; /* readable */ |
4332 |
+ if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) |
4333 |
+ mask |= POLLHUP; |
4334 |
+ if (tty_hung_up_p(filp)) |
4335 |
+ mask |= POLLHUP; |
4336 |
+ if (!tty_is_writelocked(tty) && |
4337 |
+- n_hdlc->tx_free_buf_list.head) |
4338 |
++ !list_empty(&n_hdlc->tx_free_buf_list.list)) |
4339 |
+ mask |= POLLOUT | POLLWRNORM; /* writable */ |
4340 |
+ } |
4341 |
+ return mask; |
4342 |
+@@ -853,11 +841,16 @@ static struct n_hdlc *n_hdlc_alloc(void) |
4343 |
+ if (!n_hdlc) |
4344 |
+ return NULL; |
4345 |
+ |
4346 |
+- n_hdlc_buf_list_init(&n_hdlc->rx_free_buf_list); |
4347 |
+- n_hdlc_buf_list_init(&n_hdlc->tx_free_buf_list); |
4348 |
+- n_hdlc_buf_list_init(&n_hdlc->rx_buf_list); |
4349 |
+- n_hdlc_buf_list_init(&n_hdlc->tx_buf_list); |
4350 |
+- |
4351 |
++ spin_lock_init(&n_hdlc->rx_free_buf_list.spinlock); |
4352 |
++ spin_lock_init(&n_hdlc->tx_free_buf_list.spinlock); |
4353 |
++ spin_lock_init(&n_hdlc->rx_buf_list.spinlock); |
4354 |
++ spin_lock_init(&n_hdlc->tx_buf_list.spinlock); |
4355 |
++ |
4356 |
++ INIT_LIST_HEAD(&n_hdlc->rx_free_buf_list.list); |
4357 |
++ INIT_LIST_HEAD(&n_hdlc->tx_free_buf_list.list); |
4358 |
++ INIT_LIST_HEAD(&n_hdlc->rx_buf_list.list); |
4359 |
++ INIT_LIST_HEAD(&n_hdlc->tx_buf_list.list); |
4360 |
++ |
4361 |
+ /* allocate free rx buffer list */ |
4362 |
+ for(i=0;i<DEFAULT_RX_BUF_COUNT;i++) { |
4363 |
+ buf = kmalloc(N_HDLC_BUF_SIZE, GFP_KERNEL); |
4364 |
+@@ -885,63 +878,65 @@ static struct n_hdlc *n_hdlc_alloc(void) |
4365 |
+ } /* end of n_hdlc_alloc() */ |
4366 |
+ |
4367 |
+ /** |
4368 |
+- * n_hdlc_buf_list_init - initialize specified HDLC buffer list |
4369 |
+- * @list - pointer to buffer list |
4370 |
++ * n_hdlc_buf_return - put the HDLC buffer after the head of the specified list |
4371 |
++ * @buf_list - pointer to the buffer list |
4372 |
++ * @buf - pointer to the buffer |
4373 |
+ */ |
4374 |
+-static void n_hdlc_buf_list_init(struct n_hdlc_buf_list *list) |
4375 |
++static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list, |
4376 |
++ struct n_hdlc_buf *buf) |
4377 |
+ { |
4378 |
+- memset(list, 0, sizeof(*list)); |
4379 |
+- spin_lock_init(&list->spinlock); |
4380 |
+-} /* end of n_hdlc_buf_list_init() */ |
4381 |
++ unsigned long flags; |
4382 |
++ |
4383 |
++ spin_lock_irqsave(&buf_list->spinlock, flags); |
4384 |
++ |
4385 |
++ list_add(&buf->list_item, &buf_list->list); |
4386 |
++ buf_list->count++; |
4387 |
++ |
4388 |
++ spin_unlock_irqrestore(&buf_list->spinlock, flags); |
4389 |
++} |
4390 |
+ |
4391 |
+ /** |
4392 |
+ * n_hdlc_buf_put - add specified HDLC buffer to tail of specified list |
4393 |
+- * @list - pointer to buffer list |
4394 |
++ * @buf_list - pointer to buffer list |
4395 |
+ * @buf - pointer to buffer |
4396 |
+ */ |
4397 |
+-static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, |
4398 |
++static void n_hdlc_buf_put(struct n_hdlc_buf_list *buf_list, |
4399 |
+ struct n_hdlc_buf *buf) |
4400 |
+ { |
4401 |
+ unsigned long flags; |
4402 |
+- spin_lock_irqsave(&list->spinlock,flags); |
4403 |
+- |
4404 |
+- buf->link=NULL; |
4405 |
+- if (list->tail) |
4406 |
+- list->tail->link = buf; |
4407 |
+- else |
4408 |
+- list->head = buf; |
4409 |
+- list->tail = buf; |
4410 |
+- (list->count)++; |
4411 |
+- |
4412 |
+- spin_unlock_irqrestore(&list->spinlock,flags); |
4413 |
+- |
4414 |
++ |
4415 |
++ spin_lock_irqsave(&buf_list->spinlock, flags); |
4416 |
++ |
4417 |
++ list_add_tail(&buf->list_item, &buf_list->list); |
4418 |
++ buf_list->count++; |
4419 |
++ |
4420 |
++ spin_unlock_irqrestore(&buf_list->spinlock, flags); |
4421 |
+ } /* end of n_hdlc_buf_put() */ |
4422 |
+ |
4423 |
+ /** |
4424 |
+ * n_hdlc_buf_get - remove and return an HDLC buffer from list |
4425 |
+- * @list - pointer to HDLC buffer list |
4426 |
++ * @buf_list - pointer to HDLC buffer list |
4427 |
+ * |
4428 |
+ * Remove and return an HDLC buffer from the head of the specified HDLC buffer |
4429 |
+ * list. |
4430 |
+ * Returns a pointer to HDLC buffer if available, otherwise %NULL. |
4431 |
+ */ |
4432 |
+-static struct n_hdlc_buf* n_hdlc_buf_get(struct n_hdlc_buf_list *list) |
4433 |
++static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list) |
4434 |
+ { |
4435 |
+ unsigned long flags; |
4436 |
+ struct n_hdlc_buf *buf; |
4437 |
+- spin_lock_irqsave(&list->spinlock,flags); |
4438 |
+- |
4439 |
+- buf = list->head; |
4440 |
++ |
4441 |
++ spin_lock_irqsave(&buf_list->spinlock, flags); |
4442 |
++ |
4443 |
++ buf = list_first_entry_or_null(&buf_list->list, |
4444 |
++ struct n_hdlc_buf, list_item); |
4445 |
+ if (buf) { |
4446 |
+- list->head = buf->link; |
4447 |
+- (list->count)--; |
4448 |
++ list_del(&buf->list_item); |
4449 |
++ buf_list->count--; |
4450 |
+ } |
4451 |
+- if (!list->head) |
4452 |
+- list->tail = NULL; |
4453 |
+- |
4454 |
+- spin_unlock_irqrestore(&list->spinlock,flags); |
4455 |
++ |
4456 |
++ spin_unlock_irqrestore(&buf_list->spinlock, flags); |
4457 |
+ return buf; |
4458 |
+- |
4459 |
+ } /* end of n_hdlc_buf_get() */ |
4460 |
+ |
4461 |
+ static char hdlc_banner[] __initdata = |
4462 |
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c |
4463 |
+index f6e5ef5bac5e..786bc9e6bed9 100644 |
4464 |
+--- a/drivers/tty/serial/8250/8250_pci.c |
4465 |
++++ b/drivers/tty/serial/8250/8250_pci.c |
4466 |
+@@ -2743,6 +2743,8 @@ enum pci_board_num_t { |
4467 |
+ pbn_b0_4_1152000_200, |
4468 |
+ pbn_b0_8_1152000_200, |
4469 |
+ |
4470 |
++ pbn_b0_4_1250000, |
4471 |
++ |
4472 |
+ pbn_b0_2_1843200, |
4473 |
+ pbn_b0_4_1843200, |
4474 |
+ |
4475 |
+@@ -2971,6 +2973,13 @@ static struct pciserial_board pci_boards[] = { |
4476 |
+ .uart_offset = 0x200, |
4477 |
+ }, |
4478 |
+ |
4479 |
++ [pbn_b0_4_1250000] = { |
4480 |
++ .flags = FL_BASE0, |
4481 |
++ .num_ports = 4, |
4482 |
++ .base_baud = 1250000, |
4483 |
++ .uart_offset = 8, |
4484 |
++ }, |
4485 |
++ |
4486 |
+ [pbn_b0_2_1843200] = { |
4487 |
+ .flags = FL_BASE0, |
4488 |
+ .num_ports = 2, |
4489 |
+@@ -5464,6 +5473,10 @@ static struct pci_device_id serial_pci_tbl[] = { |
4490 |
+ { PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 }, |
4491 |
+ { PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 }, |
4492 |
+ |
4493 |
++ /* MKS Tenta SCOM-080x serial cards */ |
4494 |
++ { PCI_DEVICE(0x1601, 0x0800), .driver_data = pbn_b0_4_1250000 }, |
4495 |
++ { PCI_DEVICE(0x1601, 0xa801), .driver_data = pbn_b0_4_1250000 }, |
4496 |
++ |
4497 |
+ /* |
4498 |
+ * These entries match devices with class COMMUNICATION_SERIAL, |
4499 |
+ * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL |
4500 |
+diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c |
4501 |
+index 1a049e4de937..a57f3761ab47 100644 |
4502 |
+--- a/drivers/tty/vt/vt.c |
4503 |
++++ b/drivers/tty/vt/vt.c |
4504 |
+@@ -1169,7 +1169,7 @@ static void csi_J(struct vc_data *vc, int vpar) |
4505 |
+ break; |
4506 |
+ case 3: /* erase scroll-back buffer (and whole display) */ |
4507 |
+ scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char, |
4508 |
+- vc->vc_screenbuf_size >> 1); |
4509 |
++ vc->vc_screenbuf_size); |
4510 |
+ set_origin(vc); |
4511 |
+ if (CON_IS_VISIBLE(vc)) |
4512 |
+ update_screen(vc); |
4513 |
+diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c |
4514 |
+index 9bdc6bd73432..78f4d70db917 100644 |
4515 |
+--- a/drivers/usb/chipidea/core.c |
4516 |
++++ b/drivers/usb/chipidea/core.c |
4517 |
+@@ -594,6 +594,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) |
4518 |
+ return -ENOMEM; |
4519 |
+ } |
4520 |
+ |
4521 |
++ spin_lock_init(&ci->lock); |
4522 |
+ ci->dev = dev; |
4523 |
+ ci->platdata = dev_get_platdata(dev); |
4524 |
+ ci->imx28_write_fix = !!(ci->platdata->flags & |
4525 |
+diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c |
4526 |
+index 7b362870277e..98d5882aa91b 100644 |
4527 |
+--- a/drivers/usb/chipidea/udc.c |
4528 |
++++ b/drivers/usb/chipidea/udc.c |
4529 |
+@@ -1798,8 +1798,6 @@ static int udc_start(struct ci_hdrc *ci) |
4530 |
+ struct device *dev = ci->dev; |
4531 |
+ int retval = 0; |
4532 |
+ |
4533 |
+- spin_lock_init(&ci->lock); |
4534 |
+- |
4535 |
+ ci->gadget.ops = &usb_gadget_ops; |
4536 |
+ ci->gadget.speed = USB_SPEED_UNKNOWN; |
4537 |
+ ci->gadget.max_speed = USB_SPEED_HIGH; |
4538 |
+diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c |
4539 |
+index e2f63f5d30cb..201e9229d323 100644 |
4540 |
+--- a/drivers/usb/class/cdc-acm.c |
4541 |
++++ b/drivers/usb/class/cdc-acm.c |
4542 |
+@@ -872,8 +872,6 @@ static int wait_serial_change(struct acm *acm, unsigned long arg) |
4543 |
+ DECLARE_WAITQUEUE(wait, current); |
4544 |
+ struct async_icount old, new; |
4545 |
+ |
4546 |
+- if (arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD )) |
4547 |
+- return -EINVAL; |
4548 |
+ do { |
4549 |
+ spin_lock_irq(&acm->read_lock); |
4550 |
+ old = acm->oldcount; |
4551 |
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c |
4552 |
+index 81336acc7040..65e2cec1ca2a 100644 |
4553 |
+--- a/drivers/usb/core/config.c |
4554 |
++++ b/drivers/usb/core/config.c |
4555 |
+@@ -208,6 +208,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, |
4556 |
+ |
4557 |
+ /* |
4558 |
+ * Adjust bInterval for quirked devices. |
4559 |
++ */ |
4560 |
++ /* |
4561 |
++ * This quirk fixes bIntervals reported in ms. |
4562 |
++ */ |
4563 |
++ if (to_usb_device(ddev)->quirks & |
4564 |
++ USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL) { |
4565 |
++ n = clamp(fls(d->bInterval) + 3, i, j); |
4566 |
++ i = j = n; |
4567 |
++ } |
4568 |
++ /* |
4569 |
+ * This quirk fixes bIntervals reported in |
4570 |
+ * linear microframes. |
4571 |
+ */ |
4572 |
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c |
4573 |
+index 096bb82c69c4..652e3e558257 100644 |
4574 |
+--- a/drivers/usb/core/hcd.c |
4575 |
++++ b/drivers/usb/core/hcd.c |
4576 |
+@@ -498,8 +498,10 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) |
4577 |
+ */ |
4578 |
+ tbuf_size = max_t(u16, sizeof(struct usb_hub_descriptor), wLength); |
4579 |
+ tbuf = kzalloc(tbuf_size, GFP_KERNEL); |
4580 |
+- if (!tbuf) |
4581 |
+- return -ENOMEM; |
4582 |
++ if (!tbuf) { |
4583 |
++ status = -ENOMEM; |
4584 |
++ goto err_alloc; |
4585 |
++ } |
4586 |
+ |
4587 |
+ bufp = tbuf; |
4588 |
+ |
4589 |
+@@ -702,6 +704,7 @@ error: |
4590 |
+ } |
4591 |
+ |
4592 |
+ kfree(tbuf); |
4593 |
++ err_alloc: |
4594 |
+ |
4595 |
+ /* any errors get returned through the urb completion */ |
4596 |
+ spin_lock_irq(&hcd_root_hub_lock); |
4597 |
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c |
4598 |
+index 1a3df0f8b891..a3c136b03810 100644 |
4599 |
+--- a/drivers/usb/core/hub.c |
4600 |
++++ b/drivers/usb/core/hub.c |
4601 |
+@@ -2616,8 +2616,15 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, |
4602 |
+ if (ret < 0) |
4603 |
+ return ret; |
4604 |
+ |
4605 |
+- /* The port state is unknown until the reset completes. */ |
4606 |
+- if (!(portstatus & USB_PORT_STAT_RESET)) |
4607 |
++ /* |
4608 |
++ * The port state is unknown until the reset completes. |
4609 |
++ * |
4610 |
++ * On top of that, some chips may require additional time |
4611 |
++ * to re-establish a connection after the reset is complete, |
4612 |
++ * so also wait for the connection to be re-established. |
4613 |
++ */ |
4614 |
++ if (!(portstatus & USB_PORT_STAT_RESET) && |
4615 |
++ (portstatus & USB_PORT_STAT_CONNECTION)) |
4616 |
+ break; |
4617 |
+ |
4618 |
+ /* switch to the long delay after two short delay failures */ |
4619 |
+@@ -4168,7 +4175,7 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev) |
4620 |
+ struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); |
4621 |
+ int connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN; |
4622 |
+ |
4623 |
+- if (!udev->usb2_hw_lpm_capable) |
4624 |
++ if (!udev->usb2_hw_lpm_capable || !udev->bos) |
4625 |
+ return; |
4626 |
+ |
4627 |
+ if (hub) |
4628 |
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c |
4629 |
+index 6c7e47f67dd4..ab12e018de86 100644 |
4630 |
+--- a/drivers/usb/core/quirks.c |
4631 |
++++ b/drivers/usb/core/quirks.c |
4632 |
+@@ -163,6 +163,14 @@ static const struct usb_device_id usb_quirk_list[] = { |
4633 |
+ /* M-Systems Flash Disk Pioneers */ |
4634 |
+ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, |
4635 |
+ |
4636 |
++ /* Baum Vario Ultra */ |
4637 |
++ { USB_DEVICE(0x0904, 0x6101), .driver_info = |
4638 |
++ USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL }, |
4639 |
++ { USB_DEVICE(0x0904, 0x6102), .driver_info = |
4640 |
++ USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL }, |
4641 |
++ { USB_DEVICE(0x0904, 0x6103), .driver_info = |
4642 |
++ USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL }, |
4643 |
++ |
4644 |
+ /* Keytouch QWERTY Panel keyboard */ |
4645 |
+ { USB_DEVICE(0x0926, 0x3333), .driver_info = |
4646 |
+ USB_QUIRK_CONFIG_INTF_STRINGS }, |
4647 |
+diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h |
4648 |
+index 18ae3eaa8b6f..ccd9694f8e36 100644 |
4649 |
+--- a/drivers/usb/dwc3/gadget.h |
4650 |
++++ b/drivers/usb/dwc3/gadget.h |
4651 |
+@@ -28,23 +28,23 @@ struct dwc3; |
4652 |
+ #define gadget_to_dwc(g) (container_of(g, struct dwc3, gadget)) |
4653 |
+ |
4654 |
+ /* DEPCFG parameter 1 */ |
4655 |
+-#define DWC3_DEPCFG_INT_NUM(n) ((n) << 0) |
4656 |
++#define DWC3_DEPCFG_INT_NUM(n) (((n) & 0x1f) << 0) |
4657 |
+ #define DWC3_DEPCFG_XFER_COMPLETE_EN (1 << 8) |
4658 |
+ #define DWC3_DEPCFG_XFER_IN_PROGRESS_EN (1 << 9) |
4659 |
+ #define DWC3_DEPCFG_XFER_NOT_READY_EN (1 << 10) |
4660 |
+ #define DWC3_DEPCFG_FIFO_ERROR_EN (1 << 11) |
4661 |
+ #define DWC3_DEPCFG_STREAM_EVENT_EN (1 << 13) |
4662 |
+-#define DWC3_DEPCFG_BINTERVAL_M1(n) ((n) << 16) |
4663 |
++#define DWC3_DEPCFG_BINTERVAL_M1(n) (((n) & 0xff) << 16) |
4664 |
+ #define DWC3_DEPCFG_STREAM_CAPABLE (1 << 24) |
4665 |
+-#define DWC3_DEPCFG_EP_NUMBER(n) ((n) << 25) |
4666 |
++#define DWC3_DEPCFG_EP_NUMBER(n) (((n) & 0x1f) << 25) |
4667 |
+ #define DWC3_DEPCFG_BULK_BASED (1 << 30) |
4668 |
+ #define DWC3_DEPCFG_FIFO_BASED (1 << 31) |
4669 |
+ |
4670 |
+ /* DEPCFG parameter 0 */ |
4671 |
+-#define DWC3_DEPCFG_EP_TYPE(n) ((n) << 1) |
4672 |
+-#define DWC3_DEPCFG_MAX_PACKET_SIZE(n) ((n) << 3) |
4673 |
+-#define DWC3_DEPCFG_FIFO_NUMBER(n) ((n) << 17) |
4674 |
+-#define DWC3_DEPCFG_BURST_SIZE(n) ((n) << 22) |
4675 |
++#define DWC3_DEPCFG_EP_TYPE(n) (((n) & 0x3) << 1) |
4676 |
++#define DWC3_DEPCFG_MAX_PACKET_SIZE(n) (((n) & 0x7ff) << 3) |
4677 |
++#define DWC3_DEPCFG_FIFO_NUMBER(n) (((n) & 0x1f) << 17) |
4678 |
++#define DWC3_DEPCFG_BURST_SIZE(n) (((n) & 0xf) << 22) |
4679 |
+ #define DWC3_DEPCFG_DATA_SEQ_NUM(n) ((n) << 26) |
4680 |
+ /* This applies for core versions earlier than 1.94a */ |
4681 |
+ #define DWC3_DEPCFG_IGN_SEQ_NUM (1 << 31) |
4682 |
+diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c |
4683 |
+index ab9b7ac63407..58888b8bd389 100644 |
4684 |
+--- a/drivers/usb/gadget/function/f_fs.c |
4685 |
++++ b/drivers/usb/gadget/function/f_fs.c |
4686 |
+@@ -1649,11 +1649,14 @@ static int ffs_func_eps_enable(struct ffs_function *func) |
4687 |
+ spin_lock_irqsave(&func->ffs->eps_lock, flags); |
4688 |
+ do { |
4689 |
+ struct usb_endpoint_descriptor *ds; |
4690 |
++ struct usb_ss_ep_comp_descriptor *comp_desc = NULL; |
4691 |
++ int needs_comp_desc = false; |
4692 |
+ int desc_idx; |
4693 |
+ |
4694 |
+- if (ffs->gadget->speed == USB_SPEED_SUPER) |
4695 |
++ if (ffs->gadget->speed == USB_SPEED_SUPER) { |
4696 |
+ desc_idx = 2; |
4697 |
+- else if (ffs->gadget->speed == USB_SPEED_HIGH) |
4698 |
++ needs_comp_desc = true; |
4699 |
++ } else if (ffs->gadget->speed == USB_SPEED_HIGH) |
4700 |
+ desc_idx = 1; |
4701 |
+ else |
4702 |
+ desc_idx = 0; |
4703 |
+@@ -1670,6 +1673,14 @@ static int ffs_func_eps_enable(struct ffs_function *func) |
4704 |
+ |
4705 |
+ ep->ep->driver_data = ep; |
4706 |
+ ep->ep->desc = ds; |
4707 |
++ |
4708 |
++ comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds + |
4709 |
++ USB_DT_ENDPOINT_SIZE); |
4710 |
++ ep->ep->maxburst = comp_desc->bMaxBurst + 1; |
4711 |
++ |
4712 |
++ if (needs_comp_desc) |
4713 |
++ ep->ep->comp_desc = comp_desc; |
4714 |
++ |
4715 |
+ ret = usb_ep_enable(ep->ep); |
4716 |
+ if (likely(!ret)) { |
4717 |
+ epfile->ep = ep; |
4718 |
+diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c |
4719 |
+index 945b3bd2ca98..f4a0b25d1810 100644 |
4720 |
+--- a/drivers/usb/gadget/function/f_uvc.c |
4721 |
++++ b/drivers/usb/gadget/function/f_uvc.c |
4722 |
+@@ -643,7 +643,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) |
4723 |
+ uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst; |
4724 |
+ uvc_ss_streaming_comp.wBytesPerInterval = |
4725 |
+ cpu_to_le16(max_packet_size * max_packet_mult * |
4726 |
+- opts->streaming_maxburst); |
4727 |
++ (opts->streaming_maxburst + 1)); |
4728 |
+ |
4729 |
+ /* Allocate endpoints. */ |
4730 |
+ ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); |
4731 |
+diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c |
4732 |
+index 2e7d27b4cf89..33011f8ee865 100644 |
4733 |
+--- a/drivers/usb/gadget/function/u_ether.c |
4734 |
++++ b/drivers/usb/gadget/function/u_ether.c |
4735 |
+@@ -589,14 +589,6 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, |
4736 |
+ |
4737 |
+ req->length = length; |
4738 |
+ |
4739 |
+- /* throttle high/super speed IRQ rate back slightly */ |
4740 |
+- if (gadget_is_dualspeed(dev->gadget)) |
4741 |
+- req->no_interrupt = (((dev->gadget->speed == USB_SPEED_HIGH || |
4742 |
+- dev->gadget->speed == USB_SPEED_SUPER)) && |
4743 |
+- !list_empty(&dev->tx_reqs)) |
4744 |
+- ? ((atomic_read(&dev->tx_qlen) % dev->qmult) != 0) |
4745 |
+- : 0; |
4746 |
+- |
4747 |
+ retval = usb_ep_queue(in, req, GFP_ATOMIC); |
4748 |
+ switch (retval) { |
4749 |
+ default: |
4750 |
+diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c |
4751 |
+index 81dc5959e36b..53c747fed9d7 100644 |
4752 |
+--- a/drivers/usb/gadget/udc/dummy_hcd.c |
4753 |
++++ b/drivers/usb/gadget/udc/dummy_hcd.c |
4754 |
+@@ -972,6 +972,8 @@ static int dummy_udc_probe(struct platform_device *pdev) |
4755 |
+ int rc; |
4756 |
+ |
4757 |
+ dum = *((void **)dev_get_platdata(&pdev->dev)); |
4758 |
++ /* Clear usb_gadget region for new registration to udc-core */ |
4759 |
++ memzero_explicit(&dum->gadget, sizeof(struct usb_gadget)); |
4760 |
+ dum->gadget.name = gadget_name; |
4761 |
+ dum->gadget.ops = &dummy_ops; |
4762 |
+ dum->gadget.max_speed = USB_SPEED_SUPER; |
4763 |
+diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c |
4764 |
+index 3dd487872bf1..8788799538eb 100644 |
4765 |
+--- a/drivers/usb/host/xhci-plat.c |
4766 |
++++ b/drivers/usb/host/xhci-plat.c |
4767 |
+@@ -189,6 +189,8 @@ static int xhci_plat_remove(struct platform_device *dev) |
4768 |
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
4769 |
+ struct clk *clk = xhci->clk; |
4770 |
+ |
4771 |
++ xhci->xhc_state |= XHCI_STATE_REMOVING; |
4772 |
++ |
4773 |
+ usb_remove_hcd(xhci->shared_hcd); |
4774 |
+ usb_put_hcd(xhci->shared_hcd); |
4775 |
+ |
4776 |
+diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c |
4777 |
+index 4e38683c653c..6d4e75785710 100644 |
4778 |
+--- a/drivers/usb/misc/idmouse.c |
4779 |
++++ b/drivers/usb/misc/idmouse.c |
4780 |
+@@ -346,6 +346,9 @@ static int idmouse_probe(struct usb_interface *interface, |
4781 |
+ if (iface_desc->desc.bInterfaceClass != 0x0A) |
4782 |
+ return -ENODEV; |
4783 |
+ |
4784 |
++ if (iface_desc->desc.bNumEndpoints < 1) |
4785 |
++ return -ENODEV; |
4786 |
++ |
4787 |
+ /* allocate memory for our device state and initialize it */ |
4788 |
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
4789 |
+ if (dev == NULL) |
4790 |
+diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c |
4791 |
+index 1950e87b4219..775690bed4c0 100644 |
4792 |
+--- a/drivers/usb/misc/iowarrior.c |
4793 |
++++ b/drivers/usb/misc/iowarrior.c |
4794 |
+@@ -787,12 +787,6 @@ static int iowarrior_probe(struct usb_interface *interface, |
4795 |
+ iface_desc = interface->cur_altsetting; |
4796 |
+ dev->product_id = le16_to_cpu(udev->descriptor.idProduct); |
4797 |
+ |
4798 |
+- if (iface_desc->desc.bNumEndpoints < 1) { |
4799 |
+- dev_err(&interface->dev, "Invalid number of endpoints\n"); |
4800 |
+- retval = -EINVAL; |
4801 |
+- goto error; |
4802 |
+- } |
4803 |
+- |
4804 |
+ /* set up the endpoint information */ |
4805 |
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { |
4806 |
+ endpoint = &iface_desc->endpoint[i].desc; |
4807 |
+@@ -803,6 +797,21 @@ static int iowarrior_probe(struct usb_interface *interface, |
4808 |
+ /* this one will match for the IOWarrior56 only */ |
4809 |
+ dev->int_out_endpoint = endpoint; |
4810 |
+ } |
4811 |
++ |
4812 |
++ if (!dev->int_in_endpoint) { |
4813 |
++ dev_err(&interface->dev, "no interrupt-in endpoint found\n"); |
4814 |
++ retval = -ENODEV; |
4815 |
++ goto error; |
4816 |
++ } |
4817 |
++ |
4818 |
++ if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) { |
4819 |
++ if (!dev->int_out_endpoint) { |
4820 |
++ dev_err(&interface->dev, "no interrupt-out endpoint found\n"); |
4821 |
++ retval = -ENODEV; |
4822 |
++ goto error; |
4823 |
++ } |
4824 |
++ } |
4825 |
++ |
4826 |
+ /* we have to check the report_size often, so remember it in the endianness suitable for our machine */ |
4827 |
+ dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint); |
4828 |
+ if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) && |
4829 |
+diff --git a/drivers/usb/misc/lvstest.c b/drivers/usb/misc/lvstest.c |
4830 |
+index 62cb8cd08403..66e2d036bb37 100644 |
4831 |
+--- a/drivers/usb/misc/lvstest.c |
4832 |
++++ b/drivers/usb/misc/lvstest.c |
4833 |
+@@ -370,6 +370,10 @@ static int lvs_rh_probe(struct usb_interface *intf, |
4834 |
+ |
4835 |
+ hdev = interface_to_usbdev(intf); |
4836 |
+ desc = intf->cur_altsetting; |
4837 |
++ |
4838 |
++ if (desc->desc.bNumEndpoints < 1) |
4839 |
++ return -ENODEV; |
4840 |
++ |
4841 |
+ endpoint = &desc->endpoint[0].desc; |
4842 |
+ |
4843 |
+ /* valid only for SS root hub */ |
4844 |
+diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c |
4845 |
+index 40ef40affe83..3cb05eb5f1df 100644 |
4846 |
+--- a/drivers/usb/misc/uss720.c |
4847 |
++++ b/drivers/usb/misc/uss720.c |
4848 |
+@@ -715,6 +715,11 @@ static int uss720_probe(struct usb_interface *intf, |
4849 |
+ |
4850 |
+ interface = intf->cur_altsetting; |
4851 |
+ |
4852 |
++ if (interface->desc.bNumEndpoints < 3) { |
4853 |
++ usb_put_dev(usbdev); |
4854 |
++ return -ENODEV; |
4855 |
++ } |
4856 |
++ |
4857 |
+ /* |
4858 |
+ * Allocate parport interface |
4859 |
+ */ |
4860 |
+diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c |
4861 |
+index 3df7b7ec178e..e0b1fe2f60e1 100644 |
4862 |
+--- a/drivers/usb/serial/digi_acceleport.c |
4863 |
++++ b/drivers/usb/serial/digi_acceleport.c |
4864 |
+@@ -1483,16 +1483,20 @@ static int digi_read_oob_callback(struct urb *urb) |
4865 |
+ struct usb_serial *serial = port->serial; |
4866 |
+ struct tty_struct *tty; |
4867 |
+ struct digi_port *priv = usb_get_serial_port_data(port); |
4868 |
++ unsigned char *buf = urb->transfer_buffer; |
4869 |
+ int opcode, line, status, val; |
4870 |
+ int i; |
4871 |
+ unsigned int rts; |
4872 |
+ |
4873 |
++ if (urb->actual_length < 4) |
4874 |
++ return -1; |
4875 |
++ |
4876 |
+ /* handle each oob command */ |
4877 |
+- for (i = 0; i < urb->actual_length - 3;) { |
4878 |
+- opcode = ((unsigned char *)urb->transfer_buffer)[i++]; |
4879 |
+- line = ((unsigned char *)urb->transfer_buffer)[i++]; |
4880 |
+- status = ((unsigned char *)urb->transfer_buffer)[i++]; |
4881 |
+- val = ((unsigned char *)urb->transfer_buffer)[i++]; |
4882 |
++ for (i = 0; i < urb->actual_length - 3; i += 4) { |
4883 |
++ opcode = buf[i]; |
4884 |
++ line = buf[i + 1]; |
4885 |
++ status = buf[i + 2]; |
4886 |
++ val = buf[i + 3]; |
4887 |
+ |
4888 |
+ dev_dbg(&port->dev, "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d\n", |
4889 |
+ opcode, line, status, val); |
4890 |
+diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c |
4891 |
+index ddbb8fe1046d..f6f6960218a7 100644 |
4892 |
+--- a/drivers/usb/serial/io_ti.c |
4893 |
++++ b/drivers/usb/serial/io_ti.c |
4894 |
+@@ -1546,6 +1546,12 @@ static void edge_interrupt_callback(struct urb *urb) |
4895 |
+ function = TIUMP_GET_FUNC_FROM_CODE(data[0]); |
4896 |
+ dev_dbg(dev, "%s - port_number %d, function %d, info 0x%x\n", __func__, |
4897 |
+ port_number, function, data[1]); |
4898 |
++ |
4899 |
++ if (port_number >= edge_serial->serial->num_ports) { |
4900 |
++ dev_err(dev, "bad port number %d\n", port_number); |
4901 |
++ goto exit; |
4902 |
++ } |
4903 |
++ |
4904 |
+ port = edge_serial->serial->port[port_number]; |
4905 |
+ edge_port = usb_get_serial_port_data(port); |
4906 |
+ if (!edge_port) { |
4907 |
+@@ -1626,7 +1632,7 @@ static void edge_bulk_in_callback(struct urb *urb) |
4908 |
+ |
4909 |
+ port_number = edge_port->port->port_number; |
4910 |
+ |
4911 |
+- if (edge_port->lsr_event) { |
4912 |
++ if (urb->actual_length > 0 && edge_port->lsr_event) { |
4913 |
+ edge_port->lsr_event = 0; |
4914 |
+ dev_dbg(dev, "%s ===== Port %u LSR Status = %02x, Data = %02x ======\n", |
4915 |
+ __func__, port_number, edge_port->lsr_mask, *data); |
4916 |
+diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c |
4917 |
+index f6c6900bccf0..880bbdba19d2 100644 |
4918 |
+--- a/drivers/usb/serial/omninet.c |
4919 |
++++ b/drivers/usb/serial/omninet.c |
4920 |
+@@ -129,12 +129,6 @@ static int omninet_port_remove(struct usb_serial_port *port) |
4921 |
+ |
4922 |
+ static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port) |
4923 |
+ { |
4924 |
+- struct usb_serial *serial = port->serial; |
4925 |
+- struct usb_serial_port *wport; |
4926 |
+- |
4927 |
+- wport = serial->port[1]; |
4928 |
+- tty_port_tty_set(&wport->port, tty); |
4929 |
+- |
4930 |
+ return usb_serial_generic_open(tty, port); |
4931 |
+ } |
4932 |
+ |
4933 |
+diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c |
4934 |
+index 9dfbea6c1d2c..ae652223fabc 100644 |
4935 |
+--- a/drivers/usb/serial/qcserial.c |
4936 |
++++ b/drivers/usb/serial/qcserial.c |
4937 |
+@@ -163,6 +163,8 @@ static const struct usb_device_id id_table[] = { |
4938 |
+ {DEVICE_SWI(0x413c, 0x81a9)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ |
4939 |
+ {DEVICE_SWI(0x413c, 0x81b1)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */ |
4940 |
+ {DEVICE_SWI(0x413c, 0x81b3)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */ |
4941 |
++ {DEVICE_SWI(0x413c, 0x81b5)}, /* Dell Wireless 5811e QDL */ |
4942 |
++ {DEVICE_SWI(0x413c, 0x81b6)}, /* Dell Wireless 5811e QDL */ |
4943 |
+ |
4944 |
+ /* Huawei devices */ |
4945 |
+ {DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */ |
4946 |
+diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c |
4947 |
+index b2dff0f14743..236ea43f7815 100644 |
4948 |
+--- a/drivers/usb/serial/safe_serial.c |
4949 |
++++ b/drivers/usb/serial/safe_serial.c |
4950 |
+@@ -205,6 +205,11 @@ static void safe_process_read_urb(struct urb *urb) |
4951 |
+ if (!safe) |
4952 |
+ goto out; |
4953 |
+ |
4954 |
++ if (length < 2) { |
4955 |
++ dev_err(&port->dev, "malformed packet\n"); |
4956 |
++ return; |
4957 |
++ } |
4958 |
++ |
4959 |
+ fcs = fcs_compute10(data, length, CRC10_INITFCS); |
4960 |
+ if (fcs) { |
4961 |
+ dev_err(&port->dev, "%s - bad CRC %x\n", __func__, fcs); |
4962 |
+diff --git a/drivers/usb/wusbcore/wa-hc.c b/drivers/usb/wusbcore/wa-hc.c |
4963 |
+index 252c7bd9218a..d01496fd27fe 100644 |
4964 |
+--- a/drivers/usb/wusbcore/wa-hc.c |
4965 |
++++ b/drivers/usb/wusbcore/wa-hc.c |
4966 |
+@@ -39,6 +39,9 @@ int wa_create(struct wahc *wa, struct usb_interface *iface, |
4967 |
+ int result; |
4968 |
+ struct device *dev = &iface->dev; |
4969 |
+ |
4970 |
++ if (iface->cur_altsetting->desc.bNumEndpoints < 3) |
4971 |
++ return -ENODEV; |
4972 |
++ |
4973 |
+ result = wa_rpipes_create(wa); |
4974 |
+ if (result < 0) |
4975 |
+ goto error_rpipes_create; |
4976 |
+diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c |
4977 |
+index f89245b8ba8e..68a113594808 100644 |
4978 |
+--- a/drivers/video/fbdev/core/fbcmap.c |
4979 |
++++ b/drivers/video/fbdev/core/fbcmap.c |
4980 |
+@@ -163,17 +163,18 @@ void fb_dealloc_cmap(struct fb_cmap *cmap) |
4981 |
+ |
4982 |
+ int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to) |
4983 |
+ { |
4984 |
+- int tooff = 0, fromoff = 0; |
4985 |
+- int size; |
4986 |
++ unsigned int tooff = 0, fromoff = 0; |
4987 |
++ size_t size; |
4988 |
+ |
4989 |
+ if (to->start > from->start) |
4990 |
+ fromoff = to->start - from->start; |
4991 |
+ else |
4992 |
+ tooff = from->start - to->start; |
4993 |
+- size = to->len - tooff; |
4994 |
+- if (size > (int) (from->len - fromoff)) |
4995 |
+- size = from->len - fromoff; |
4996 |
+- if (size <= 0) |
4997 |
++ if (fromoff >= from->len || tooff >= to->len) |
4998 |
++ return -EINVAL; |
4999 |
++ |
5000 |
++ size = min_t(size_t, to->len - tooff, from->len - fromoff); |
5001 |
++ if (size == 0) |
5002 |
+ return -EINVAL; |
5003 |
+ size *= sizeof(u16); |
5004 |
+ |
5005 |
+@@ -187,17 +188,18 @@ int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to) |
5006 |
+ |
5007 |
+ int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to) |
5008 |
+ { |
5009 |
+- int tooff = 0, fromoff = 0; |
5010 |
+- int size; |
5011 |
++ unsigned int tooff = 0, fromoff = 0; |
5012 |
++ size_t size; |
5013 |
+ |
5014 |
+ if (to->start > from->start) |
5015 |
+ fromoff = to->start - from->start; |
5016 |
+ else |
5017 |
+ tooff = from->start - to->start; |
5018 |
+- size = to->len - tooff; |
5019 |
+- if (size > (int) (from->len - fromoff)) |
5020 |
+- size = from->len - fromoff; |
5021 |
+- if (size <= 0) |
5022 |
++ if (fromoff >= from->len || tooff >= to->len) |
5023 |
++ return -EINVAL; |
5024 |
++ |
5025 |
++ size = min_t(size_t, to->len - tooff, from->len - fromoff); |
5026 |
++ if (size == 0) |
5027 |
+ return -EINVAL; |
5028 |
+ size *= sizeof(u16); |
5029 |
+ |
5030 |
+diff --git a/fs/coredump.c b/fs/coredump.c |
5031 |
+index 7eb6181184ea..0ad7a30e3107 100644 |
5032 |
+--- a/fs/coredump.c |
5033 |
++++ b/fs/coredump.c |
5034 |
+@@ -1,6 +1,7 @@ |
5035 |
+ #include <linux/slab.h> |
5036 |
+ #include <linux/file.h> |
5037 |
+ #include <linux/fdtable.h> |
5038 |
++#include <linux/freezer.h> |
5039 |
+ #include <linux/mm.h> |
5040 |
+ #include <linux/stat.h> |
5041 |
+ #include <linux/fcntl.h> |
5042 |
+@@ -393,7 +394,9 @@ static int coredump_wait(int exit_code, struct core_state *core_state) |
5043 |
+ if (core_waiters > 0) { |
5044 |
+ struct core_thread *ptr; |
5045 |
+ |
5046 |
++ freezer_do_not_count(); |
5047 |
+ wait_for_completion(&core_state->startup); |
5048 |
++ freezer_count(); |
5049 |
+ /* |
5050 |
+ * Wait for all the threads to become inactive, so that |
5051 |
+ * all the thread context (extended register state, like |
5052 |
+diff --git a/fs/fat/inode.c b/fs/fat/inode.c |
5053 |
+index 756aead10d96..75b5a159d607 100644 |
5054 |
+--- a/fs/fat/inode.c |
5055 |
++++ b/fs/fat/inode.c |
5056 |
+@@ -1266,6 +1266,16 @@ out: |
5057 |
+ return 0; |
5058 |
+ } |
5059 |
+ |
5060 |
++static void fat_dummy_inode_init(struct inode *inode) |
5061 |
++{ |
5062 |
++ /* Initialize this dummy inode to work as no-op. */ |
5063 |
++ MSDOS_I(inode)->mmu_private = 0; |
5064 |
++ MSDOS_I(inode)->i_start = 0; |
5065 |
++ MSDOS_I(inode)->i_logstart = 0; |
5066 |
++ MSDOS_I(inode)->i_attrs = 0; |
5067 |
++ MSDOS_I(inode)->i_pos = 0; |
5068 |
++} |
5069 |
++ |
5070 |
+ static int fat_read_root(struct inode *inode) |
5071 |
+ { |
5072 |
+ struct super_block *sb = inode->i_sb; |
5073 |
+@@ -1711,12 +1721,13 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, |
5074 |
+ fat_inode = new_inode(sb); |
5075 |
+ if (!fat_inode) |
5076 |
+ goto out_fail; |
5077 |
+- MSDOS_I(fat_inode)->i_pos = 0; |
5078 |
++ fat_dummy_inode_init(fat_inode); |
5079 |
+ sbi->fat_inode = fat_inode; |
5080 |
+ |
5081 |
+ fsinfo_inode = new_inode(sb); |
5082 |
+ if (!fsinfo_inode) |
5083 |
+ goto out_fail; |
5084 |
++ fat_dummy_inode_init(fsinfo_inode); |
5085 |
+ fsinfo_inode->i_ino = MSDOS_FSINFO_INO; |
5086 |
+ sbi->fsinfo_inode = fsinfo_inode; |
5087 |
+ insert_inode_hash(fsinfo_inode); |
5088 |
+diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c |
5089 |
+index f5b2453a43b2..5dcd602b2996 100644 |
5090 |
+--- a/fs/xfs/xfs_aops.c |
5091 |
++++ b/fs/xfs/xfs_aops.c |
5092 |
+@@ -153,6 +153,12 @@ xfs_setfilesize( |
5093 |
+ rwsem_acquire_read(&VFS_I(ip)->i_sb->s_writers.lock_map[SB_FREEZE_FS-1], |
5094 |
+ 0, 1, _THIS_IP_); |
5095 |
+ |
5096 |
++ /* we abort the update if there was an IO error */ |
5097 |
++ if (ioend->io_error) { |
5098 |
++ xfs_trans_cancel(tp, 0); |
5099 |
++ return ioend->io_error; |
5100 |
++ } |
5101 |
++ |
5102 |
+ xfs_ilock(ip, XFS_ILOCK_EXCL); |
5103 |
+ isize = xfs_new_eof(ip, ioend->io_offset + ioend->io_size); |
5104 |
+ if (!isize) { |
5105 |
+@@ -208,14 +214,17 @@ xfs_end_io( |
5106 |
+ ioend->io_error = -EIO; |
5107 |
+ goto done; |
5108 |
+ } |
5109 |
+- if (ioend->io_error) |
5110 |
+- goto done; |
5111 |
+ |
5112 |
+ /* |
5113 |
+ * For unwritten extents we need to issue transactions to convert a |
5114 |
+ * range to normal written extens after the data I/O has finished. |
5115 |
++ * Detecting and handling completion IO errors is done individually |
5116 |
++ * for each case as different cleanup operations need to be performed |
5117 |
++ * on error. |
5118 |
+ */ |
5119 |
+ if (ioend->io_type == XFS_IO_UNWRITTEN) { |
5120 |
++ if (ioend->io_error) |
5121 |
++ goto done; |
5122 |
+ error = xfs_iomap_write_unwritten(ip, ioend->io_offset, |
5123 |
+ ioend->io_size); |
5124 |
+ } else if (ioend->io_isdirect && xfs_ioend_is_append(ioend)) { |
5125 |
+diff --git a/include/linux/can/core.h b/include/linux/can/core.h |
5126 |
+index a0875001b13c..df08a41d5be5 100644 |
5127 |
+--- a/include/linux/can/core.h |
5128 |
++++ b/include/linux/can/core.h |
5129 |
+@@ -45,10 +45,9 @@ struct can_proto { |
5130 |
+ extern int can_proto_register(const struct can_proto *cp); |
5131 |
+ extern void can_proto_unregister(const struct can_proto *cp); |
5132 |
+ |
5133 |
+-extern int can_rx_register(struct net_device *dev, canid_t can_id, |
5134 |
+- canid_t mask, |
5135 |
+- void (*func)(struct sk_buff *, void *), |
5136 |
+- void *data, char *ident); |
5137 |
++int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, |
5138 |
++ void (*func)(struct sk_buff *, void *), |
5139 |
++ void *data, char *ident, struct sock *sk); |
5140 |
+ |
5141 |
+ extern void can_rx_unregister(struct net_device *dev, canid_t can_id, |
5142 |
+ canid_t mask, |
5143 |
+diff --git a/include/linux/ceph/osdmap.h b/include/linux/ceph/osdmap.h |
5144 |
+index 561ea896c657..e5ea74c354a0 100644 |
5145 |
+--- a/include/linux/ceph/osdmap.h |
5146 |
++++ b/include/linux/ceph/osdmap.h |
5147 |
+@@ -49,7 +49,7 @@ static inline bool ceph_can_shift_osds(struct ceph_pg_pool_info *pool) |
5148 |
+ case CEPH_POOL_TYPE_EC: |
5149 |
+ return false; |
5150 |
+ default: |
5151 |
+- BUG_ON(1); |
5152 |
++ BUG(); |
5153 |
+ } |
5154 |
+ } |
5155 |
+ |
5156 |
+diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h |
5157 |
+index ff82a32871b5..439cde68dda9 100644 |
5158 |
+--- a/include/linux/lockd/lockd.h |
5159 |
++++ b/include/linux/lockd/lockd.h |
5160 |
+@@ -351,7 +351,8 @@ static inline int nlm_privileged_requester(const struct svc_rqst *rqstp) |
5161 |
+ static inline int nlm_compare_locks(const struct file_lock *fl1, |
5162 |
+ const struct file_lock *fl2) |
5163 |
+ { |
5164 |
+- return fl1->fl_pid == fl2->fl_pid |
5165 |
++ return file_inode(fl1->fl_file) == file_inode(fl2->fl_file) |
5166 |
++ && fl1->fl_pid == fl2->fl_pid |
5167 |
+ && fl1->fl_owner == fl2->fl_owner |
5168 |
+ && fl1->fl_start == fl2->fl_start |
5169 |
+ && fl1->fl_end == fl2->fl_end |
5170 |
+diff --git a/include/linux/mroute.h b/include/linux/mroute.h |
5171 |
+index 79aaa9fc1a15..d5277fc3ce2e 100644 |
5172 |
+--- a/include/linux/mroute.h |
5173 |
++++ b/include/linux/mroute.h |
5174 |
+@@ -103,5 +103,5 @@ struct mfc_cache { |
5175 |
+ struct rtmsg; |
5176 |
+ extern int ipmr_get_route(struct net *net, struct sk_buff *skb, |
5177 |
+ __be32 saddr, __be32 daddr, |
5178 |
+- struct rtmsg *rtm, int nowait); |
5179 |
++ struct rtmsg *rtm, int nowait, u32 portid); |
5180 |
+ #endif |
5181 |
+diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h |
5182 |
+index 66982e764051..f831155dc7d1 100644 |
5183 |
+--- a/include/linux/mroute6.h |
5184 |
++++ b/include/linux/mroute6.h |
5185 |
+@@ -115,7 +115,7 @@ struct mfc6_cache { |
5186 |
+ |
5187 |
+ struct rtmsg; |
5188 |
+ extern int ip6mr_get_route(struct net *net, struct sk_buff *skb, |
5189 |
+- struct rtmsg *rtm, int nowait); |
5190 |
++ struct rtmsg *rtm, int nowait, u32 portid); |
5191 |
+ |
5192 |
+ #ifdef CONFIG_IPV6_MROUTE |
5193 |
+ extern struct sock *mroute6_socket(struct net *net, struct sk_buff *skb); |
5194 |
+diff --git a/include/linux/pwm.h b/include/linux/pwm.h |
5195 |
+index e90628cac8fa..84e526a12def 100644 |
5196 |
+--- a/include/linux/pwm.h |
5197 |
++++ b/include/linux/pwm.h |
5198 |
+@@ -299,6 +299,7 @@ static inline void pwm_add_table(struct pwm_lookup *table, size_t num) |
5199 |
+ #ifdef CONFIG_PWM_SYSFS |
5200 |
+ void pwmchip_sysfs_export(struct pwm_chip *chip); |
5201 |
+ void pwmchip_sysfs_unexport(struct pwm_chip *chip); |
5202 |
++void pwmchip_sysfs_unexport_children(struct pwm_chip *chip); |
5203 |
+ #else |
5204 |
+ static inline void pwmchip_sysfs_export(struct pwm_chip *chip) |
5205 |
+ { |
5206 |
+@@ -307,6 +308,10 @@ static inline void pwmchip_sysfs_export(struct pwm_chip *chip) |
5207 |
+ static inline void pwmchip_sysfs_unexport(struct pwm_chip *chip) |
5208 |
+ { |
5209 |
+ } |
5210 |
++ |
5211 |
++static inline void pwmchip_sysfs_unexport_children(struct pwm_chip *chip) |
5212 |
++{ |
5213 |
++} |
5214 |
+ #endif /* CONFIG_PWM_SYSFS */ |
5215 |
+ |
5216 |
+ #endif /* __LINUX_PWM_H */ |
5217 |
+diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h |
5218 |
+index 1d0043dc34e4..de2a722fe3cf 100644 |
5219 |
+--- a/include/linux/usb/quirks.h |
5220 |
++++ b/include/linux/usb/quirks.h |
5221 |
+@@ -50,4 +50,10 @@ |
5222 |
+ /* device can't handle Link Power Management */ |
5223 |
+ #define USB_QUIRK_NO_LPM BIT(10) |
5224 |
+ |
5225 |
++/* |
5226 |
++ * Device reports its bInterval as linear frames instead of the |
5227 |
++ * USB 2.0 calculation. |
5228 |
++ */ |
5229 |
++#define USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL BIT(11) |
5230 |
++ |
5231 |
+ #endif /* __LINUX_USB_QUIRKS_H */ |
5232 |
+diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h |
5233 |
+index 3ebb168b9afc..a34b141f125f 100644 |
5234 |
+--- a/include/net/cipso_ipv4.h |
5235 |
++++ b/include/net/cipso_ipv4.h |
5236 |
+@@ -309,6 +309,10 @@ static inline int cipso_v4_validate(const struct sk_buff *skb, |
5237 |
+ } |
5238 |
+ |
5239 |
+ for (opt_iter = 6; opt_iter < opt_len;) { |
5240 |
++ if (opt_iter + 1 == opt_len) { |
5241 |
++ err_offset = opt_iter; |
5242 |
++ goto out; |
5243 |
++ } |
5244 |
+ tag_len = opt[opt_iter + 1]; |
5245 |
+ if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) { |
5246 |
+ err_offset = opt_iter + 1; |
5247 |
+diff --git a/include/trace/events/syscalls.h b/include/trace/events/syscalls.h |
5248 |
+index 14e49c798135..b35533b94277 100644 |
5249 |
+--- a/include/trace/events/syscalls.h |
5250 |
++++ b/include/trace/events/syscalls.h |
5251 |
+@@ -1,5 +1,6 @@ |
5252 |
+ #undef TRACE_SYSTEM |
5253 |
+ #define TRACE_SYSTEM raw_syscalls |
5254 |
++#undef TRACE_INCLUDE_FILE |
5255 |
+ #define TRACE_INCLUDE_FILE syscalls |
5256 |
+ |
5257 |
+ #if !defined(_TRACE_EVENTS_SYSCALLS_H) || defined(TRACE_HEADER_MULTI_READ) |
5258 |
+diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h |
5259 |
+index 1a85940f8ab7..8a8135c4e99a 100644 |
5260 |
+--- a/include/uapi/linux/netlink.h |
5261 |
++++ b/include/uapi/linux/netlink.h |
5262 |
+@@ -106,8 +106,10 @@ struct nlmsgerr { |
5263 |
+ #define NETLINK_PKTINFO 3 |
5264 |
+ #define NETLINK_BROADCAST_ERROR 4 |
5265 |
+ #define NETLINK_NO_ENOBUFS 5 |
5266 |
++#ifndef __KERNEL__ |
5267 |
+ #define NETLINK_RX_RING 6 |
5268 |
+ #define NETLINK_TX_RING 7 |
5269 |
++#endif |
5270 |
+ |
5271 |
+ struct nl_pktinfo { |
5272 |
+ __u32 group; |
5273 |
+@@ -130,6 +132,7 @@ struct nl_mmap_hdr { |
5274 |
+ __u32 nm_gid; |
5275 |
+ }; |
5276 |
+ |
5277 |
++#ifndef __KERNEL__ |
5278 |
+ enum nl_mmap_status { |
5279 |
+ NL_MMAP_STATUS_UNUSED, |
5280 |
+ NL_MMAP_STATUS_RESERVED, |
5281 |
+@@ -141,6 +144,7 @@ enum nl_mmap_status { |
5282 |
+ #define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO |
5283 |
+ #define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT) |
5284 |
+ #define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr)) |
5285 |
++#endif |
5286 |
+ |
5287 |
+ #define NET_MAJOR 36 /* Major 36 is reserved for networking */ |
5288 |
+ |
5289 |
+diff --git a/include/uapi/linux/netlink_diag.h b/include/uapi/linux/netlink_diag.h |
5290 |
+index f2159d30d1f5..d79399394b46 100644 |
5291 |
+--- a/include/uapi/linux/netlink_diag.h |
5292 |
++++ b/include/uapi/linux/netlink_diag.h |
5293 |
+@@ -48,6 +48,8 @@ enum { |
5294 |
+ |
5295 |
+ #define NDIAG_SHOW_MEMINFO 0x00000001 /* show memory info of a socket */ |
5296 |
+ #define NDIAG_SHOW_GROUPS 0x00000002 /* show groups of a netlink socket */ |
5297 |
++#ifndef __KERNEL__ |
5298 |
+ #define NDIAG_SHOW_RING_CFG 0x00000004 /* show ring configuration */ |
5299 |
++#endif |
5300 |
+ |
5301 |
+ #endif |
5302 |
+diff --git a/include/uapi/linux/packet_diag.h b/include/uapi/linux/packet_diag.h |
5303 |
+index d08c63f3dd6f..0c5d5dd61b6a 100644 |
5304 |
+--- a/include/uapi/linux/packet_diag.h |
5305 |
++++ b/include/uapi/linux/packet_diag.h |
5306 |
+@@ -64,7 +64,7 @@ struct packet_diag_mclist { |
5307 |
+ __u32 pdmc_count; |
5308 |
+ __u16 pdmc_type; |
5309 |
+ __u16 pdmc_alen; |
5310 |
+- __u8 pdmc_addr[MAX_ADDR_LEN]; |
5311 |
++ __u8 pdmc_addr[32]; /* MAX_ADDR_LEN */ |
5312 |
+ }; |
5313 |
+ |
5314 |
+ struct packet_diag_ring { |
5315 |
+diff --git a/kernel/futex.c b/kernel/futex.c |
5316 |
+index 8874a7b431e4..54ebb63711f4 100644 |
5317 |
+--- a/kernel/futex.c |
5318 |
++++ b/kernel/futex.c |
5319 |
+@@ -2567,7 +2567,6 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, |
5320 |
+ { |
5321 |
+ struct hrtimer_sleeper timeout, *to = NULL; |
5322 |
+ struct rt_mutex_waiter rt_waiter; |
5323 |
+- struct rt_mutex *pi_mutex = NULL; |
5324 |
+ struct futex_hash_bucket *hb; |
5325 |
+ union futex_key key2 = FUTEX_KEY_INIT; |
5326 |
+ struct futex_q q = futex_q_init; |
5327 |
+@@ -2651,6 +2650,8 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, |
5328 |
+ if (q.pi_state && (q.pi_state->owner != current)) { |
5329 |
+ spin_lock(q.lock_ptr); |
5330 |
+ ret = fixup_pi_state_owner(uaddr2, &q, current); |
5331 |
++ if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current) |
5332 |
++ rt_mutex_unlock(&q.pi_state->pi_mutex); |
5333 |
+ /* |
5334 |
+ * Drop the reference to the pi state which |
5335 |
+ * the requeue_pi() code acquired for us. |
5336 |
+@@ -2659,6 +2660,8 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, |
5337 |
+ spin_unlock(q.lock_ptr); |
5338 |
+ } |
5339 |
+ } else { |
5340 |
++ struct rt_mutex *pi_mutex; |
5341 |
++ |
5342 |
+ /* |
5343 |
+ * We have been woken up by futex_unlock_pi(), a timeout, or a |
5344 |
+ * signal. futex_unlock_pi() will not destroy the lock_ptr nor |
5345 |
+@@ -2682,18 +2685,19 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, |
5346 |
+ if (res) |
5347 |
+ ret = (res < 0) ? res : 0; |
5348 |
+ |
5349 |
++ /* |
5350 |
++ * If fixup_pi_state_owner() faulted and was unable to handle |
5351 |
++ * the fault, unlock the rt_mutex and return the fault to |
5352 |
++ * userspace. |
5353 |
++ */ |
5354 |
++ if (ret && rt_mutex_owner(pi_mutex) == current) |
5355 |
++ rt_mutex_unlock(pi_mutex); |
5356 |
++ |
5357 |
+ /* Unqueue and drop the lock. */ |
5358 |
+ unqueue_me_pi(&q); |
5359 |
+ } |
5360 |
+ |
5361 |
+- /* |
5362 |
+- * If fixup_pi_state_owner() faulted and was unable to handle the |
5363 |
+- * fault, unlock the rt_mutex and return the fault to userspace. |
5364 |
+- */ |
5365 |
+- if (ret == -EFAULT) { |
5366 |
+- if (pi_mutex && rt_mutex_owner(pi_mutex) == current) |
5367 |
+- rt_mutex_unlock(pi_mutex); |
5368 |
+- } else if (ret == -EINTR) { |
5369 |
++ if (ret == -EINTR) { |
5370 |
+ /* |
5371 |
+ * We've already been requeued, but cannot restart by calling |
5372 |
+ * futex_lock_pi() directly. We could restart this syscall, but |
5373 |
+diff --git a/kernel/padata.c b/kernel/padata.c |
5374 |
+index 161402f0b517..1e3f9772dbd4 100644 |
5375 |
+--- a/kernel/padata.c |
5376 |
++++ b/kernel/padata.c |
5377 |
+@@ -189,19 +189,20 @@ static struct padata_priv *padata_get_next(struct parallel_data *pd) |
5378 |
+ |
5379 |
+ reorder = &next_queue->reorder; |
5380 |
+ |
5381 |
++ spin_lock(&reorder->lock); |
5382 |
+ if (!list_empty(&reorder->list)) { |
5383 |
+ padata = list_entry(reorder->list.next, |
5384 |
+ struct padata_priv, list); |
5385 |
+ |
5386 |
+- spin_lock(&reorder->lock); |
5387 |
+ list_del_init(&padata->list); |
5388 |
+ atomic_dec(&pd->reorder_objects); |
5389 |
+- spin_unlock(&reorder->lock); |
5390 |
+ |
5391 |
+ pd->processed++; |
5392 |
+ |
5393 |
++ spin_unlock(&reorder->lock); |
5394 |
+ goto out; |
5395 |
+ } |
5396 |
++ spin_unlock(&reorder->lock); |
5397 |
+ |
5398 |
+ if (__this_cpu_read(pd->pqueue->cpu_index) == next_queue->cpu_index) { |
5399 |
+ padata = ERR_PTR(-ENODATA); |
5400 |
+diff --git a/lib/vsprintf.c b/lib/vsprintf.c |
5401 |
+index ec337f64f52d..3146abf4efc3 100644 |
5402 |
+--- a/lib/vsprintf.c |
5403 |
++++ b/lib/vsprintf.c |
5404 |
+@@ -1728,7 +1728,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) |
5405 |
+ |
5406 |
+ /* Reject out-of-range values early. Large positive sizes are |
5407 |
+ used for unknown buffer sizes. */ |
5408 |
+- if (WARN_ON_ONCE((int) size < 0)) |
5409 |
++ if (WARN_ON_ONCE(size > INT_MAX)) |
5410 |
+ return 0; |
5411 |
+ |
5412 |
+ str = buf; |
5413 |
+diff --git a/mm/swapfile.c b/mm/swapfile.c |
5414 |
+index 8798b2e0ac59..14ae9e3ec728 100644 |
5415 |
+--- a/mm/swapfile.c |
5416 |
++++ b/mm/swapfile.c |
5417 |
+@@ -2184,6 +2184,8 @@ static unsigned long read_swap_header(struct swap_info_struct *p, |
5418 |
+ swab32s(&swap_header->info.version); |
5419 |
+ swab32s(&swap_header->info.last_page); |
5420 |
+ swab32s(&swap_header->info.nr_badpages); |
5421 |
++ if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES) |
5422 |
++ return 0; |
5423 |
+ for (i = 0; i < swap_header->info.nr_badpages; i++) |
5424 |
+ swab32s(&swap_header->info.badpages[i]); |
5425 |
+ } |
5426 |
+diff --git a/net/can/af_can.c b/net/can/af_can.c |
5427 |
+index d6030d6949df..ee6eee7a8b42 100644 |
5428 |
+--- a/net/can/af_can.c |
5429 |
++++ b/net/can/af_can.c |
5430 |
+@@ -446,6 +446,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, |
5431 |
+ * @func: callback function on filter match |
5432 |
+ * @data: returned parameter for callback function |
5433 |
+ * @ident: string for calling module identification |
5434 |
++ * @sk: socket pointer (might be NULL) |
5435 |
+ * |
5436 |
+ * Description: |
5437 |
+ * Invokes the callback function with the received sk_buff and the given |
5438 |
+@@ -469,7 +470,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, |
5439 |
+ */ |
5440 |
+ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, |
5441 |
+ void (*func)(struct sk_buff *, void *), void *data, |
5442 |
+- char *ident) |
5443 |
++ char *ident, struct sock *sk) |
5444 |
+ { |
5445 |
+ struct receiver *r; |
5446 |
+ struct hlist_head *rl; |
5447 |
+@@ -497,6 +498,7 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, |
5448 |
+ r->func = func; |
5449 |
+ r->data = data; |
5450 |
+ r->ident = ident; |
5451 |
++ r->sk = sk; |
5452 |
+ |
5453 |
+ hlist_add_head_rcu(&r->list, rl); |
5454 |
+ d->entries++; |
5455 |
+@@ -521,8 +523,11 @@ EXPORT_SYMBOL(can_rx_register); |
5456 |
+ static void can_rx_delete_receiver(struct rcu_head *rp) |
5457 |
+ { |
5458 |
+ struct receiver *r = container_of(rp, struct receiver, rcu); |
5459 |
++ struct sock *sk = r->sk; |
5460 |
+ |
5461 |
+ kmem_cache_free(rcv_cache, r); |
5462 |
++ if (sk) |
5463 |
++ sock_put(sk); |
5464 |
+ } |
5465 |
+ |
5466 |
+ /** |
5467 |
+@@ -597,8 +602,11 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask, |
5468 |
+ spin_unlock(&can_rcvlists_lock); |
5469 |
+ |
5470 |
+ /* schedule the receiver item for deletion */ |
5471 |
+- if (r) |
5472 |
++ if (r) { |
5473 |
++ if (r->sk) |
5474 |
++ sock_hold(r->sk); |
5475 |
+ call_rcu(&r->rcu, can_rx_delete_receiver); |
5476 |
++ } |
5477 |
+ } |
5478 |
+ EXPORT_SYMBOL(can_rx_unregister); |
5479 |
+ |
5480 |
+diff --git a/net/can/af_can.h b/net/can/af_can.h |
5481 |
+index fca0fe9fc45a..b86f5129e838 100644 |
5482 |
+--- a/net/can/af_can.h |
5483 |
++++ b/net/can/af_can.h |
5484 |
+@@ -50,13 +50,14 @@ |
5485 |
+ |
5486 |
+ struct receiver { |
5487 |
+ struct hlist_node list; |
5488 |
+- struct rcu_head rcu; |
5489 |
+ canid_t can_id; |
5490 |
+ canid_t mask; |
5491 |
+ unsigned long matches; |
5492 |
+ void (*func)(struct sk_buff *, void *); |
5493 |
+ void *data; |
5494 |
+ char *ident; |
5495 |
++ struct sock *sk; |
5496 |
++ struct rcu_head rcu; |
5497 |
+ }; |
5498 |
+ |
5499 |
+ #define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS) |
5500 |
+diff --git a/net/can/bcm.c b/net/can/bcm.c |
5501 |
+index dcb75c0e66c1..51c208f0d3d1 100644 |
5502 |
+--- a/net/can/bcm.c |
5503 |
++++ b/net/can/bcm.c |
5504 |
+@@ -1169,7 +1169,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, |
5505 |
+ err = can_rx_register(dev, op->can_id, |
5506 |
+ REGMASK(op->can_id), |
5507 |
+ bcm_rx_handler, op, |
5508 |
+- "bcm"); |
5509 |
++ "bcm", sk); |
5510 |
+ |
5511 |
+ op->rx_reg_dev = dev; |
5512 |
+ dev_put(dev); |
5513 |
+@@ -1178,7 +1178,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, |
5514 |
+ } else |
5515 |
+ err = can_rx_register(NULL, op->can_id, |
5516 |
+ REGMASK(op->can_id), |
5517 |
+- bcm_rx_handler, op, "bcm"); |
5518 |
++ bcm_rx_handler, op, "bcm", sk); |
5519 |
+ if (err) { |
5520 |
+ /* this bcm rx op is broken -> remove it */ |
5521 |
+ list_del(&op->list); |
5522 |
+diff --git a/net/can/gw.c b/net/can/gw.c |
5523 |
+index 050a2110d43f..d4921582d3bd 100644 |
5524 |
+--- a/net/can/gw.c |
5525 |
++++ b/net/can/gw.c |
5526 |
+@@ -441,7 +441,7 @@ static inline int cgw_register_filter(struct cgw_job *gwj) |
5527 |
+ { |
5528 |
+ return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id, |
5529 |
+ gwj->ccgw.filter.can_mask, can_can_gw_rcv, |
5530 |
+- gwj, "gw"); |
5531 |
++ gwj, "gw", NULL); |
5532 |
+ } |
5533 |
+ |
5534 |
+ static inline void cgw_unregister_filter(struct cgw_job *gwj) |
5535 |
+diff --git a/net/can/raw.c b/net/can/raw.c |
5536 |
+index 081e81fd017f..bdca782df701 100644 |
5537 |
+--- a/net/can/raw.c |
5538 |
++++ b/net/can/raw.c |
5539 |
+@@ -164,7 +164,7 @@ static int raw_enable_filters(struct net_device *dev, struct sock *sk, |
5540 |
+ for (i = 0; i < count; i++) { |
5541 |
+ err = can_rx_register(dev, filter[i].can_id, |
5542 |
+ filter[i].can_mask, |
5543 |
+- raw_rcv, sk, "raw"); |
5544 |
++ raw_rcv, sk, "raw", sk); |
5545 |
+ if (err) { |
5546 |
+ /* clean up successfully registered filters */ |
5547 |
+ while (--i >= 0) |
5548 |
+@@ -185,7 +185,7 @@ static int raw_enable_errfilter(struct net_device *dev, struct sock *sk, |
5549 |
+ |
5550 |
+ if (err_mask) |
5551 |
+ err = can_rx_register(dev, 0, err_mask | CAN_ERR_FLAG, |
5552 |
+- raw_rcv, sk, "raw"); |
5553 |
++ raw_rcv, sk, "raw", sk); |
5554 |
+ |
5555 |
+ return err; |
5556 |
+ } |
5557 |
+diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c |
5558 |
+index 60441b6a9546..8bb2e0c1cb50 100644 |
5559 |
+--- a/net/ceph/osdmap.c |
5560 |
++++ b/net/ceph/osdmap.c |
5561 |
+@@ -1240,7 +1240,6 @@ static int decode_new_up_state_weight(void **p, void *end, |
5562 |
+ if ((map->osd_state[osd] & CEPH_OSD_EXISTS) && |
5563 |
+ (xorstate & CEPH_OSD_EXISTS)) { |
5564 |
+ pr_info("osd%d does not exist\n", osd); |
5565 |
+- map->osd_weight[osd] = CEPH_OSD_IN; |
5566 |
+ ret = set_primary_affinity(map, osd, |
5567 |
+ CEPH_OSD_DEFAULT_PRIMARY_AFFINITY); |
5568 |
+ if (ret) |
5569 |
+diff --git a/net/core/dev.c b/net/core/dev.c |
5570 |
+index 2a24197f3a45..86bdf6d813f6 100644 |
5571 |
+--- a/net/core/dev.c |
5572 |
++++ b/net/core/dev.c |
5573 |
+@@ -1611,24 +1611,19 @@ EXPORT_SYMBOL(call_netdevice_notifiers); |
5574 |
+ |
5575 |
+ static struct static_key netstamp_needed __read_mostly; |
5576 |
+ #ifdef HAVE_JUMP_LABEL |
5577 |
+-/* We are not allowed to call static_key_slow_dec() from irq context |
5578 |
+- * If net_disable_timestamp() is called from irq context, defer the |
5579 |
+- * static_key_slow_dec() calls. |
5580 |
+- */ |
5581 |
+ static atomic_t netstamp_needed_deferred; |
5582 |
+-#endif |
5583 |
+- |
5584 |
+-void net_enable_timestamp(void) |
5585 |
++static void netstamp_clear(struct work_struct *work) |
5586 |
+ { |
5587 |
+-#ifdef HAVE_JUMP_LABEL |
5588 |
+ int deferred = atomic_xchg(&netstamp_needed_deferred, 0); |
5589 |
+ |
5590 |
+- if (deferred) { |
5591 |
+- while (--deferred) |
5592 |
+- static_key_slow_dec(&netstamp_needed); |
5593 |
+- return; |
5594 |
+- } |
5595 |
++ while (deferred--) |
5596 |
++ static_key_slow_dec(&netstamp_needed); |
5597 |
++} |
5598 |
++static DECLARE_WORK(netstamp_work, netstamp_clear); |
5599 |
+ #endif |
5600 |
++ |
5601 |
++void net_enable_timestamp(void) |
5602 |
++{ |
5603 |
+ static_key_slow_inc(&netstamp_needed); |
5604 |
+ } |
5605 |
+ EXPORT_SYMBOL(net_enable_timestamp); |
5606 |
+@@ -1636,12 +1631,12 @@ EXPORT_SYMBOL(net_enable_timestamp); |
5607 |
+ void net_disable_timestamp(void) |
5608 |
+ { |
5609 |
+ #ifdef HAVE_JUMP_LABEL |
5610 |
+- if (in_interrupt()) { |
5611 |
+- atomic_inc(&netstamp_needed_deferred); |
5612 |
+- return; |
5613 |
+- } |
5614 |
+-#endif |
5615 |
++ /* net_disable_timestamp() can be called from non process context */ |
5616 |
++ atomic_inc(&netstamp_needed_deferred); |
5617 |
++ schedule_work(&netstamp_work); |
5618 |
++#else |
5619 |
+ static_key_slow_dec(&netstamp_needed); |
5620 |
++#endif |
5621 |
+ } |
5622 |
+ EXPORT_SYMBOL(net_disable_timestamp); |
5623 |
+ |
5624 |
+@@ -2746,6 +2741,7 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d |
5625 |
+ } |
5626 |
+ return head; |
5627 |
+ } |
5628 |
++EXPORT_SYMBOL_GPL(validate_xmit_skb_list); |
5629 |
+ |
5630 |
+ static void qdisc_pkt_len_init(struct sk_buff *skb) |
5631 |
+ { |
5632 |
+@@ -4898,6 +4894,7 @@ static inline bool netdev_adjacent_is_neigh_list(struct net_device *dev, |
5633 |
+ |
5634 |
+ static int __netdev_adjacent_dev_insert(struct net_device *dev, |
5635 |
+ struct net_device *adj_dev, |
5636 |
++ u16 ref_nr, |
5637 |
+ struct list_head *dev_list, |
5638 |
+ void *private, bool master) |
5639 |
+ { |
5640 |
+@@ -4907,7 +4904,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, |
5641 |
+ adj = __netdev_find_adj(dev, adj_dev, dev_list); |
5642 |
+ |
5643 |
+ if (adj) { |
5644 |
+- adj->ref_nr++; |
5645 |
++ adj->ref_nr += ref_nr; |
5646 |
+ return 0; |
5647 |
+ } |
5648 |
+ |
5649 |
+@@ -4917,7 +4914,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, |
5650 |
+ |
5651 |
+ adj->dev = adj_dev; |
5652 |
+ adj->master = master; |
5653 |
+- adj->ref_nr = 1; |
5654 |
++ adj->ref_nr = ref_nr; |
5655 |
+ adj->private = private; |
5656 |
+ dev_hold(adj_dev); |
5657 |
+ |
5658 |
+@@ -4956,6 +4953,7 @@ free_adj: |
5659 |
+ |
5660 |
+ static void __netdev_adjacent_dev_remove(struct net_device *dev, |
5661 |
+ struct net_device *adj_dev, |
5662 |
++ u16 ref_nr, |
5663 |
+ struct list_head *dev_list) |
5664 |
+ { |
5665 |
+ struct netdev_adjacent *adj; |
5666 |
+@@ -4968,10 +4966,10 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev, |
5667 |
+ BUG(); |
5668 |
+ } |
5669 |
+ |
5670 |
+- if (adj->ref_nr > 1) { |
5671 |
+- pr_debug("%s to %s ref_nr-- = %d\n", dev->name, adj_dev->name, |
5672 |
+- adj->ref_nr-1); |
5673 |
+- adj->ref_nr--; |
5674 |
++ if (adj->ref_nr > ref_nr) { |
5675 |
++ pr_debug("%s to %s ref_nr-%d = %d\n", dev->name, adj_dev->name, |
5676 |
++ ref_nr, adj->ref_nr-ref_nr); |
5677 |
++ adj->ref_nr -= ref_nr; |
5678 |
+ return; |
5679 |
+ } |
5680 |
+ |
5681 |
+@@ -4990,21 +4988,22 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev, |
5682 |
+ |
5683 |
+ static int __netdev_adjacent_dev_link_lists(struct net_device *dev, |
5684 |
+ struct net_device *upper_dev, |
5685 |
++ u16 ref_nr, |
5686 |
+ struct list_head *up_list, |
5687 |
+ struct list_head *down_list, |
5688 |
+ void *private, bool master) |
5689 |
+ { |
5690 |
+ int ret; |
5691 |
+ |
5692 |
+- ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, private, |
5693 |
+- master); |
5694 |
++ ret = __netdev_adjacent_dev_insert(dev, upper_dev, ref_nr, up_list, |
5695 |
++ private, master); |
5696 |
+ if (ret) |
5697 |
+ return ret; |
5698 |
+ |
5699 |
+- ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, private, |
5700 |
+- false); |
5701 |
++ ret = __netdev_adjacent_dev_insert(upper_dev, dev, ref_nr, down_list, |
5702 |
++ private, false); |
5703 |
+ if (ret) { |
5704 |
+- __netdev_adjacent_dev_remove(dev, upper_dev, up_list); |
5705 |
++ __netdev_adjacent_dev_remove(dev, upper_dev, ref_nr, up_list); |
5706 |
+ return ret; |
5707 |
+ } |
5708 |
+ |
5709 |
+@@ -5012,9 +5011,10 @@ static int __netdev_adjacent_dev_link_lists(struct net_device *dev, |
5710 |
+ } |
5711 |
+ |
5712 |
+ static int __netdev_adjacent_dev_link(struct net_device *dev, |
5713 |
+- struct net_device *upper_dev) |
5714 |
++ struct net_device *upper_dev, |
5715 |
++ u16 ref_nr) |
5716 |
+ { |
5717 |
+- return __netdev_adjacent_dev_link_lists(dev, upper_dev, |
5718 |
++ return __netdev_adjacent_dev_link_lists(dev, upper_dev, ref_nr, |
5719 |
+ &dev->all_adj_list.upper, |
5720 |
+ &upper_dev->all_adj_list.lower, |
5721 |
+ NULL, false); |
5722 |
+@@ -5022,17 +5022,19 @@ static int __netdev_adjacent_dev_link(struct net_device *dev, |
5723 |
+ |
5724 |
+ static void __netdev_adjacent_dev_unlink_lists(struct net_device *dev, |
5725 |
+ struct net_device *upper_dev, |
5726 |
++ u16 ref_nr, |
5727 |
+ struct list_head *up_list, |
5728 |
+ struct list_head *down_list) |
5729 |
+ { |
5730 |
+- __netdev_adjacent_dev_remove(dev, upper_dev, up_list); |
5731 |
+- __netdev_adjacent_dev_remove(upper_dev, dev, down_list); |
5732 |
++ __netdev_adjacent_dev_remove(dev, upper_dev, ref_nr, up_list); |
5733 |
++ __netdev_adjacent_dev_remove(upper_dev, dev, ref_nr, down_list); |
5734 |
+ } |
5735 |
+ |
5736 |
+ static void __netdev_adjacent_dev_unlink(struct net_device *dev, |
5737 |
+- struct net_device *upper_dev) |
5738 |
++ struct net_device *upper_dev, |
5739 |
++ u16 ref_nr) |
5740 |
+ { |
5741 |
+- __netdev_adjacent_dev_unlink_lists(dev, upper_dev, |
5742 |
++ __netdev_adjacent_dev_unlink_lists(dev, upper_dev, ref_nr, |
5743 |
+ &dev->all_adj_list.upper, |
5744 |
+ &upper_dev->all_adj_list.lower); |
5745 |
+ } |
5746 |
+@@ -5041,17 +5043,17 @@ static int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, |
5747 |
+ struct net_device *upper_dev, |
5748 |
+ void *private, bool master) |
5749 |
+ { |
5750 |
+- int ret = __netdev_adjacent_dev_link(dev, upper_dev); |
5751 |
++ int ret = __netdev_adjacent_dev_link(dev, upper_dev, 1); |
5752 |
+ |
5753 |
+ if (ret) |
5754 |
+ return ret; |
5755 |
+ |
5756 |
+- ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, |
5757 |
++ ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, 1, |
5758 |
+ &dev->adj_list.upper, |
5759 |
+ &upper_dev->adj_list.lower, |
5760 |
+ private, master); |
5761 |
+ if (ret) { |
5762 |
+- __netdev_adjacent_dev_unlink(dev, upper_dev); |
5763 |
++ __netdev_adjacent_dev_unlink(dev, upper_dev, 1); |
5764 |
+ return ret; |
5765 |
+ } |
5766 |
+ |
5767 |
+@@ -5061,8 +5063,8 @@ static int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, |
5768 |
+ static void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev, |
5769 |
+ struct net_device *upper_dev) |
5770 |
+ { |
5771 |
+- __netdev_adjacent_dev_unlink(dev, upper_dev); |
5772 |
+- __netdev_adjacent_dev_unlink_lists(dev, upper_dev, |
5773 |
++ __netdev_adjacent_dev_unlink(dev, upper_dev, 1); |
5774 |
++ __netdev_adjacent_dev_unlink_lists(dev, upper_dev, 1, |
5775 |
+ &dev->adj_list.upper, |
5776 |
+ &upper_dev->adj_list.lower); |
5777 |
+ } |
5778 |
+@@ -5103,7 +5105,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, |
5779 |
+ list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) { |
5780 |
+ pr_debug("Interlinking %s with %s, non-neighbour\n", |
5781 |
+ i->dev->name, j->dev->name); |
5782 |
+- ret = __netdev_adjacent_dev_link(i->dev, j->dev); |
5783 |
++ ret = __netdev_adjacent_dev_link(i->dev, j->dev, i->ref_nr); |
5784 |
+ if (ret) |
5785 |
+ goto rollback_mesh; |
5786 |
+ } |
5787 |
+@@ -5113,7 +5115,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, |
5788 |
+ list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) { |
5789 |
+ pr_debug("linking %s's upper device %s with %s\n", |
5790 |
+ upper_dev->name, i->dev->name, dev->name); |
5791 |
+- ret = __netdev_adjacent_dev_link(dev, i->dev); |
5792 |
++ ret = __netdev_adjacent_dev_link(dev, i->dev, i->ref_nr); |
5793 |
+ if (ret) |
5794 |
+ goto rollback_upper_mesh; |
5795 |
+ } |
5796 |
+@@ -5122,7 +5124,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, |
5797 |
+ list_for_each_entry(i, &dev->all_adj_list.lower, list) { |
5798 |
+ pr_debug("linking %s's lower device %s with %s\n", dev->name, |
5799 |
+ i->dev->name, upper_dev->name); |
5800 |
+- ret = __netdev_adjacent_dev_link(i->dev, upper_dev); |
5801 |
++ ret = __netdev_adjacent_dev_link(i->dev, upper_dev, i->ref_nr); |
5802 |
+ if (ret) |
5803 |
+ goto rollback_lower_mesh; |
5804 |
+ } |
5805 |
+@@ -5135,7 +5137,7 @@ rollback_lower_mesh: |
5806 |
+ list_for_each_entry(i, &dev->all_adj_list.lower, list) { |
5807 |
+ if (i == to_i) |
5808 |
+ break; |
5809 |
+- __netdev_adjacent_dev_unlink(i->dev, upper_dev); |
5810 |
++ __netdev_adjacent_dev_unlink(i->dev, upper_dev, i->ref_nr); |
5811 |
+ } |
5812 |
+ |
5813 |
+ i = NULL; |
5814 |
+@@ -5145,7 +5147,7 @@ rollback_upper_mesh: |
5815 |
+ list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) { |
5816 |
+ if (i == to_i) |
5817 |
+ break; |
5818 |
+- __netdev_adjacent_dev_unlink(dev, i->dev); |
5819 |
++ __netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr); |
5820 |
+ } |
5821 |
+ |
5822 |
+ i = j = NULL; |
5823 |
+@@ -5157,7 +5159,7 @@ rollback_mesh: |
5824 |
+ list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) { |
5825 |
+ if (i == to_i && j == to_j) |
5826 |
+ break; |
5827 |
+- __netdev_adjacent_dev_unlink(i->dev, j->dev); |
5828 |
++ __netdev_adjacent_dev_unlink(i->dev, j->dev, i->ref_nr); |
5829 |
+ } |
5830 |
+ if (i == to_i) |
5831 |
+ break; |
5832 |
+@@ -5233,16 +5235,16 @@ void netdev_upper_dev_unlink(struct net_device *dev, |
5833 |
+ */ |
5834 |
+ list_for_each_entry(i, &dev->all_adj_list.lower, list) |
5835 |
+ list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) |
5836 |
+- __netdev_adjacent_dev_unlink(i->dev, j->dev); |
5837 |
++ __netdev_adjacent_dev_unlink(i->dev, j->dev, i->ref_nr); |
5838 |
+ |
5839 |
+ /* remove also the devices itself from lower/upper device |
5840 |
+ * list |
5841 |
+ */ |
5842 |
+ list_for_each_entry(i, &dev->all_adj_list.lower, list) |
5843 |
+- __netdev_adjacent_dev_unlink(i->dev, upper_dev); |
5844 |
++ __netdev_adjacent_dev_unlink(i->dev, upper_dev, i->ref_nr); |
5845 |
+ |
5846 |
+ list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) |
5847 |
+- __netdev_adjacent_dev_unlink(dev, i->dev); |
5848 |
++ __netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr); |
5849 |
+ |
5850 |
+ call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev); |
5851 |
+ } |
5852 |
+diff --git a/net/core/pktgen.c b/net/core/pktgen.c |
5853 |
+index 4ff3eacc99f5..b3aa63260cab 100644 |
5854 |
+--- a/net/core/pktgen.c |
5855 |
++++ b/net/core/pktgen.c |
5856 |
+@@ -211,8 +211,8 @@ |
5857 |
+ #define T_REMDEV (1<<3) /* Remove one dev */ |
5858 |
+ |
5859 |
+ /* If lock -- protects updating of if_list */ |
5860 |
+-#define if_lock(t) spin_lock(&(t->if_lock)); |
5861 |
+-#define if_unlock(t) spin_unlock(&(t->if_lock)); |
5862 |
++#define if_lock(t) mutex_lock(&(t->if_lock)); |
5863 |
++#define if_unlock(t) mutex_unlock(&(t->if_lock)); |
5864 |
+ |
5865 |
+ /* Used to help with determining the pkts on receive */ |
5866 |
+ #define PKTGEN_MAGIC 0xbe9be955 |
5867 |
+@@ -418,7 +418,7 @@ struct pktgen_net { |
5868 |
+ }; |
5869 |
+ |
5870 |
+ struct pktgen_thread { |
5871 |
+- spinlock_t if_lock; /* for list of devices */ |
5872 |
++ struct mutex if_lock; /* for list of devices */ |
5873 |
+ struct list_head if_list; /* All device here */ |
5874 |
+ struct list_head th_list; |
5875 |
+ struct task_struct *tsk; |
5876 |
+@@ -1952,11 +1952,13 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d |
5877 |
+ { |
5878 |
+ struct pktgen_thread *t; |
5879 |
+ |
5880 |
++ mutex_lock(&pktgen_thread_lock); |
5881 |
++ |
5882 |
+ list_for_each_entry(t, &pn->pktgen_threads, th_list) { |
5883 |
+ struct pktgen_dev *pkt_dev; |
5884 |
+ |
5885 |
+- rcu_read_lock(); |
5886 |
+- list_for_each_entry_rcu(pkt_dev, &t->if_list, list) { |
5887 |
++ if_lock(t); |
5888 |
++ list_for_each_entry(pkt_dev, &t->if_list, list) { |
5889 |
+ if (pkt_dev->odev != dev) |
5890 |
+ continue; |
5891 |
+ |
5892 |
+@@ -1971,8 +1973,9 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d |
5893 |
+ dev->name); |
5894 |
+ break; |
5895 |
+ } |
5896 |
+- rcu_read_unlock(); |
5897 |
++ if_unlock(t); |
5898 |
+ } |
5899 |
++ mutex_unlock(&pktgen_thread_lock); |
5900 |
+ } |
5901 |
+ |
5902 |
+ static int pktgen_device_event(struct notifier_block *unused, |
5903 |
+@@ -3656,7 +3659,7 @@ static int __net_init pktgen_create_thread(int cpu, struct pktgen_net *pn) |
5904 |
+ return -ENOMEM; |
5905 |
+ } |
5906 |
+ |
5907 |
+- spin_lock_init(&t->if_lock); |
5908 |
++ mutex_init(&t->if_lock); |
5909 |
+ t->cpu = cpu; |
5910 |
+ |
5911 |
+ INIT_LIST_HEAD(&t->if_list); |
5912 |
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c |
5913 |
+index 97549212e9e3..b2e2a53c2284 100644 |
5914 |
+--- a/net/core/skbuff.c |
5915 |
++++ b/net/core/skbuff.c |
5916 |
+@@ -3617,13 +3617,14 @@ void skb_complete_tx_timestamp(struct sk_buff *skb, |
5917 |
+ { |
5918 |
+ struct sock *sk = skb->sk; |
5919 |
+ |
5920 |
+- /* take a reference to prevent skb_orphan() from freeing the socket */ |
5921 |
+- sock_hold(sk); |
5922 |
+- |
5923 |
+- *skb_hwtstamps(skb) = *hwtstamps; |
5924 |
+- __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND); |
5925 |
+- |
5926 |
+- sock_put(sk); |
5927 |
++ /* Take a reference to prevent skb_orphan() from freeing the socket, |
5928 |
++ * but only if the socket refcount is not zero. |
5929 |
++ */ |
5930 |
++ if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) { |
5931 |
++ *skb_hwtstamps(skb) = *hwtstamps; |
5932 |
++ __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND); |
5933 |
++ sock_put(sk); |
5934 |
++ } |
5935 |
+ } |
5936 |
+ EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp); |
5937 |
+ |
5938 |
+@@ -3661,7 +3662,7 @@ void skb_complete_wifi_ack(struct sk_buff *skb, bool acked) |
5939 |
+ { |
5940 |
+ struct sock *sk = skb->sk; |
5941 |
+ struct sock_exterr_skb *serr; |
5942 |
+- int err; |
5943 |
++ int err = 1; |
5944 |
+ |
5945 |
+ skb->wifi_acked_valid = 1; |
5946 |
+ skb->wifi_acked = acked; |
5947 |
+@@ -3671,14 +3672,15 @@ void skb_complete_wifi_ack(struct sk_buff *skb, bool acked) |
5948 |
+ serr->ee.ee_errno = ENOMSG; |
5949 |
+ serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS; |
5950 |
+ |
5951 |
+- /* take a reference to prevent skb_orphan() from freeing the socket */ |
5952 |
+- sock_hold(sk); |
5953 |
+- |
5954 |
+- err = sock_queue_err_skb(sk, skb); |
5955 |
++ /* Take a reference to prevent skb_orphan() from freeing the socket, |
5956 |
++ * but only if the socket refcount is not zero. |
5957 |
++ */ |
5958 |
++ if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) { |
5959 |
++ err = sock_queue_err_skb(sk, skb); |
5960 |
++ sock_put(sk); |
5961 |
++ } |
5962 |
+ if (err) |
5963 |
+ kfree_skb(skb); |
5964 |
+- |
5965 |
+- sock_put(sk); |
5966 |
+ } |
5967 |
+ EXPORT_SYMBOL_GPL(skb_complete_wifi_ack); |
5968 |
+ |
5969 |
+diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c |
5970 |
+index f053198e730c..5e3a7302f774 100644 |
5971 |
+--- a/net/dccp/ccids/ccid2.c |
5972 |
++++ b/net/dccp/ccids/ccid2.c |
5973 |
+@@ -749,6 +749,7 @@ static void ccid2_hc_tx_exit(struct sock *sk) |
5974 |
+ for (i = 0; i < hc->tx_seqbufc; i++) |
5975 |
+ kfree(hc->tx_seqbuf[i]); |
5976 |
+ hc->tx_seqbufc = 0; |
5977 |
++ dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks); |
5978 |
+ } |
5979 |
+ |
5980 |
+ static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) |
5981 |
+diff --git a/net/dccp/input.c b/net/dccp/input.c |
5982 |
+index 3c8ec7d4a34e..700440e4fa3b 100644 |
5983 |
+--- a/net/dccp/input.c |
5984 |
++++ b/net/dccp/input.c |
5985 |
+@@ -606,7 +606,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, |
5986 |
+ if (inet_csk(sk)->icsk_af_ops->conn_request(sk, |
5987 |
+ skb) < 0) |
5988 |
+ return 1; |
5989 |
+- goto discard; |
5990 |
++ consume_skb(skb); |
5991 |
++ return 0; |
5992 |
+ } |
5993 |
+ if (dh->dccph_type == DCCP_PKT_RESET) |
5994 |
+ goto discard; |
5995 |
+diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c |
5996 |
+index 6ca645c4b48e..502d9a885329 100644 |
5997 |
+--- a/net/dccp/ipv4.c |
5998 |
++++ b/net/dccp/ipv4.c |
5999 |
+@@ -262,7 +262,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) |
6000 |
+ |
6001 |
+ switch (type) { |
6002 |
+ case ICMP_REDIRECT: |
6003 |
+- dccp_do_redirect(skb, sk); |
6004 |
++ if (!sock_owned_by_user(sk)) |
6005 |
++ dccp_do_redirect(skb, sk); |
6006 |
+ goto out; |
6007 |
+ case ICMP_SOURCE_QUENCH: |
6008 |
+ /* Just silently ignore these. */ |
6009 |
+diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c |
6010 |
+index 7bcb22317841..ff186dac3e07 100644 |
6011 |
+--- a/net/dccp/ipv6.c |
6012 |
++++ b/net/dccp/ipv6.c |
6013 |
+@@ -131,10 +131,12 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
6014 |
+ np = inet6_sk(sk); |
6015 |
+ |
6016 |
+ if (type == NDISC_REDIRECT) { |
6017 |
+- struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie); |
6018 |
++ if (!sock_owned_by_user(sk)) { |
6019 |
++ struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie); |
6020 |
+ |
6021 |
+- if (dst) |
6022 |
+- dst->ops->redirect(dst, sk, skb); |
6023 |
++ if (dst) |
6024 |
++ dst->ops->redirect(dst, sk, skb); |
6025 |
++ } |
6026 |
+ goto out; |
6027 |
+ } |
6028 |
+ |
6029 |
+diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c |
6030 |
+index b50dc436db1f..e6aaf92e0e1b 100644 |
6031 |
+--- a/net/dccp/minisocks.c |
6032 |
++++ b/net/dccp/minisocks.c |
6033 |
+@@ -135,6 +135,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk, |
6034 |
+ /* It is still raw copy of parent, so invalidate |
6035 |
+ * destructor and make plain sk_free() */ |
6036 |
+ newsk->sk_destruct = NULL; |
6037 |
++ bh_unlock_sock(newsk); |
6038 |
+ sk_free(newsk); |
6039 |
+ return NULL; |
6040 |
+ } |
6041 |
+diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c |
6042 |
+index bc7c9662a904..e08003d026eb 100644 |
6043 |
+--- a/net/ipv4/cipso_ipv4.c |
6044 |
++++ b/net/ipv4/cipso_ipv4.c |
6045 |
+@@ -1655,6 +1655,10 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option) |
6046 |
+ goto validate_return_locked; |
6047 |
+ } |
6048 |
+ |
6049 |
++ if (opt_iter + 1 == opt_len) { |
6050 |
++ err_offset = opt_iter; |
6051 |
++ goto validate_return_locked; |
6052 |
++ } |
6053 |
+ tag_len = tag[1]; |
6054 |
+ if (tag_len > (opt_len - opt_iter)) { |
6055 |
+ err_offset = opt_iter + 1; |
6056 |
+diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c |
6057 |
+index 046fce012da5..8839b55ea4de 100644 |
6058 |
+--- a/net/ipv4/ip_sockglue.c |
6059 |
++++ b/net/ipv4/ip_sockglue.c |
6060 |
+@@ -1066,7 +1066,14 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb) |
6061 |
+ pktinfo->ipi_ifindex = 0; |
6062 |
+ pktinfo->ipi_spec_dst.s_addr = 0; |
6063 |
+ } |
6064 |
+- skb_dst_drop(skb); |
6065 |
++ /* We need to keep the dst for __ip_options_echo() |
6066 |
++ * We could restrict the test to opt.ts_needtime || opt.srr, |
6067 |
++ * but the following is good enough as IP options are not often used. |
6068 |
++ */ |
6069 |
++ if (unlikely(IPCB(skb)->opt.optlen)) |
6070 |
++ skb_dst_force(skb); |
6071 |
++ else |
6072 |
++ skb_dst_drop(skb); |
6073 |
+ } |
6074 |
+ |
6075 |
+ int ip_setsockopt(struct sock *sk, int level, |
6076 |
+diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c |
6077 |
+index 1b7f6da99ef4..2348cc87b0bc 100644 |
6078 |
+--- a/net/ipv4/ipmr.c |
6079 |
++++ b/net/ipv4/ipmr.c |
6080 |
+@@ -2188,7 +2188,7 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, |
6081 |
+ |
6082 |
+ int ipmr_get_route(struct net *net, struct sk_buff *skb, |
6083 |
+ __be32 saddr, __be32 daddr, |
6084 |
+- struct rtmsg *rtm, int nowait) |
6085 |
++ struct rtmsg *rtm, int nowait, u32 portid) |
6086 |
+ { |
6087 |
+ struct mfc_cache *cache; |
6088 |
+ struct mr_table *mrt; |
6089 |
+@@ -2233,6 +2233,7 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb, |
6090 |
+ return -ENOMEM; |
6091 |
+ } |
6092 |
+ |
6093 |
++ NETLINK_CB(skb2).portid = portid; |
6094 |
+ skb_push(skb2, sizeof(struct iphdr)); |
6095 |
+ skb_reset_network_header(skb2); |
6096 |
+ iph = ip_hdr(skb2); |
6097 |
+diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c |
6098 |
+index 64f4edb2dbf9..c225b227cc45 100644 |
6099 |
+--- a/net/ipv4/ping.c |
6100 |
++++ b/net/ipv4/ping.c |
6101 |
+@@ -644,6 +644,8 @@ static int ping_v4_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, |
6102 |
+ { |
6103 |
+ struct sk_buff *skb = skb_peek(&sk->sk_write_queue); |
6104 |
+ |
6105 |
++ if (!skb) |
6106 |
++ return 0; |
6107 |
+ pfh->wcheck = csum_partial((char *)&pfh->icmph, |
6108 |
+ sizeof(struct icmphdr), pfh->wcheck); |
6109 |
+ pfh->icmph.checksum = csum_fold(pfh->wcheck); |
6110 |
+diff --git a/net/ipv4/route.c b/net/ipv4/route.c |
6111 |
+index 12c5df33c0b7..2fe9459fbe24 100644 |
6112 |
+--- a/net/ipv4/route.c |
6113 |
++++ b/net/ipv4/route.c |
6114 |
+@@ -1835,6 +1835,7 @@ int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr, |
6115 |
+ { |
6116 |
+ int res; |
6117 |
+ |
6118 |
++ tos &= IPTOS_RT_MASK; |
6119 |
+ rcu_read_lock(); |
6120 |
+ |
6121 |
+ /* Multicast recognition logic is moved from route cache to here. |
6122 |
+@@ -2373,7 +2374,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, |
6123 |
+ IPV4_DEVCONF_ALL(net, MC_FORWARDING)) { |
6124 |
+ int err = ipmr_get_route(net, skb, |
6125 |
+ fl4->saddr, fl4->daddr, |
6126 |
+- r, nowait); |
6127 |
++ r, nowait, portid); |
6128 |
++ |
6129 |
+ if (err <= 0) { |
6130 |
+ if (!nowait) { |
6131 |
+ if (err == 0) |
6132 |
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c |
6133 |
+index 633cd34f57ec..3d61bdbae920 100644 |
6134 |
+--- a/net/ipv4/sysctl_net_ipv4.c |
6135 |
++++ b/net/ipv4/sysctl_net_ipv4.c |
6136 |
+@@ -103,10 +103,10 @@ static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t hig |
6137 |
+ kgid_t *data = table->data; |
6138 |
+ struct net *net = |
6139 |
+ container_of(table->data, struct net, ipv4.ping_group_range.range); |
6140 |
+- write_seqlock(&net->ipv4.ip_local_ports.lock); |
6141 |
++ write_seqlock_bh(&net->ipv4.ip_local_ports.lock); |
6142 |
+ data[0] = low; |
6143 |
+ data[1] = high; |
6144 |
+- write_sequnlock(&net->ipv4.ip_local_ports.lock); |
6145 |
++ write_sequnlock_bh(&net->ipv4.ip_local_ports.lock); |
6146 |
+ } |
6147 |
+ |
6148 |
+ /* Validate changes from /proc interface. */ |
6149 |
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c |
6150 |
+index a21c47289765..daf3b217b1e4 100644 |
6151 |
+--- a/net/ipv4/tcp.c |
6152 |
++++ b/net/ipv4/tcp.c |
6153 |
+@@ -775,6 +775,12 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, |
6154 |
+ ret = -EAGAIN; |
6155 |
+ break; |
6156 |
+ } |
6157 |
++ /* if __tcp_splice_read() got nothing while we have |
6158 |
++ * an skb in receive queue, we do not want to loop. |
6159 |
++ * This might happen with URG data. |
6160 |
++ */ |
6161 |
++ if (!skb_queue_empty(&sk->sk_receive_queue)) |
6162 |
++ break; |
6163 |
+ sk_wait_data(sk, &timeo); |
6164 |
+ if (signal_pending(current)) { |
6165 |
+ ret = sock_intr_errno(timeo); |
6166 |
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c |
6167 |
+index 067baa738001..737186dbbd74 100644 |
6168 |
+--- a/net/ipv4/tcp_input.c |
6169 |
++++ b/net/ipv4/tcp_input.c |
6170 |
+@@ -2360,10 +2360,9 @@ static void DBGUNDO(struct sock *sk, const char *msg) |
6171 |
+ } |
6172 |
+ #if IS_ENABLED(CONFIG_IPV6) |
6173 |
+ else if (sk->sk_family == AF_INET6) { |
6174 |
+- struct ipv6_pinfo *np = inet6_sk(sk); |
6175 |
+ pr_debug("Undo %s %pI6/%u c%u l%u ss%u/%u p%u\n", |
6176 |
+ msg, |
6177 |
+- &np->daddr, ntohs(inet->inet_dport), |
6178 |
++ &sk->sk_v6_daddr, ntohs(inet->inet_dport), |
6179 |
+ tp->snd_cwnd, tcp_left_out(tp), |
6180 |
+ tp->snd_ssthresh, tp->prior_ssthresh, |
6181 |
+ tp->packets_out); |
6182 |
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c |
6183 |
+index 5d5390299277..d3d62be2376b 100644 |
6184 |
+--- a/net/ipv4/tcp_ipv4.c |
6185 |
++++ b/net/ipv4/tcp_ipv4.c |
6186 |
+@@ -271,10 +271,13 @@ EXPORT_SYMBOL(tcp_v4_connect); |
6187 |
+ */ |
6188 |
+ void tcp_v4_mtu_reduced(struct sock *sk) |
6189 |
+ { |
6190 |
+- struct dst_entry *dst; |
6191 |
+ struct inet_sock *inet = inet_sk(sk); |
6192 |
+- u32 mtu = tcp_sk(sk)->mtu_info; |
6193 |
++ struct dst_entry *dst; |
6194 |
++ u32 mtu; |
6195 |
+ |
6196 |
++ if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) |
6197 |
++ return; |
6198 |
++ mtu = tcp_sk(sk)->mtu_info; |
6199 |
+ dst = inet_csk_update_pmtu(sk, mtu); |
6200 |
+ if (!dst) |
6201 |
+ return; |
6202 |
+@@ -386,7 +389,8 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) |
6203 |
+ |
6204 |
+ switch (type) { |
6205 |
+ case ICMP_REDIRECT: |
6206 |
+- do_redirect(icmp_skb, sk); |
6207 |
++ if (!sock_owned_by_user(sk)) |
6208 |
++ do_redirect(icmp_skb, sk); |
6209 |
+ goto out; |
6210 |
+ case ICMP_SOURCE_QUENCH: |
6211 |
+ /* Just silently ignore these. */ |
6212 |
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c |
6213 |
+index af2f64eeb98f..a680177694ec 100644 |
6214 |
+--- a/net/ipv4/tcp_output.c |
6215 |
++++ b/net/ipv4/tcp_output.c |
6216 |
+@@ -1869,12 +1869,14 @@ static int tcp_mtu_probe(struct sock *sk) |
6217 |
+ len = 0; |
6218 |
+ tcp_for_write_queue_from_safe(skb, next, sk) { |
6219 |
+ copy = min_t(int, skb->len, probe_size - len); |
6220 |
+- if (nskb->ip_summed) |
6221 |
++ if (nskb->ip_summed) { |
6222 |
+ skb_copy_bits(skb, 0, skb_put(nskb, copy), copy); |
6223 |
+- else |
6224 |
+- nskb->csum = skb_copy_and_csum_bits(skb, 0, |
6225 |
+- skb_put(nskb, copy), |
6226 |
+- copy, nskb->csum); |
6227 |
++ } else { |
6228 |
++ __wsum csum = skb_copy_and_csum_bits(skb, 0, |
6229 |
++ skb_put(nskb, copy), |
6230 |
++ copy, 0); |
6231 |
++ nskb->csum = csum_block_add(nskb->csum, csum, len); |
6232 |
++ } |
6233 |
+ |
6234 |
+ if (skb->len <= copy) { |
6235 |
+ /* We've eaten all the data from this skb. |
6236 |
+@@ -2291,9 +2293,11 @@ u32 __tcp_select_window(struct sock *sk) |
6237 |
+ int full_space = min_t(int, tp->window_clamp, allowed_space); |
6238 |
+ int window; |
6239 |
+ |
6240 |
+- if (mss > full_space) |
6241 |
++ if (unlikely(mss > full_space)) { |
6242 |
+ mss = full_space; |
6243 |
+- |
6244 |
++ if (mss <= 0) |
6245 |
++ return 0; |
6246 |
++ } |
6247 |
+ if (free_space < (full_space >> 1)) { |
6248 |
+ icsk->icsk_ack.quick = 0; |
6249 |
+ |
6250 |
+@@ -2479,7 +2483,8 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) |
6251 |
+ * copying overhead: fragmentation, tunneling, mangling etc. |
6252 |
+ */ |
6253 |
+ if (atomic_read(&sk->sk_wmem_alloc) > |
6254 |
+- min(sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2), sk->sk_sndbuf)) |
6255 |
++ min_t(u32, sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2), |
6256 |
++ sk->sk_sndbuf)) |
6257 |
+ return -EAGAIN; |
6258 |
+ |
6259 |
+ if (skb_still_in_host_queue(sk, skb)) |
6260 |
+diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c |
6261 |
+index 9b21ae8b2e31..baec68553e90 100644 |
6262 |
+--- a/net/ipv4/tcp_timer.c |
6263 |
++++ b/net/ipv4/tcp_timer.c |
6264 |
+@@ -207,7 +207,8 @@ void tcp_delack_timer_handler(struct sock *sk) |
6265 |
+ |
6266 |
+ sk_mem_reclaim_partial(sk); |
6267 |
+ |
6268 |
+- if (sk->sk_state == TCP_CLOSE || !(icsk->icsk_ack.pending & ICSK_ACK_TIMER)) |
6269 |
++ if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) || |
6270 |
++ !(icsk->icsk_ack.pending & ICSK_ACK_TIMER)) |
6271 |
+ goto out; |
6272 |
+ |
6273 |
+ if (time_after(icsk->icsk_ack.timeout, jiffies)) { |
6274 |
+@@ -486,7 +487,8 @@ void tcp_write_timer_handler(struct sock *sk) |
6275 |
+ struct inet_connection_sock *icsk = inet_csk(sk); |
6276 |
+ int event; |
6277 |
+ |
6278 |
+- if (sk->sk_state == TCP_CLOSE || !icsk->icsk_pending) |
6279 |
++ if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) || |
6280 |
++ !icsk->icsk_pending) |
6281 |
+ goto out; |
6282 |
+ |
6283 |
+ if (time_after(icsk->icsk_timeout, jiffies)) { |
6284 |
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c |
6285 |
+index 953572c17b3d..4cc14452d5cc 100644 |
6286 |
+--- a/net/ipv6/addrconf.c |
6287 |
++++ b/net/ipv6/addrconf.c |
6288 |
+@@ -2695,7 +2695,7 @@ static void init_loopback(struct net_device *dev) |
6289 |
+ * lo device down, release this obsolete dst and |
6290 |
+ * reallocate a new router for ifa. |
6291 |
+ */ |
6292 |
+- if (sp_ifa->rt->dst.obsolete > 0) { |
6293 |
++ if (!atomic_read(&sp_ifa->rt->rt6i_ref)) { |
6294 |
+ ip6_rt_put(sp_ifa->rt); |
6295 |
+ sp_ifa->rt = NULL; |
6296 |
+ } else { |
6297 |
+diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c |
6298 |
+index 1a93a39b2aab..df3633e20458 100644 |
6299 |
+--- a/net/ipv6/ip6_gre.c |
6300 |
++++ b/net/ipv6/ip6_gre.c |
6301 |
+@@ -55,6 +55,7 @@ |
6302 |
+ #include <net/ip6_fib.h> |
6303 |
+ #include <net/ip6_route.h> |
6304 |
+ #include <net/ip6_tunnel.h> |
6305 |
++#include <net/gre.h> |
6306 |
+ |
6307 |
+ |
6308 |
+ static bool log_ecn_error = true; |
6309 |
+@@ -367,35 +368,37 @@ static void ip6gre_tunnel_uninit(struct net_device *dev) |
6310 |
+ |
6311 |
+ |
6312 |
+ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
6313 |
+- u8 type, u8 code, int offset, __be32 info) |
6314 |
++ u8 type, u8 code, int offset, __be32 info) |
6315 |
+ { |
6316 |
+- const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb->data; |
6317 |
+- __be16 *p = (__be16 *)(skb->data + offset); |
6318 |
+- int grehlen = offset + 4; |
6319 |
++ const struct gre_base_hdr *greh; |
6320 |
++ const struct ipv6hdr *ipv6h; |
6321 |
++ int grehlen = sizeof(*greh); |
6322 |
+ struct ip6_tnl *t; |
6323 |
++ int key_off = 0; |
6324 |
+ __be16 flags; |
6325 |
++ __be32 key; |
6326 |
+ |
6327 |
+- flags = p[0]; |
6328 |
+- if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { |
6329 |
+- if (flags&(GRE_VERSION|GRE_ROUTING)) |
6330 |
+- return; |
6331 |
+- if (flags&GRE_KEY) { |
6332 |
+- grehlen += 4; |
6333 |
+- if (flags&GRE_CSUM) |
6334 |
+- grehlen += 4; |
6335 |
+- } |
6336 |
++ if (!pskb_may_pull(skb, offset + grehlen)) |
6337 |
++ return; |
6338 |
++ greh = (const struct gre_base_hdr *)(skb->data + offset); |
6339 |
++ flags = greh->flags; |
6340 |
++ if (flags & (GRE_VERSION | GRE_ROUTING)) |
6341 |
++ return; |
6342 |
++ if (flags & GRE_CSUM) |
6343 |
++ grehlen += 4; |
6344 |
++ if (flags & GRE_KEY) { |
6345 |
++ key_off = grehlen + offset; |
6346 |
++ grehlen += 4; |
6347 |
+ } |
6348 |
+ |
6349 |
+- /* If only 8 bytes returned, keyed message will be dropped here */ |
6350 |
+- if (!pskb_may_pull(skb, grehlen)) |
6351 |
++ if (!pskb_may_pull(skb, offset + grehlen)) |
6352 |
+ return; |
6353 |
+ ipv6h = (const struct ipv6hdr *)skb->data; |
6354 |
+- p = (__be16 *)(skb->data + offset); |
6355 |
++ greh = (const struct gre_base_hdr *)(skb->data + offset); |
6356 |
++ key = key_off ? *(__be32 *)(skb->data + key_off) : 0; |
6357 |
+ |
6358 |
+ t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr, |
6359 |
+- flags & GRE_KEY ? |
6360 |
+- *(((__be32 *)p) + (grehlen / 4) - 1) : 0, |
6361 |
+- p[1]); |
6362 |
++ key, greh->protocol); |
6363 |
+ if (t == NULL) |
6364 |
+ return; |
6365 |
+ |
6366 |
+@@ -889,7 +892,6 @@ static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev) |
6367 |
+ encap_limit = t->parms.encap_limit; |
6368 |
+ |
6369 |
+ memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); |
6370 |
+- fl6.flowi6_proto = skb->protocol; |
6371 |
+ |
6372 |
+ err = ip6gre_xmit2(skb, dev, 0, &fl6, encap_limit, &mtu); |
6373 |
+ |
6374 |
+diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c |
6375 |
+index 6987d3cb4163..8afea07e53a2 100644 |
6376 |
+--- a/net/ipv6/ip6_tunnel.c |
6377 |
++++ b/net/ipv6/ip6_tunnel.c |
6378 |
+@@ -407,18 +407,19 @@ ip6_tnl_dev_uninit(struct net_device *dev) |
6379 |
+ |
6380 |
+ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) |
6381 |
+ { |
6382 |
+- const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw; |
6383 |
+- __u8 nexthdr = ipv6h->nexthdr; |
6384 |
+- __u16 off = sizeof(*ipv6h); |
6385 |
++ const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw; |
6386 |
++ unsigned int nhoff = raw - skb->data; |
6387 |
++ unsigned int off = nhoff + sizeof(*ipv6h); |
6388 |
++ u8 next, nexthdr = ipv6h->nexthdr; |
6389 |
+ |
6390 |
+ while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) { |
6391 |
+- __u16 optlen = 0; |
6392 |
+ struct ipv6_opt_hdr *hdr; |
6393 |
+- if (raw + off + sizeof(*hdr) > skb->data && |
6394 |
+- !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr))) |
6395 |
++ u16 optlen; |
6396 |
++ |
6397 |
++ if (!pskb_may_pull(skb, off + sizeof(*hdr))) |
6398 |
+ break; |
6399 |
+ |
6400 |
+- hdr = (struct ipv6_opt_hdr *) (raw + off); |
6401 |
++ hdr = (struct ipv6_opt_hdr *)(skb->data + off); |
6402 |
+ if (nexthdr == NEXTHDR_FRAGMENT) { |
6403 |
+ struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr; |
6404 |
+ if (frag_hdr->frag_off) |
6405 |
+@@ -429,20 +430,29 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) |
6406 |
+ } else { |
6407 |
+ optlen = ipv6_optlen(hdr); |
6408 |
+ } |
6409 |
++ /* cache hdr->nexthdr, since pskb_may_pull() might |
6410 |
++ * invalidate hdr |
6411 |
++ */ |
6412 |
++ next = hdr->nexthdr; |
6413 |
+ if (nexthdr == NEXTHDR_DEST) { |
6414 |
+- __u16 i = off + 2; |
6415 |
++ u16 i = 2; |
6416 |
++ |
6417 |
++ /* Remember : hdr is no longer valid at this point. */ |
6418 |
++ if (!pskb_may_pull(skb, off + optlen)) |
6419 |
++ break; |
6420 |
++ |
6421 |
+ while (1) { |
6422 |
+ struct ipv6_tlv_tnl_enc_lim *tel; |
6423 |
+ |
6424 |
+ /* No more room for encapsulation limit */ |
6425 |
+- if (i + sizeof (*tel) > off + optlen) |
6426 |
++ if (i + sizeof(*tel) > optlen) |
6427 |
+ break; |
6428 |
+ |
6429 |
+- tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i]; |
6430 |
++ tel = (struct ipv6_tlv_tnl_enc_lim *)(skb->data + off + i); |
6431 |
+ /* return index of option if found and valid */ |
6432 |
+ if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT && |
6433 |
+ tel->length == 1) |
6434 |
+- return i; |
6435 |
++ return i + off - nhoff; |
6436 |
+ /* else jump to next option */ |
6437 |
+ if (tel->type) |
6438 |
+ i += tel->length + 2; |
6439 |
+@@ -450,7 +460,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) |
6440 |
+ i++; |
6441 |
+ } |
6442 |
+ } |
6443 |
+- nexthdr = hdr->nexthdr; |
6444 |
++ nexthdr = next; |
6445 |
+ off += optlen; |
6446 |
+ } |
6447 |
+ return 0; |
6448 |
+diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c |
6449 |
+index 1d67b37592d1..591e2355cc9e 100644 |
6450 |
+--- a/net/ipv6/ip6_vti.c |
6451 |
++++ b/net/ipv6/ip6_vti.c |
6452 |
+@@ -645,6 +645,10 @@ vti6_parm_to_user(struct ip6_tnl_parm2 *u, const struct __ip6_tnl_parm *p) |
6453 |
+ u->link = p->link; |
6454 |
+ u->i_key = p->i_key; |
6455 |
+ u->o_key = p->o_key; |
6456 |
++ if (u->i_key) |
6457 |
++ u->i_flags |= GRE_KEY; |
6458 |
++ if (u->o_key) |
6459 |
++ u->o_flags |= GRE_KEY; |
6460 |
+ u->proto = p->proto; |
6461 |
+ |
6462 |
+ memcpy(u->name, p->name, sizeof(u->name)); |
6463 |
+diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c |
6464 |
+index 4ca7cdd15aad..2b93262d5d5f 100644 |
6465 |
+--- a/net/ipv6/ip6mr.c |
6466 |
++++ b/net/ipv6/ip6mr.c |
6467 |
+@@ -2276,8 +2276,8 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, |
6468 |
+ return 1; |
6469 |
+ } |
6470 |
+ |
6471 |
+-int ip6mr_get_route(struct net *net, |
6472 |
+- struct sk_buff *skb, struct rtmsg *rtm, int nowait) |
6473 |
++int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm, |
6474 |
++ int nowait, u32 portid) |
6475 |
+ { |
6476 |
+ int err; |
6477 |
+ struct mr6_table *mrt; |
6478 |
+@@ -2322,6 +2322,7 @@ int ip6mr_get_route(struct net *net, |
6479 |
+ return -ENOMEM; |
6480 |
+ } |
6481 |
+ |
6482 |
++ NETLINK_CB(skb2).portid = portid; |
6483 |
+ skb_reset_transport_header(skb2); |
6484 |
+ |
6485 |
+ skb_put(skb2, sizeof(struct ipv6hdr)); |
6486 |
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c |
6487 |
+index 2d9aca57e7c7..8d3103459b2d 100644 |
6488 |
+--- a/net/ipv6/route.c |
6489 |
++++ b/net/ipv6/route.c |
6490 |
+@@ -2612,7 +2612,9 @@ static int rt6_fill_node(struct net *net, |
6491 |
+ if (iif) { |
6492 |
+ #ifdef CONFIG_IPV6_MROUTE |
6493 |
+ if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) { |
6494 |
+- int err = ip6mr_get_route(net, skb, rtm, nowait); |
6495 |
++ int err = ip6mr_get_route(net, skb, rtm, nowait, |
6496 |
++ portid); |
6497 |
++ |
6498 |
+ if (err <= 0) { |
6499 |
+ if (!nowait) { |
6500 |
+ if (err == 0) |
6501 |
+diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c |
6502 |
+index 45eae1e609d6..eb36219f0a3c 100644 |
6503 |
+--- a/net/ipv6/sit.c |
6504 |
++++ b/net/ipv6/sit.c |
6505 |
+@@ -1388,6 +1388,7 @@ static int ipip6_tunnel_init(struct net_device *dev) |
6506 |
+ tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); |
6507 |
+ if (!tunnel->dst_cache) { |
6508 |
+ free_percpu(dev->tstats); |
6509 |
++ dev->tstats = NULL; |
6510 |
+ return -ENOMEM; |
6511 |
+ } |
6512 |
+ |
6513 |
+diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c |
6514 |
+index b8e14a5ae0b1..0ade453839c4 100644 |
6515 |
+--- a/net/ipv6/tcp_ipv6.c |
6516 |
++++ b/net/ipv6/tcp_ipv6.c |
6517 |
+@@ -389,10 +389,12 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
6518 |
+ np = inet6_sk(sk); |
6519 |
+ |
6520 |
+ if (type == NDISC_REDIRECT) { |
6521 |
+- struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie); |
6522 |
++ if (!sock_owned_by_user(sk)) { |
6523 |
++ struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie); |
6524 |
+ |
6525 |
+- if (dst) |
6526 |
+- dst->ops->redirect(dst, sk, skb); |
6527 |
++ if (dst) |
6528 |
++ dst->ops->redirect(dst, sk, skb); |
6529 |
++ } |
6530 |
+ goto out; |
6531 |
+ } |
6532 |
+ |
6533 |
+@@ -1049,6 +1051,16 @@ drop: |
6534 |
+ return 0; /* don't send reset */ |
6535 |
+ } |
6536 |
+ |
6537 |
++static void tcp_v6_restore_cb(struct sk_buff *skb) |
6538 |
++{ |
6539 |
++ /* We need to move header back to the beginning if xfrm6_policy_check() |
6540 |
++ * and tcp_v6_fill_cb() are going to be called again. |
6541 |
++ * ip6_datagram_recv_specific_ctl() also expects IP6CB to be there. |
6542 |
++ */ |
6543 |
++ memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6, |
6544 |
++ sizeof(struct inet6_skb_parm)); |
6545 |
++} |
6546 |
++ |
6547 |
+ static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, |
6548 |
+ struct request_sock *req, |
6549 |
+ struct dst_entry *dst) |
6550 |
+@@ -1180,8 +1192,10 @@ static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, |
6551 |
+ sk_gfp_atomic(sk, GFP_ATOMIC)); |
6552 |
+ consume_skb(ireq->pktopts); |
6553 |
+ ireq->pktopts = NULL; |
6554 |
+- if (newnp->pktoptions) |
6555 |
++ if (newnp->pktoptions) { |
6556 |
++ tcp_v6_restore_cb(newnp->pktoptions); |
6557 |
+ skb_set_owner_r(newnp->pktoptions, newsk); |
6558 |
++ } |
6559 |
+ } |
6560 |
+ newnp->opt = NULL; |
6561 |
+ newnp->mcast_oif = tcp_v6_iif(skb); |
6562 |
+@@ -1381,6 +1395,7 @@ ipv6_pktoptions: |
6563 |
+ np->flow_label = ip6_flowlabel(ipv6_hdr(opt_skb)); |
6564 |
+ if (ipv6_opt_accepted(sk, opt_skb, &TCP_SKB_CB(opt_skb)->header.h6)) { |
6565 |
+ skb_set_owner_r(opt_skb, sk); |
6566 |
++ tcp_v6_restore_cb(opt_skb); |
6567 |
+ opt_skb = xchg(&np->pktoptions, opt_skb); |
6568 |
+ } else { |
6569 |
+ __kfree_skb(opt_skb); |
6570 |
+@@ -1414,15 +1429,6 @@ static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr, |
6571 |
+ TCP_SKB_CB(skb)->sacked = 0; |
6572 |
+ } |
6573 |
+ |
6574 |
+-static void tcp_v6_restore_cb(struct sk_buff *skb) |
6575 |
+-{ |
6576 |
+- /* We need to move header back to the beginning if xfrm6_policy_check() |
6577 |
+- * and tcp_v6_fill_cb() are going to be called again. |
6578 |
+- */ |
6579 |
+- memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6, |
6580 |
+- sizeof(struct inet6_skb_parm)); |
6581 |
+-} |
6582 |
+- |
6583 |
+ static int tcp_v6_rcv(struct sk_buff *skb) |
6584 |
+ { |
6585 |
+ const struct tcphdr *th; |
6586 |
+diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h |
6587 |
+index 68aa9ffd4ae4..e9ec7d2cc357 100644 |
6588 |
+--- a/net/l2tp/l2tp_core.h |
6589 |
++++ b/net/l2tp/l2tp_core.h |
6590 |
+@@ -273,6 +273,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, |
6591 |
+ int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, |
6592 |
+ const struct l2tp_nl_cmd_ops *ops); |
6593 |
+ void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type); |
6594 |
++int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg); |
6595 |
+ |
6596 |
+ /* Session reference counts. Incremented when code obtains a reference |
6597 |
+ * to a session. |
6598 |
+diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c |
6599 |
+index e45d2b77bb42..c2cd3dd7fa67 100644 |
6600 |
+--- a/net/l2tp/l2tp_ip.c |
6601 |
++++ b/net/l2tp/l2tp_ip.c |
6602 |
+@@ -11,6 +11,7 @@ |
6603 |
+ |
6604 |
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
6605 |
+ |
6606 |
++#include <asm/ioctls.h> |
6607 |
+ #include <linux/icmp.h> |
6608 |
+ #include <linux/module.h> |
6609 |
+ #include <linux/skbuff.h> |
6610 |
+@@ -381,7 +382,7 @@ static int l2tp_ip_backlog_recv(struct sock *sk, struct sk_buff *skb) |
6611 |
+ drop: |
6612 |
+ IP_INC_STATS(sock_net(sk), IPSTATS_MIB_INDISCARDS); |
6613 |
+ kfree_skb(skb); |
6614 |
+- return -1; |
6615 |
++ return 0; |
6616 |
+ } |
6617 |
+ |
6618 |
+ /* Userspace will call sendmsg() on the tunnel socket to send L2TP |
6619 |
+@@ -554,6 +555,30 @@ out: |
6620 |
+ return err ? err : copied; |
6621 |
+ } |
6622 |
+ |
6623 |
++int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg) |
6624 |
++{ |
6625 |
++ struct sk_buff *skb; |
6626 |
++ int amount; |
6627 |
++ |
6628 |
++ switch (cmd) { |
6629 |
++ case SIOCOUTQ: |
6630 |
++ amount = sk_wmem_alloc_get(sk); |
6631 |
++ break; |
6632 |
++ case SIOCINQ: |
6633 |
++ spin_lock_bh(&sk->sk_receive_queue.lock); |
6634 |
++ skb = skb_peek(&sk->sk_receive_queue); |
6635 |
++ amount = skb ? skb->len : 0; |
6636 |
++ spin_unlock_bh(&sk->sk_receive_queue.lock); |
6637 |
++ break; |
6638 |
++ |
6639 |
++ default: |
6640 |
++ return -ENOIOCTLCMD; |
6641 |
++ } |
6642 |
++ |
6643 |
++ return put_user(amount, (int __user *)arg); |
6644 |
++} |
6645 |
++EXPORT_SYMBOL(l2tp_ioctl); |
6646 |
++ |
6647 |
+ static struct proto l2tp_ip_prot = { |
6648 |
+ .name = "L2TP/IP", |
6649 |
+ .owner = THIS_MODULE, |
6650 |
+@@ -562,7 +587,7 @@ static struct proto l2tp_ip_prot = { |
6651 |
+ .bind = l2tp_ip_bind, |
6652 |
+ .connect = l2tp_ip_connect, |
6653 |
+ .disconnect = l2tp_ip_disconnect, |
6654 |
+- .ioctl = udp_ioctl, |
6655 |
++ .ioctl = l2tp_ioctl, |
6656 |
+ .destroy = l2tp_ip_destroy_sock, |
6657 |
+ .setsockopt = ip_setsockopt, |
6658 |
+ .getsockopt = ip_getsockopt, |
6659 |
+diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c |
6660 |
+index b8e469b832df..f5d6fd834303 100644 |
6661 |
+--- a/net/l2tp/l2tp_ip6.c |
6662 |
++++ b/net/l2tp/l2tp_ip6.c |
6663 |
+@@ -715,7 +715,7 @@ static struct proto l2tp_ip6_prot = { |
6664 |
+ .bind = l2tp_ip6_bind, |
6665 |
+ .connect = l2tp_ip6_connect, |
6666 |
+ .disconnect = l2tp_ip6_disconnect, |
6667 |
+- .ioctl = udp_ioctl, |
6668 |
++ .ioctl = l2tp_ioctl, |
6669 |
+ .destroy = l2tp_ip6_destroy_sock, |
6670 |
+ .setsockopt = ipv6_setsockopt, |
6671 |
+ .getsockopt = ipv6_getsockopt, |
6672 |
+diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c |
6673 |
+index 42dc2e45c921..9c68d0bca046 100644 |
6674 |
+--- a/net/llc/llc_conn.c |
6675 |
++++ b/net/llc/llc_conn.c |
6676 |
+@@ -821,7 +821,10 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) |
6677 |
+ * another trick required to cope with how the PROCOM state |
6678 |
+ * machine works. -acme |
6679 |
+ */ |
6680 |
++ skb_orphan(skb); |
6681 |
++ sock_hold(sk); |
6682 |
+ skb->sk = sk; |
6683 |
++ skb->destructor = sock_efree; |
6684 |
+ } |
6685 |
+ if (!sock_owned_by_user(sk)) |
6686 |
+ llc_conn_rcv(sk, skb); |
6687 |
+diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c |
6688 |
+index 06033f6c845f..cdc1b620cbe1 100644 |
6689 |
+--- a/net/llc/llc_sap.c |
6690 |
++++ b/net/llc/llc_sap.c |
6691 |
+@@ -290,7 +290,10 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb, |
6692 |
+ |
6693 |
+ ev->type = LLC_SAP_EV_TYPE_PDU; |
6694 |
+ ev->reason = 0; |
6695 |
++ skb_orphan(skb); |
6696 |
++ sock_hold(sk); |
6697 |
+ skb->sk = sk; |
6698 |
++ skb->destructor = sock_efree; |
6699 |
+ llc_sap_state_process(sap, skb); |
6700 |
+ } |
6701 |
+ |
6702 |
+diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c |
6703 |
+index 4a95fe3cffbc..3b98c1b4a719 100644 |
6704 |
+--- a/net/mac80211/pm.c |
6705 |
++++ b/net/mac80211/pm.c |
6706 |
+@@ -116,6 +116,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) |
6707 |
+ break; |
6708 |
+ } |
6709 |
+ |
6710 |
++ flush_delayed_work(&sdata->dec_tailroom_needed_wk); |
6711 |
+ drv_remove_interface(local, sdata); |
6712 |
+ } |
6713 |
+ |
6714 |
+diff --git a/net/netlink/Kconfig b/net/netlink/Kconfig |
6715 |
+index 2c5e95e9bfbd..5d6e8c05b3d4 100644 |
6716 |
+--- a/net/netlink/Kconfig |
6717 |
++++ b/net/netlink/Kconfig |
6718 |
+@@ -2,15 +2,6 @@ |
6719 |
+ # Netlink Sockets |
6720 |
+ # |
6721 |
+ |
6722 |
+-config NETLINK_MMAP |
6723 |
+- bool "NETLINK: mmaped IO" |
6724 |
+- ---help--- |
6725 |
+- This option enables support for memory mapped netlink IO. This |
6726 |
+- reduces overhead by avoiding copying data between kernel- and |
6727 |
+- userspace. |
6728 |
+- |
6729 |
+- If unsure, say N. |
6730 |
+- |
6731 |
+ config NETLINK_DIAG |
6732 |
+ tristate "NETLINK: socket monitoring interface" |
6733 |
+ default n |
6734 |
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c |
6735 |
+index 15fc0938e1c4..4792e76b7d4a 100644 |
6736 |
+--- a/net/netlink/af_netlink.c |
6737 |
++++ b/net/netlink/af_netlink.c |
6738 |
+@@ -234,7 +234,7 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb, |
6739 |
+ |
6740 |
+ dev_hold(dev); |
6741 |
+ |
6742 |
+- if (netlink_skb_is_mmaped(skb) || is_vmalloc_addr(skb->head)) |
6743 |
++ if (is_vmalloc_addr(skb->head)) |
6744 |
+ nskb = netlink_to_full_skb(skb, GFP_ATOMIC); |
6745 |
+ else |
6746 |
+ nskb = skb_clone(skb, GFP_ATOMIC); |
6747 |
+@@ -308,599 +308,8 @@ static void netlink_rcv_wake(struct sock *sk) |
6748 |
+ wake_up_interruptible(&nlk->wait); |
6749 |
+ } |
6750 |
+ |
6751 |
+-#ifdef CONFIG_NETLINK_MMAP |
6752 |
+-static bool netlink_rx_is_mmaped(struct sock *sk) |
6753 |
+-{ |
6754 |
+- return nlk_sk(sk)->rx_ring.pg_vec != NULL; |
6755 |
+-} |
6756 |
+- |
6757 |
+-static bool netlink_tx_is_mmaped(struct sock *sk) |
6758 |
+-{ |
6759 |
+- return nlk_sk(sk)->tx_ring.pg_vec != NULL; |
6760 |
+-} |
6761 |
+- |
6762 |
+-static __pure struct page *pgvec_to_page(const void *addr) |
6763 |
+-{ |
6764 |
+- if (is_vmalloc_addr(addr)) |
6765 |
+- return vmalloc_to_page(addr); |
6766 |
+- else |
6767 |
+- return virt_to_page(addr); |
6768 |
+-} |
6769 |
+- |
6770 |
+-static void free_pg_vec(void **pg_vec, unsigned int order, unsigned int len) |
6771 |
+-{ |
6772 |
+- unsigned int i; |
6773 |
+- |
6774 |
+- for (i = 0; i < len; i++) { |
6775 |
+- if (pg_vec[i] != NULL) { |
6776 |
+- if (is_vmalloc_addr(pg_vec[i])) |
6777 |
+- vfree(pg_vec[i]); |
6778 |
+- else |
6779 |
+- free_pages((unsigned long)pg_vec[i], order); |
6780 |
+- } |
6781 |
+- } |
6782 |
+- kfree(pg_vec); |
6783 |
+-} |
6784 |
+- |
6785 |
+-static void *alloc_one_pg_vec_page(unsigned long order) |
6786 |
+-{ |
6787 |
+- void *buffer; |
6788 |
+- gfp_t gfp_flags = GFP_KERNEL | __GFP_COMP | __GFP_ZERO | |
6789 |
+- __GFP_NOWARN | __GFP_NORETRY; |
6790 |
+- |
6791 |
+- buffer = (void *)__get_free_pages(gfp_flags, order); |
6792 |
+- if (buffer != NULL) |
6793 |
+- return buffer; |
6794 |
+- |
6795 |
+- buffer = vzalloc((1 << order) * PAGE_SIZE); |
6796 |
+- if (buffer != NULL) |
6797 |
+- return buffer; |
6798 |
+- |
6799 |
+- gfp_flags &= ~__GFP_NORETRY; |
6800 |
+- return (void *)__get_free_pages(gfp_flags, order); |
6801 |
+-} |
6802 |
+- |
6803 |
+-static void **alloc_pg_vec(struct netlink_sock *nlk, |
6804 |
+- struct nl_mmap_req *req, unsigned int order) |
6805 |
+-{ |
6806 |
+- unsigned int block_nr = req->nm_block_nr; |
6807 |
+- unsigned int i; |
6808 |
+- void **pg_vec; |
6809 |
+- |
6810 |
+- pg_vec = kcalloc(block_nr, sizeof(void *), GFP_KERNEL); |
6811 |
+- if (pg_vec == NULL) |
6812 |
+- return NULL; |
6813 |
+- |
6814 |
+- for (i = 0; i < block_nr; i++) { |
6815 |
+- pg_vec[i] = alloc_one_pg_vec_page(order); |
6816 |
+- if (pg_vec[i] == NULL) |
6817 |
+- goto err1; |
6818 |
+- } |
6819 |
+- |
6820 |
+- return pg_vec; |
6821 |
+-err1: |
6822 |
+- free_pg_vec(pg_vec, order, block_nr); |
6823 |
+- return NULL; |
6824 |
+-} |
6825 |
+- |
6826 |
+- |
6827 |
+-static void |
6828 |
+-__netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, bool tx_ring, void **pg_vec, |
6829 |
+- unsigned int order) |
6830 |
+-{ |
6831 |
+- struct netlink_sock *nlk = nlk_sk(sk); |
6832 |
+- struct sk_buff_head *queue; |
6833 |
+- struct netlink_ring *ring; |
6834 |
+- |
6835 |
+- queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue; |
6836 |
+- ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring; |
6837 |
+- |
6838 |
+- spin_lock_bh(&queue->lock); |
6839 |
+- |
6840 |
+- ring->frame_max = req->nm_frame_nr - 1; |
6841 |
+- ring->head = 0; |
6842 |
+- ring->frame_size = req->nm_frame_size; |
6843 |
+- ring->pg_vec_pages = req->nm_block_size / PAGE_SIZE; |
6844 |
+- |
6845 |
+- swap(ring->pg_vec_len, req->nm_block_nr); |
6846 |
+- swap(ring->pg_vec_order, order); |
6847 |
+- swap(ring->pg_vec, pg_vec); |
6848 |
+- |
6849 |
+- __skb_queue_purge(queue); |
6850 |
+- spin_unlock_bh(&queue->lock); |
6851 |
+- |
6852 |
+- WARN_ON(atomic_read(&nlk->mapped)); |
6853 |
+- |
6854 |
+- if (pg_vec) |
6855 |
+- free_pg_vec(pg_vec, order, req->nm_block_nr); |
6856 |
+-} |
6857 |
+- |
6858 |
+-static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, |
6859 |
+- bool tx_ring) |
6860 |
+-{ |
6861 |
+- struct netlink_sock *nlk = nlk_sk(sk); |
6862 |
+- struct netlink_ring *ring; |
6863 |
+- void **pg_vec = NULL; |
6864 |
+- unsigned int order = 0; |
6865 |
+- |
6866 |
+- ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring; |
6867 |
+- |
6868 |
+- if (atomic_read(&nlk->mapped)) |
6869 |
+- return -EBUSY; |
6870 |
+- if (atomic_read(&ring->pending)) |
6871 |
+- return -EBUSY; |
6872 |
+- |
6873 |
+- if (req->nm_block_nr) { |
6874 |
+- if (ring->pg_vec != NULL) |
6875 |
+- return -EBUSY; |
6876 |
+- |
6877 |
+- if ((int)req->nm_block_size <= 0) |
6878 |
+- return -EINVAL; |
6879 |
+- if (!PAGE_ALIGNED(req->nm_block_size)) |
6880 |
+- return -EINVAL; |
6881 |
+- if (req->nm_frame_size < NL_MMAP_HDRLEN) |
6882 |
+- return -EINVAL; |
6883 |
+- if (!IS_ALIGNED(req->nm_frame_size, NL_MMAP_MSG_ALIGNMENT)) |
6884 |
+- return -EINVAL; |
6885 |
+- |
6886 |
+- ring->frames_per_block = req->nm_block_size / |
6887 |
+- req->nm_frame_size; |
6888 |
+- if (ring->frames_per_block == 0) |
6889 |
+- return -EINVAL; |
6890 |
+- if (ring->frames_per_block * req->nm_block_nr != |
6891 |
+- req->nm_frame_nr) |
6892 |
+- return -EINVAL; |
6893 |
+- |
6894 |
+- order = get_order(req->nm_block_size); |
6895 |
+- pg_vec = alloc_pg_vec(nlk, req, order); |
6896 |
+- if (pg_vec == NULL) |
6897 |
+- return -ENOMEM; |
6898 |
+- } else { |
6899 |
+- if (req->nm_frame_nr) |
6900 |
+- return -EINVAL; |
6901 |
+- } |
6902 |
+- |
6903 |
+- mutex_lock(&nlk->pg_vec_lock); |
6904 |
+- if (atomic_read(&nlk->mapped) == 0) { |
6905 |
+- __netlink_set_ring(sk, req, tx_ring, pg_vec, order); |
6906 |
+- mutex_unlock(&nlk->pg_vec_lock); |
6907 |
+- return 0; |
6908 |
+- } |
6909 |
+- |
6910 |
+- mutex_unlock(&nlk->pg_vec_lock); |
6911 |
+- |
6912 |
+- if (pg_vec) |
6913 |
+- free_pg_vec(pg_vec, order, req->nm_block_nr); |
6914 |
+- |
6915 |
+- return -EBUSY; |
6916 |
+-} |
6917 |
+- |
6918 |
+-static void netlink_mm_open(struct vm_area_struct *vma) |
6919 |
+-{ |
6920 |
+- struct file *file = vma->vm_file; |
6921 |
+- struct socket *sock = file->private_data; |
6922 |
+- struct sock *sk = sock->sk; |
6923 |
+- |
6924 |
+- if (sk) |
6925 |
+- atomic_inc(&nlk_sk(sk)->mapped); |
6926 |
+-} |
6927 |
+- |
6928 |
+-static void netlink_mm_close(struct vm_area_struct *vma) |
6929 |
+-{ |
6930 |
+- struct file *file = vma->vm_file; |
6931 |
+- struct socket *sock = file->private_data; |
6932 |
+- struct sock *sk = sock->sk; |
6933 |
+- |
6934 |
+- if (sk) |
6935 |
+- atomic_dec(&nlk_sk(sk)->mapped); |
6936 |
+-} |
6937 |
+- |
6938 |
+-static const struct vm_operations_struct netlink_mmap_ops = { |
6939 |
+- .open = netlink_mm_open, |
6940 |
+- .close = netlink_mm_close, |
6941 |
+-}; |
6942 |
+- |
6943 |
+-static int netlink_mmap(struct file *file, struct socket *sock, |
6944 |
+- struct vm_area_struct *vma) |
6945 |
+-{ |
6946 |
+- struct sock *sk = sock->sk; |
6947 |
+- struct netlink_sock *nlk = nlk_sk(sk); |
6948 |
+- struct netlink_ring *ring; |
6949 |
+- unsigned long start, size, expected; |
6950 |
+- unsigned int i; |
6951 |
+- int err = -EINVAL; |
6952 |
+- |
6953 |
+- if (vma->vm_pgoff) |
6954 |
+- return -EINVAL; |
6955 |
+- |
6956 |
+- mutex_lock(&nlk->pg_vec_lock); |
6957 |
+- |
6958 |
+- expected = 0; |
6959 |
+- for (ring = &nlk->rx_ring; ring <= &nlk->tx_ring; ring++) { |
6960 |
+- if (ring->pg_vec == NULL) |
6961 |
+- continue; |
6962 |
+- expected += ring->pg_vec_len * ring->pg_vec_pages * PAGE_SIZE; |
6963 |
+- } |
6964 |
+- |
6965 |
+- if (expected == 0) |
6966 |
+- goto out; |
6967 |
+- |
6968 |
+- size = vma->vm_end - vma->vm_start; |
6969 |
+- if (size != expected) |
6970 |
+- goto out; |
6971 |
+- |
6972 |
+- start = vma->vm_start; |
6973 |
+- for (ring = &nlk->rx_ring; ring <= &nlk->tx_ring; ring++) { |
6974 |
+- if (ring->pg_vec == NULL) |
6975 |
+- continue; |
6976 |
+- |
6977 |
+- for (i = 0; i < ring->pg_vec_len; i++) { |
6978 |
+- struct page *page; |
6979 |
+- void *kaddr = ring->pg_vec[i]; |
6980 |
+- unsigned int pg_num; |
6981 |
+- |
6982 |
+- for (pg_num = 0; pg_num < ring->pg_vec_pages; pg_num++) { |
6983 |
+- page = pgvec_to_page(kaddr); |
6984 |
+- err = vm_insert_page(vma, start, page); |
6985 |
+- if (err < 0) |
6986 |
+- goto out; |
6987 |
+- start += PAGE_SIZE; |
6988 |
+- kaddr += PAGE_SIZE; |
6989 |
+- } |
6990 |
+- } |
6991 |
+- } |
6992 |
+- |
6993 |
+- atomic_inc(&nlk->mapped); |
6994 |
+- vma->vm_ops = &netlink_mmap_ops; |
6995 |
+- err = 0; |
6996 |
+-out: |
6997 |
+- mutex_unlock(&nlk->pg_vec_lock); |
6998 |
+- return err; |
6999 |
+-} |
7000 |
+- |
7001 |
+-static void netlink_frame_flush_dcache(const struct nl_mmap_hdr *hdr, unsigned int nm_len) |
7002 |
+-{ |
7003 |
+-#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE == 1 |
7004 |
+- struct page *p_start, *p_end; |
7005 |
+- |
7006 |
+- /* First page is flushed through netlink_{get,set}_status */ |
7007 |
+- p_start = pgvec_to_page(hdr + PAGE_SIZE); |
7008 |
+- p_end = pgvec_to_page((void *)hdr + NL_MMAP_HDRLEN + nm_len - 1); |
7009 |
+- while (p_start <= p_end) { |
7010 |
+- flush_dcache_page(p_start); |
7011 |
+- p_start++; |
7012 |
+- } |
7013 |
+-#endif |
7014 |
+-} |
7015 |
+- |
7016 |
+-static enum nl_mmap_status netlink_get_status(const struct nl_mmap_hdr *hdr) |
7017 |
+-{ |
7018 |
+- smp_rmb(); |
7019 |
+- flush_dcache_page(pgvec_to_page(hdr)); |
7020 |
+- return hdr->nm_status; |
7021 |
+-} |
7022 |
+- |
7023 |
+-static void netlink_set_status(struct nl_mmap_hdr *hdr, |
7024 |
+- enum nl_mmap_status status) |
7025 |
+-{ |
7026 |
+- smp_mb(); |
7027 |
+- hdr->nm_status = status; |
7028 |
+- flush_dcache_page(pgvec_to_page(hdr)); |
7029 |
+-} |
7030 |
+- |
7031 |
+-static struct nl_mmap_hdr * |
7032 |
+-__netlink_lookup_frame(const struct netlink_ring *ring, unsigned int pos) |
7033 |
+-{ |
7034 |
+- unsigned int pg_vec_pos, frame_off; |
7035 |
+- |
7036 |
+- pg_vec_pos = pos / ring->frames_per_block; |
7037 |
+- frame_off = pos % ring->frames_per_block; |
7038 |
+- |
7039 |
+- return ring->pg_vec[pg_vec_pos] + (frame_off * ring->frame_size); |
7040 |
+-} |
7041 |
+- |
7042 |
+-static struct nl_mmap_hdr * |
7043 |
+-netlink_lookup_frame(const struct netlink_ring *ring, unsigned int pos, |
7044 |
+- enum nl_mmap_status status) |
7045 |
+-{ |
7046 |
+- struct nl_mmap_hdr *hdr; |
7047 |
+- |
7048 |
+- hdr = __netlink_lookup_frame(ring, pos); |
7049 |
+- if (netlink_get_status(hdr) != status) |
7050 |
+- return NULL; |
7051 |
+- |
7052 |
+- return hdr; |
7053 |
+-} |
7054 |
+- |
7055 |
+-static struct nl_mmap_hdr * |
7056 |
+-netlink_current_frame(const struct netlink_ring *ring, |
7057 |
+- enum nl_mmap_status status) |
7058 |
+-{ |
7059 |
+- return netlink_lookup_frame(ring, ring->head, status); |
7060 |
+-} |
7061 |
+- |
7062 |
+-static struct nl_mmap_hdr * |
7063 |
+-netlink_previous_frame(const struct netlink_ring *ring, |
7064 |
+- enum nl_mmap_status status) |
7065 |
+-{ |
7066 |
+- unsigned int prev; |
7067 |
+- |
7068 |
+- prev = ring->head ? ring->head - 1 : ring->frame_max; |
7069 |
+- return netlink_lookup_frame(ring, prev, status); |
7070 |
+-} |
7071 |
+- |
7072 |
+-static void netlink_increment_head(struct netlink_ring *ring) |
7073 |
+-{ |
7074 |
+- ring->head = ring->head != ring->frame_max ? ring->head + 1 : 0; |
7075 |
+-} |
7076 |
+- |
7077 |
+-static void netlink_forward_ring(struct netlink_ring *ring) |
7078 |
+-{ |
7079 |
+- unsigned int head = ring->head, pos = head; |
7080 |
+- const struct nl_mmap_hdr *hdr; |
7081 |
+- |
7082 |
+- do { |
7083 |
+- hdr = __netlink_lookup_frame(ring, pos); |
7084 |
+- if (hdr->nm_status == NL_MMAP_STATUS_UNUSED) |
7085 |
+- break; |
7086 |
+- if (hdr->nm_status != NL_MMAP_STATUS_SKIP) |
7087 |
+- break; |
7088 |
+- netlink_increment_head(ring); |
7089 |
+- } while (ring->head != head); |
7090 |
+-} |
7091 |
+- |
7092 |
+-static bool netlink_dump_space(struct netlink_sock *nlk) |
7093 |
+-{ |
7094 |
+- struct netlink_ring *ring = &nlk->rx_ring; |
7095 |
+- struct nl_mmap_hdr *hdr; |
7096 |
+- unsigned int n; |
7097 |
+- |
7098 |
+- hdr = netlink_current_frame(ring, NL_MMAP_STATUS_UNUSED); |
7099 |
+- if (hdr == NULL) |
7100 |
+- return false; |
7101 |
+- |
7102 |
+- n = ring->head + ring->frame_max / 2; |
7103 |
+- if (n > ring->frame_max) |
7104 |
+- n -= ring->frame_max; |
7105 |
+- |
7106 |
+- hdr = __netlink_lookup_frame(ring, n); |
7107 |
+- |
7108 |
+- return hdr->nm_status == NL_MMAP_STATUS_UNUSED; |
7109 |
+-} |
7110 |
+- |
7111 |
+-static unsigned int netlink_poll(struct file *file, struct socket *sock, |
7112 |
+- poll_table *wait) |
7113 |
+-{ |
7114 |
+- struct sock *sk = sock->sk; |
7115 |
+- struct netlink_sock *nlk = nlk_sk(sk); |
7116 |
+- unsigned int mask; |
7117 |
+- int err; |
7118 |
+- |
7119 |
+- if (nlk->rx_ring.pg_vec != NULL) { |
7120 |
+- /* Memory mapped sockets don't call recvmsg(), so flow control |
7121 |
+- * for dumps is performed here. A dump is allowed to continue |
7122 |
+- * if at least half the ring is unused. |
7123 |
+- */ |
7124 |
+- while (nlk->cb_running && netlink_dump_space(nlk)) { |
7125 |
+- err = netlink_dump(sk); |
7126 |
+- if (err < 0) { |
7127 |
+- sk->sk_err = -err; |
7128 |
+- sk->sk_error_report(sk); |
7129 |
+- break; |
7130 |
+- } |
7131 |
+- } |
7132 |
+- netlink_rcv_wake(sk); |
7133 |
+- } |
7134 |
+- |
7135 |
+- mask = datagram_poll(file, sock, wait); |
7136 |
+- |
7137 |
+- spin_lock_bh(&sk->sk_receive_queue.lock); |
7138 |
+- if (nlk->rx_ring.pg_vec) { |
7139 |
+- netlink_forward_ring(&nlk->rx_ring); |
7140 |
+- if (!netlink_previous_frame(&nlk->rx_ring, NL_MMAP_STATUS_UNUSED)) |
7141 |
+- mask |= POLLIN | POLLRDNORM; |
7142 |
+- } |
7143 |
+- spin_unlock_bh(&sk->sk_receive_queue.lock); |
7144 |
+- |
7145 |
+- spin_lock_bh(&sk->sk_write_queue.lock); |
7146 |
+- if (nlk->tx_ring.pg_vec) { |
7147 |
+- if (netlink_current_frame(&nlk->tx_ring, NL_MMAP_STATUS_UNUSED)) |
7148 |
+- mask |= POLLOUT | POLLWRNORM; |
7149 |
+- } |
7150 |
+- spin_unlock_bh(&sk->sk_write_queue.lock); |
7151 |
+- |
7152 |
+- return mask; |
7153 |
+-} |
7154 |
+- |
7155 |
+-static struct nl_mmap_hdr *netlink_mmap_hdr(struct sk_buff *skb) |
7156 |
+-{ |
7157 |
+- return (struct nl_mmap_hdr *)(skb->head - NL_MMAP_HDRLEN); |
7158 |
+-} |
7159 |
+- |
7160 |
+-static void netlink_ring_setup_skb(struct sk_buff *skb, struct sock *sk, |
7161 |
+- struct netlink_ring *ring, |
7162 |
+- struct nl_mmap_hdr *hdr) |
7163 |
+-{ |
7164 |
+- unsigned int size; |
7165 |
+- void *data; |
7166 |
+- |
7167 |
+- size = ring->frame_size - NL_MMAP_HDRLEN; |
7168 |
+- data = (void *)hdr + NL_MMAP_HDRLEN; |
7169 |
+- |
7170 |
+- skb->head = data; |
7171 |
+- skb->data = data; |
7172 |
+- skb_reset_tail_pointer(skb); |
7173 |
+- skb->end = skb->tail + size; |
7174 |
+- skb->len = 0; |
7175 |
+- |
7176 |
+- skb->destructor = netlink_skb_destructor; |
7177 |
+- NETLINK_CB(skb).flags |= NETLINK_SKB_MMAPED; |
7178 |
+- NETLINK_CB(skb).sk = sk; |
7179 |
+-} |
7180 |
+- |
7181 |
+-static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg, |
7182 |
+- u32 dst_portid, u32 dst_group, |
7183 |
+- struct sock_iocb *siocb) |
7184 |
+-{ |
7185 |
+- struct netlink_sock *nlk = nlk_sk(sk); |
7186 |
+- struct netlink_ring *ring; |
7187 |
+- struct nl_mmap_hdr *hdr; |
7188 |
+- struct sk_buff *skb; |
7189 |
+- unsigned int maxlen; |
7190 |
+- int err = 0, len = 0; |
7191 |
+- |
7192 |
+- mutex_lock(&nlk->pg_vec_lock); |
7193 |
+- |
7194 |
+- ring = &nlk->tx_ring; |
7195 |
+- maxlen = ring->frame_size - NL_MMAP_HDRLEN; |
7196 |
+- |
7197 |
+- do { |
7198 |
+- unsigned int nm_len; |
7199 |
+- |
7200 |
+- hdr = netlink_current_frame(ring, NL_MMAP_STATUS_VALID); |
7201 |
+- if (hdr == NULL) { |
7202 |
+- if (!(msg->msg_flags & MSG_DONTWAIT) && |
7203 |
+- atomic_read(&nlk->tx_ring.pending)) |
7204 |
+- schedule(); |
7205 |
+- continue; |
7206 |
+- } |
7207 |
+- |
7208 |
+- nm_len = ACCESS_ONCE(hdr->nm_len); |
7209 |
+- if (nm_len > maxlen) { |
7210 |
+- err = -EINVAL; |
7211 |
+- goto out; |
7212 |
+- } |
7213 |
+- |
7214 |
+- netlink_frame_flush_dcache(hdr, nm_len); |
7215 |
+- |
7216 |
+- skb = alloc_skb(nm_len, GFP_KERNEL); |
7217 |
+- if (skb == NULL) { |
7218 |
+- err = -ENOBUFS; |
7219 |
+- goto out; |
7220 |
+- } |
7221 |
+- __skb_put(skb, nm_len); |
7222 |
+- memcpy(skb->data, (void *)hdr + NL_MMAP_HDRLEN, nm_len); |
7223 |
+- netlink_set_status(hdr, NL_MMAP_STATUS_UNUSED); |
7224 |
+- |
7225 |
+- netlink_increment_head(ring); |
7226 |
+- |
7227 |
+- NETLINK_CB(skb).portid = nlk->portid; |
7228 |
+- NETLINK_CB(skb).dst_group = dst_group; |
7229 |
+- NETLINK_CB(skb).creds = siocb->scm->creds; |
7230 |
+- |
7231 |
+- err = security_netlink_send(sk, skb); |
7232 |
+- if (err) { |
7233 |
+- kfree_skb(skb); |
7234 |
+- goto out; |
7235 |
+- } |
7236 |
+- |
7237 |
+- if (unlikely(dst_group)) { |
7238 |
+- atomic_inc(&skb->users); |
7239 |
+- netlink_broadcast(sk, skb, dst_portid, dst_group, |
7240 |
+- GFP_KERNEL); |
7241 |
+- } |
7242 |
+- err = netlink_unicast(sk, skb, dst_portid, |
7243 |
+- msg->msg_flags & MSG_DONTWAIT); |
7244 |
+- if (err < 0) |
7245 |
+- goto out; |
7246 |
+- len += err; |
7247 |
+- |
7248 |
+- } while (hdr != NULL || |
7249 |
+- (!(msg->msg_flags & MSG_DONTWAIT) && |
7250 |
+- atomic_read(&nlk->tx_ring.pending))); |
7251 |
+- |
7252 |
+- if (len > 0) |
7253 |
+- err = len; |
7254 |
+-out: |
7255 |
+- mutex_unlock(&nlk->pg_vec_lock); |
7256 |
+- return err; |
7257 |
+-} |
7258 |
+- |
7259 |
+-static void netlink_queue_mmaped_skb(struct sock *sk, struct sk_buff *skb) |
7260 |
+-{ |
7261 |
+- struct nl_mmap_hdr *hdr; |
7262 |
+- |
7263 |
+- hdr = netlink_mmap_hdr(skb); |
7264 |
+- hdr->nm_len = skb->len; |
7265 |
+- hdr->nm_group = NETLINK_CB(skb).dst_group; |
7266 |
+- hdr->nm_pid = NETLINK_CB(skb).creds.pid; |
7267 |
+- hdr->nm_uid = from_kuid(sk_user_ns(sk), NETLINK_CB(skb).creds.uid); |
7268 |
+- hdr->nm_gid = from_kgid(sk_user_ns(sk), NETLINK_CB(skb).creds.gid); |
7269 |
+- netlink_frame_flush_dcache(hdr, hdr->nm_len); |
7270 |
+- netlink_set_status(hdr, NL_MMAP_STATUS_VALID); |
7271 |
+- |
7272 |
+- NETLINK_CB(skb).flags |= NETLINK_SKB_DELIVERED; |
7273 |
+- kfree_skb(skb); |
7274 |
+-} |
7275 |
+- |
7276 |
+-static void netlink_ring_set_copied(struct sock *sk, struct sk_buff *skb) |
7277 |
+-{ |
7278 |
+- struct netlink_sock *nlk = nlk_sk(sk); |
7279 |
+- struct netlink_ring *ring = &nlk->rx_ring; |
7280 |
+- struct nl_mmap_hdr *hdr; |
7281 |
+- |
7282 |
+- spin_lock_bh(&sk->sk_receive_queue.lock); |
7283 |
+- hdr = netlink_current_frame(ring, NL_MMAP_STATUS_UNUSED); |
7284 |
+- if (hdr == NULL) { |
7285 |
+- spin_unlock_bh(&sk->sk_receive_queue.lock); |
7286 |
+- kfree_skb(skb); |
7287 |
+- netlink_overrun(sk); |
7288 |
+- return; |
7289 |
+- } |
7290 |
+- netlink_increment_head(ring); |
7291 |
+- __skb_queue_tail(&sk->sk_receive_queue, skb); |
7292 |
+- spin_unlock_bh(&sk->sk_receive_queue.lock); |
7293 |
+- |
7294 |
+- hdr->nm_len = skb->len; |
7295 |
+- hdr->nm_group = NETLINK_CB(skb).dst_group; |
7296 |
+- hdr->nm_pid = NETLINK_CB(skb).creds.pid; |
7297 |
+- hdr->nm_uid = from_kuid(sk_user_ns(sk), NETLINK_CB(skb).creds.uid); |
7298 |
+- hdr->nm_gid = from_kgid(sk_user_ns(sk), NETLINK_CB(skb).creds.gid); |
7299 |
+- netlink_set_status(hdr, NL_MMAP_STATUS_COPY); |
7300 |
+-} |
7301 |
+- |
7302 |
+-#else /* CONFIG_NETLINK_MMAP */ |
7303 |
+-#define netlink_rx_is_mmaped(sk) false |
7304 |
+-#define netlink_tx_is_mmaped(sk) false |
7305 |
+-#define netlink_mmap sock_no_mmap |
7306 |
+-#define netlink_poll datagram_poll |
7307 |
+-#define netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group, siocb) 0 |
7308 |
+-#endif /* CONFIG_NETLINK_MMAP */ |
7309 |
+- |
7310 |
+ static void netlink_skb_destructor(struct sk_buff *skb) |
7311 |
+ { |
7312 |
+-#ifdef CONFIG_NETLINK_MMAP |
7313 |
+- struct nl_mmap_hdr *hdr; |
7314 |
+- struct netlink_ring *ring; |
7315 |
+- struct sock *sk; |
7316 |
+- |
7317 |
+- /* If a packet from the kernel to userspace was freed because of an |
7318 |
+- * error without being delivered to userspace, the kernel must reset |
7319 |
+- * the status. In the direction userspace to kernel, the status is |
7320 |
+- * always reset here after the packet was processed and freed. |
7321 |
+- */ |
7322 |
+- if (netlink_skb_is_mmaped(skb)) { |
7323 |
+- hdr = netlink_mmap_hdr(skb); |
7324 |
+- sk = NETLINK_CB(skb).sk; |
7325 |
+- |
7326 |
+- if (NETLINK_CB(skb).flags & NETLINK_SKB_TX) { |
7327 |
+- netlink_set_status(hdr, NL_MMAP_STATUS_UNUSED); |
7328 |
+- ring = &nlk_sk(sk)->tx_ring; |
7329 |
+- } else { |
7330 |
+- if (!(NETLINK_CB(skb).flags & NETLINK_SKB_DELIVERED)) { |
7331 |
+- hdr->nm_len = 0; |
7332 |
+- netlink_set_status(hdr, NL_MMAP_STATUS_VALID); |
7333 |
+- } |
7334 |
+- ring = &nlk_sk(sk)->rx_ring; |
7335 |
+- } |
7336 |
+- |
7337 |
+- WARN_ON(atomic_read(&ring->pending) == 0); |
7338 |
+- atomic_dec(&ring->pending); |
7339 |
+- sock_put(sk); |
7340 |
+- |
7341 |
+- skb->head = NULL; |
7342 |
+- } |
7343 |
+-#endif |
7344 |
+ if (is_vmalloc_addr(skb->head)) { |
7345 |
+ if (!skb->cloned || |
7346 |
+ !atomic_dec_return(&(skb_shinfo(skb)->dataref))) |
7347 |
+@@ -934,18 +343,6 @@ static void netlink_sock_destruct(struct sock *sk) |
7348 |
+ } |
7349 |
+ |
7350 |
+ skb_queue_purge(&sk->sk_receive_queue); |
7351 |
+-#ifdef CONFIG_NETLINK_MMAP |
7352 |
+- if (1) { |
7353 |
+- struct nl_mmap_req req; |
7354 |
+- |
7355 |
+- memset(&req, 0, sizeof(req)); |
7356 |
+- if (nlk->rx_ring.pg_vec) |
7357 |
+- __netlink_set_ring(sk, &req, false, NULL, 0); |
7358 |
+- memset(&req, 0, sizeof(req)); |
7359 |
+- if (nlk->tx_ring.pg_vec) |
7360 |
+- __netlink_set_ring(sk, &req, true, NULL, 0); |
7361 |
+- } |
7362 |
+-#endif /* CONFIG_NETLINK_MMAP */ |
7363 |
+ |
7364 |
+ if (!sock_flag(sk, SOCK_DEAD)) { |
7365 |
+ printk(KERN_ERR "Freeing alive netlink socket %p\n", sk); |
7366 |
+@@ -1153,9 +550,6 @@ static int __netlink_create(struct net *net, struct socket *sock, |
7367 |
+ mutex_init(nlk->cb_mutex); |
7368 |
+ } |
7369 |
+ init_waitqueue_head(&nlk->wait); |
7370 |
+-#ifdef CONFIG_NETLINK_MMAP |
7371 |
+- mutex_init(&nlk->pg_vec_lock); |
7372 |
+-#endif |
7373 |
+ |
7374 |
+ sk->sk_destruct = netlink_sock_destruct; |
7375 |
+ sk->sk_protocol = protocol; |
7376 |
+@@ -1653,9 +1047,8 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, |
7377 |
+ |
7378 |
+ nlk = nlk_sk(sk); |
7379 |
+ |
7380 |
+- if ((atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf || |
7381 |
+- test_bit(NETLINK_CONGESTED, &nlk->state)) && |
7382 |
+- !netlink_skb_is_mmaped(skb)) { |
7383 |
++ if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf || |
7384 |
++ test_bit(NETLINK_CONGESTED, &nlk->state)) { |
7385 |
+ DECLARE_WAITQUEUE(wait, current); |
7386 |
+ if (!*timeo) { |
7387 |
+ if (!ssk || netlink_is_kernel(ssk)) |
7388 |
+@@ -1693,14 +1086,7 @@ static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb) |
7389 |
+ |
7390 |
+ netlink_deliver_tap(skb); |
7391 |
+ |
7392 |
+-#ifdef CONFIG_NETLINK_MMAP |
7393 |
+- if (netlink_skb_is_mmaped(skb)) |
7394 |
+- netlink_queue_mmaped_skb(sk, skb); |
7395 |
+- else if (netlink_rx_is_mmaped(sk)) |
7396 |
+- netlink_ring_set_copied(sk, skb); |
7397 |
+- else |
7398 |
+-#endif /* CONFIG_NETLINK_MMAP */ |
7399 |
+- skb_queue_tail(&sk->sk_receive_queue, skb); |
7400 |
++ skb_queue_tail(&sk->sk_receive_queue, skb); |
7401 |
+ sk->sk_data_ready(sk); |
7402 |
+ return len; |
7403 |
+ } |
7404 |
+@@ -1724,9 +1110,6 @@ static struct sk_buff *netlink_trim(struct sk_buff *skb, gfp_t allocation) |
7405 |
+ int delta; |
7406 |
+ |
7407 |
+ WARN_ON(skb->sk != NULL); |
7408 |
+- if (netlink_skb_is_mmaped(skb)) |
7409 |
+- return skb; |
7410 |
+- |
7411 |
+ delta = skb->end - skb->tail; |
7412 |
+ if (is_vmalloc_addr(skb->head) || delta * 2 < skb->truesize) |
7413 |
+ return skb; |
7414 |
+@@ -1805,66 +1188,6 @@ EXPORT_SYMBOL(netlink_unicast); |
7415 |
+ struct sk_buff *netlink_alloc_skb(struct sock *ssk, unsigned int size, |
7416 |
+ u32 dst_portid, gfp_t gfp_mask) |
7417 |
+ { |
7418 |
+-#ifdef CONFIG_NETLINK_MMAP |
7419 |
+- struct sock *sk = NULL; |
7420 |
+- struct sk_buff *skb; |
7421 |
+- struct netlink_ring *ring; |
7422 |
+- struct nl_mmap_hdr *hdr; |
7423 |
+- unsigned int maxlen; |
7424 |
+- |
7425 |
+- sk = netlink_getsockbyportid(ssk, dst_portid); |
7426 |
+- if (IS_ERR(sk)) |
7427 |
+- goto out; |
7428 |
+- |
7429 |
+- ring = &nlk_sk(sk)->rx_ring; |
7430 |
+- /* fast-path without atomic ops for common case: non-mmaped receiver */ |
7431 |
+- if (ring->pg_vec == NULL) |
7432 |
+- goto out_put; |
7433 |
+- |
7434 |
+- if (ring->frame_size - NL_MMAP_HDRLEN < size) |
7435 |
+- goto out_put; |
7436 |
+- |
7437 |
+- skb = alloc_skb_head(gfp_mask); |
7438 |
+- if (skb == NULL) |
7439 |
+- goto err1; |
7440 |
+- |
7441 |
+- spin_lock_bh(&sk->sk_receive_queue.lock); |
7442 |
+- /* check again under lock */ |
7443 |
+- if (ring->pg_vec == NULL) |
7444 |
+- goto out_free; |
7445 |
+- |
7446 |
+- /* check again under lock */ |
7447 |
+- maxlen = ring->frame_size - NL_MMAP_HDRLEN; |
7448 |
+- if (maxlen < size) |
7449 |
+- goto out_free; |
7450 |
+- |
7451 |
+- netlink_forward_ring(ring); |
7452 |
+- hdr = netlink_current_frame(ring, NL_MMAP_STATUS_UNUSED); |
7453 |
+- if (hdr == NULL) |
7454 |
+- goto err2; |
7455 |
+- netlink_ring_setup_skb(skb, sk, ring, hdr); |
7456 |
+- netlink_set_status(hdr, NL_MMAP_STATUS_RESERVED); |
7457 |
+- atomic_inc(&ring->pending); |
7458 |
+- netlink_increment_head(ring); |
7459 |
+- |
7460 |
+- spin_unlock_bh(&sk->sk_receive_queue.lock); |
7461 |
+- return skb; |
7462 |
+- |
7463 |
+-err2: |
7464 |
+- kfree_skb(skb); |
7465 |
+- spin_unlock_bh(&sk->sk_receive_queue.lock); |
7466 |
+- netlink_overrun(sk); |
7467 |
+-err1: |
7468 |
+- sock_put(sk); |
7469 |
+- return NULL; |
7470 |
+- |
7471 |
+-out_free: |
7472 |
+- kfree_skb(skb); |
7473 |
+- spin_unlock_bh(&sk->sk_receive_queue.lock); |
7474 |
+-out_put: |
7475 |
+- sock_put(sk); |
7476 |
+-out: |
7477 |
+-#endif |
7478 |
+ return alloc_skb(size, gfp_mask); |
7479 |
+ } |
7480 |
+ EXPORT_SYMBOL_GPL(netlink_alloc_skb); |
7481 |
+@@ -2126,8 +1449,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, |
7482 |
+ if (level != SOL_NETLINK) |
7483 |
+ return -ENOPROTOOPT; |
7484 |
+ |
7485 |
+- if (optname != NETLINK_RX_RING && optname != NETLINK_TX_RING && |
7486 |
+- optlen >= sizeof(int) && |
7487 |
++ if (optlen >= sizeof(int) && |
7488 |
+ get_user(val, (unsigned int __user *)optval)) |
7489 |
+ return -EFAULT; |
7490 |
+ |
7491 |
+@@ -2180,25 +1502,6 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, |
7492 |
+ } |
7493 |
+ err = 0; |
7494 |
+ break; |
7495 |
+-#ifdef CONFIG_NETLINK_MMAP |
7496 |
+- case NETLINK_RX_RING: |
7497 |
+- case NETLINK_TX_RING: { |
7498 |
+- struct nl_mmap_req req; |
7499 |
+- |
7500 |
+- /* Rings might consume more memory than queue limits, require |
7501 |
+- * CAP_NET_ADMIN. |
7502 |
+- */ |
7503 |
+- if (!capable(CAP_NET_ADMIN)) |
7504 |
+- return -EPERM; |
7505 |
+- if (optlen < sizeof(req)) |
7506 |
+- return -EINVAL; |
7507 |
+- if (copy_from_user(&req, optval, sizeof(req))) |
7508 |
+- return -EFAULT; |
7509 |
+- err = netlink_set_ring(sk, &req, |
7510 |
+- optname == NETLINK_TX_RING); |
7511 |
+- break; |
7512 |
+- } |
7513 |
+-#endif /* CONFIG_NETLINK_MMAP */ |
7514 |
+ default: |
7515 |
+ err = -ENOPROTOOPT; |
7516 |
+ } |
7517 |
+@@ -2311,13 +1614,6 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, |
7518 |
+ goto out; |
7519 |
+ } |
7520 |
+ |
7521 |
+- if (netlink_tx_is_mmaped(sk) && |
7522 |
+- msg->msg_iov->iov_base == NULL) { |
7523 |
+- err = netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group, |
7524 |
+- siocb); |
7525 |
+- goto out; |
7526 |
+- } |
7527 |
+- |
7528 |
+ err = -EMSGSIZE; |
7529 |
+ if (len > sk->sk_sndbuf - 32) |
7530 |
+ goto out; |
7531 |
+@@ -2398,7 +1694,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, |
7532 |
+ /* Record the max length of recvmsg() calls for future allocations */ |
7533 |
+ nlk->max_recvmsg_len = max(nlk->max_recvmsg_len, len); |
7534 |
+ nlk->max_recvmsg_len = min_t(size_t, nlk->max_recvmsg_len, |
7535 |
+- 16384); |
7536 |
++ SKB_WITH_OVERHEAD(32768)); |
7537 |
+ |
7538 |
+ copied = data_skb->len; |
7539 |
+ if (len < copied) { |
7540 |
+@@ -2643,8 +1939,7 @@ static int netlink_dump(struct sock *sk) |
7541 |
+ cb = &nlk->cb; |
7542 |
+ alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE); |
7543 |
+ |
7544 |
+- if (!netlink_rx_is_mmaped(sk) && |
7545 |
+- atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) |
7546 |
++ if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) |
7547 |
+ goto errout_skb; |
7548 |
+ |
7549 |
+ /* NLMSG_GOODSIZE is small to avoid high order allocations being |
7550 |
+@@ -2656,9 +1951,8 @@ static int netlink_dump(struct sock *sk) |
7551 |
+ skb = netlink_alloc_skb(sk, |
7552 |
+ nlk->max_recvmsg_len, |
7553 |
+ nlk->portid, |
7554 |
+- GFP_KERNEL | |
7555 |
+- __GFP_NOWARN | |
7556 |
+- __GFP_NORETRY); |
7557 |
++ (GFP_KERNEL & ~__GFP_WAIT) | |
7558 |
++ __GFP_NOWARN | __GFP_NORETRY); |
7559 |
+ /* available room should be exact amount to avoid MSG_TRUNC */ |
7560 |
+ if (skb) |
7561 |
+ skb_reserve(skb, skb_tailroom(skb) - |
7562 |
+@@ -2666,7 +1960,7 @@ static int netlink_dump(struct sock *sk) |
7563 |
+ } |
7564 |
+ if (!skb) |
7565 |
+ skb = netlink_alloc_skb(sk, alloc_size, nlk->portid, |
7566 |
+- GFP_KERNEL); |
7567 |
++ (GFP_KERNEL & ~__GFP_WAIT)); |
7568 |
+ if (!skb) |
7569 |
+ goto errout_skb; |
7570 |
+ netlink_skb_set_owner_r(skb, sk); |
7571 |
+@@ -2722,16 +2016,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, |
7572 |
+ struct netlink_sock *nlk; |
7573 |
+ int ret; |
7574 |
+ |
7575 |
+- /* Memory mapped dump requests need to be copied to avoid looping |
7576 |
+- * on the pending state in netlink_mmap_sendmsg() while the CB hold |
7577 |
+- * a reference to the skb. |
7578 |
+- */ |
7579 |
+- if (netlink_skb_is_mmaped(skb)) { |
7580 |
+- skb = skb_copy(skb, GFP_KERNEL); |
7581 |
+- if (skb == NULL) |
7582 |
+- return -ENOBUFS; |
7583 |
+- } else |
7584 |
+- atomic_inc(&skb->users); |
7585 |
++ atomic_inc(&skb->users); |
7586 |
+ |
7587 |
+ sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).portid); |
7588 |
+ if (sk == NULL) { |
7589 |
+@@ -3072,7 +2357,7 @@ static const struct proto_ops netlink_ops = { |
7590 |
+ .socketpair = sock_no_socketpair, |
7591 |
+ .accept = sock_no_accept, |
7592 |
+ .getname = netlink_getname, |
7593 |
+- .poll = netlink_poll, |
7594 |
++ .poll = datagram_poll, |
7595 |
+ .ioctl = sock_no_ioctl, |
7596 |
+ .listen = sock_no_listen, |
7597 |
+ .shutdown = sock_no_shutdown, |
7598 |
+@@ -3080,7 +2365,7 @@ static const struct proto_ops netlink_ops = { |
7599 |
+ .getsockopt = netlink_getsockopt, |
7600 |
+ .sendmsg = netlink_sendmsg, |
7601 |
+ .recvmsg = netlink_recvmsg, |
7602 |
+- .mmap = netlink_mmap, |
7603 |
++ .mmap = sock_no_mmap, |
7604 |
+ .sendpage = sock_no_sendpage, |
7605 |
+ }; |
7606 |
+ |
7607 |
+diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h |
7608 |
+index 3951874e715d..c6bd3dd35cb3 100644 |
7609 |
+--- a/net/netlink/af_netlink.h |
7610 |
++++ b/net/netlink/af_netlink.h |
7611 |
+@@ -42,12 +42,6 @@ struct netlink_sock { |
7612 |
+ int (*netlink_bind)(int group); |
7613 |
+ void (*netlink_unbind)(int group); |
7614 |
+ struct module *module; |
7615 |
+-#ifdef CONFIG_NETLINK_MMAP |
7616 |
+- struct mutex pg_vec_lock; |
7617 |
+- struct netlink_ring rx_ring; |
7618 |
+- struct netlink_ring tx_ring; |
7619 |
+- atomic_t mapped; |
7620 |
+-#endif /* CONFIG_NETLINK_MMAP */ |
7621 |
+ |
7622 |
+ struct rhash_head node; |
7623 |
+ }; |
7624 |
+@@ -57,15 +51,6 @@ static inline struct netlink_sock *nlk_sk(struct sock *sk) |
7625 |
+ return container_of(sk, struct netlink_sock, sk); |
7626 |
+ } |
7627 |
+ |
7628 |
+-static inline bool netlink_skb_is_mmaped(const struct sk_buff *skb) |
7629 |
+-{ |
7630 |
+-#ifdef CONFIG_NETLINK_MMAP |
7631 |
+- return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED; |
7632 |
+-#else |
7633 |
+- return false; |
7634 |
+-#endif /* CONFIG_NETLINK_MMAP */ |
7635 |
+-} |
7636 |
+- |
7637 |
+ struct netlink_table { |
7638 |
+ struct rhashtable hash; |
7639 |
+ struct hlist_head mc_list; |
7640 |
+diff --git a/net/netlink/diag.c b/net/netlink/diag.c |
7641 |
+index de8c74a3c061..dd5f2ffd13e6 100644 |
7642 |
+--- a/net/netlink/diag.c |
7643 |
++++ b/net/netlink/diag.c |
7644 |
+@@ -8,41 +8,6 @@ |
7645 |
+ |
7646 |
+ #include "af_netlink.h" |
7647 |
+ |
7648 |
+-#ifdef CONFIG_NETLINK_MMAP |
7649 |
+-static int sk_diag_put_ring(struct netlink_ring *ring, int nl_type, |
7650 |
+- struct sk_buff *nlskb) |
7651 |
+-{ |
7652 |
+- struct netlink_diag_ring ndr; |
7653 |
+- |
7654 |
+- ndr.ndr_block_size = ring->pg_vec_pages << PAGE_SHIFT; |
7655 |
+- ndr.ndr_block_nr = ring->pg_vec_len; |
7656 |
+- ndr.ndr_frame_size = ring->frame_size; |
7657 |
+- ndr.ndr_frame_nr = ring->frame_max + 1; |
7658 |
+- |
7659 |
+- return nla_put(nlskb, nl_type, sizeof(ndr), &ndr); |
7660 |
+-} |
7661 |
+- |
7662 |
+-static int sk_diag_put_rings_cfg(struct sock *sk, struct sk_buff *nlskb) |
7663 |
+-{ |
7664 |
+- struct netlink_sock *nlk = nlk_sk(sk); |
7665 |
+- int ret; |
7666 |
+- |
7667 |
+- mutex_lock(&nlk->pg_vec_lock); |
7668 |
+- ret = sk_diag_put_ring(&nlk->rx_ring, NETLINK_DIAG_RX_RING, nlskb); |
7669 |
+- if (!ret) |
7670 |
+- ret = sk_diag_put_ring(&nlk->tx_ring, NETLINK_DIAG_TX_RING, |
7671 |
+- nlskb); |
7672 |
+- mutex_unlock(&nlk->pg_vec_lock); |
7673 |
+- |
7674 |
+- return ret; |
7675 |
+-} |
7676 |
+-#else |
7677 |
+-static int sk_diag_put_rings_cfg(struct sock *sk, struct sk_buff *nlskb) |
7678 |
+-{ |
7679 |
+- return 0; |
7680 |
+-} |
7681 |
+-#endif |
7682 |
+- |
7683 |
+ static int sk_diag_dump_groups(struct sock *sk, struct sk_buff *nlskb) |
7684 |
+ { |
7685 |
+ struct netlink_sock *nlk = nlk_sk(sk); |
7686 |
+@@ -87,10 +52,6 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, |
7687 |
+ sock_diag_put_meminfo(sk, skb, NETLINK_DIAG_MEMINFO)) |
7688 |
+ goto out_nlmsg_trim; |
7689 |
+ |
7690 |
+- if ((req->ndiag_show & NDIAG_SHOW_RING_CFG) && |
7691 |
+- sk_diag_put_rings_cfg(sk, skb)) |
7692 |
+- goto out_nlmsg_trim; |
7693 |
+- |
7694 |
+ return nlmsg_end(skb, nlh); |
7695 |
+ |
7696 |
+ out_nlmsg_trim: |
7697 |
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c |
7698 |
+index abffc1519e4d..86b3e2f70a27 100644 |
7699 |
+--- a/net/packet/af_packet.c |
7700 |
++++ b/net/packet/af_packet.c |
7701 |
+@@ -240,7 +240,7 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po); |
7702 |
+ static int packet_direct_xmit(struct sk_buff *skb) |
7703 |
+ { |
7704 |
+ struct net_device *dev = skb->dev; |
7705 |
+- netdev_features_t features; |
7706 |
++ struct sk_buff *orig_skb = skb; |
7707 |
+ struct netdev_queue *txq; |
7708 |
+ int ret = NETDEV_TX_BUSY; |
7709 |
+ |
7710 |
+@@ -248,9 +248,8 @@ static int packet_direct_xmit(struct sk_buff *skb) |
7711 |
+ !netif_carrier_ok(dev))) |
7712 |
+ goto drop; |
7713 |
+ |
7714 |
+- features = netif_skb_features(skb); |
7715 |
+- if (skb_needs_linearize(skb, features) && |
7716 |
+- __skb_linearize(skb)) |
7717 |
++ skb = validate_xmit_skb_list(skb, dev); |
7718 |
++ if (skb != orig_skb) |
7719 |
+ goto drop; |
7720 |
+ |
7721 |
+ txq = skb_get_tx_queue(dev, skb); |
7722 |
+@@ -270,7 +269,7 @@ static int packet_direct_xmit(struct sk_buff *skb) |
7723 |
+ return ret; |
7724 |
+ drop: |
7725 |
+ atomic_long_inc(&dev->tx_dropped); |
7726 |
+- kfree_skb(skb); |
7727 |
++ kfree_skb_list(skb); |
7728 |
+ return NET_XMIT_DROP; |
7729 |
+ } |
7730 |
+ |
7731 |
+@@ -2739,7 +2738,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, |
7732 |
+ int addr_len) |
7733 |
+ { |
7734 |
+ struct sock *sk = sock->sk; |
7735 |
+- char name[15]; |
7736 |
++ char name[sizeof(uaddr->sa_data) + 1]; |
7737 |
+ |
7738 |
+ /* |
7739 |
+ * Check legality |
7740 |
+@@ -2747,7 +2746,11 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, |
7741 |
+ |
7742 |
+ if (addr_len != sizeof(struct sockaddr)) |
7743 |
+ return -EINVAL; |
7744 |
+- strlcpy(name, uaddr->sa_data, sizeof(name)); |
7745 |
++ /* uaddr->sa_data comes from the userspace, it's not guaranteed to be |
7746 |
++ * zero-terminated. |
7747 |
++ */ |
7748 |
++ memcpy(name, uaddr->sa_data, sizeof(uaddr->sa_data)); |
7749 |
++ name[sizeof(uaddr->sa_data)] = 0; |
7750 |
+ |
7751 |
+ return packet_do_bind(sk, name, 0, pkt_sk(sk)->num); |
7752 |
+ } |
7753 |
+@@ -3552,6 +3555,7 @@ static int packet_notifier(struct notifier_block *this, |
7754 |
+ } |
7755 |
+ if (msg == NETDEV_UNREGISTER) { |
7756 |
+ packet_cached_dev_reset(po); |
7757 |
++ fanout_release(sk); |
7758 |
+ po->ifindex = -1; |
7759 |
+ if (po->prot_hook.dev) |
7760 |
+ dev_put(po->prot_hook.dev); |
7761 |
+@@ -3804,8 +3808,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, |
7762 |
+ if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) |
7763 |
+ goto out; |
7764 |
+ if (po->tp_version >= TPACKET_V3 && |
7765 |
+- (int)(req->tp_block_size - |
7766 |
+- BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0) |
7767 |
++ req->tp_block_size <= |
7768 |
++ BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv)) |
7769 |
+ goto out; |
7770 |
+ if (unlikely(req->tp_frame_size < po->tp_hdrlen + |
7771 |
+ po->tp_reserve)) |
7772 |
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c |
7773 |
+index e6bb98e583fb..690a973b72b5 100644 |
7774 |
+--- a/net/sctp/sm_statefuns.c |
7775 |
++++ b/net/sctp/sm_statefuns.c |
7776 |
+@@ -3426,6 +3426,12 @@ sctp_disposition_t sctp_sf_ootb(struct net *net, |
7777 |
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
7778 |
+ commands); |
7779 |
+ |
7780 |
++ /* Report violation if chunk len overflows */ |
7781 |
++ ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); |
7782 |
++ if (ch_end > skb_tail_pointer(skb)) |
7783 |
++ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
7784 |
++ commands); |
7785 |
++ |
7786 |
+ /* Now that we know we at least have a chunk header, |
7787 |
+ * do things that are type appropriate. |
7788 |
+ */ |
7789 |
+@@ -3457,12 +3463,6 @@ sctp_disposition_t sctp_sf_ootb(struct net *net, |
7790 |
+ } |
7791 |
+ } |
7792 |
+ |
7793 |
+- /* Report violation if chunk len overflows */ |
7794 |
+- ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); |
7795 |
+- if (ch_end > skb_tail_pointer(skb)) |
7796 |
+- return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
7797 |
+- commands); |
7798 |
+- |
7799 |
+ ch = (sctp_chunkhdr_t *) ch_end; |
7800 |
+ } while (ch_end < skb_tail_pointer(skb)); |
7801 |
+ |
7802 |
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c |
7803 |
+index 72da7d58ccca..1e557ee4cd65 100644 |
7804 |
+--- a/net/sctp/socket.c |
7805 |
++++ b/net/sctp/socket.c |
7806 |
+@@ -4385,7 +4385,7 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len, |
7807 |
+ static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, |
7808 |
+ int __user *optlen) |
7809 |
+ { |
7810 |
+- if (len <= 0) |
7811 |
++ if (len == 0) |
7812 |
+ return -EINVAL; |
7813 |
+ if (len > sizeof(struct sctp_event_subscribe)) |
7814 |
+ len = sizeof(struct sctp_event_subscribe); |
7815 |
+@@ -5981,6 +5981,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, |
7816 |
+ if (get_user(len, optlen)) |
7817 |
+ return -EFAULT; |
7818 |
+ |
7819 |
++ if (len < 0) |
7820 |
++ return -EINVAL; |
7821 |
++ |
7822 |
+ lock_sock(sk); |
7823 |
+ |
7824 |
+ switch (optname) { |
7825 |
+@@ -6962,7 +6965,8 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, |
7826 |
+ */ |
7827 |
+ release_sock(sk); |
7828 |
+ current_timeo = schedule_timeout(current_timeo); |
7829 |
+- BUG_ON(sk != asoc->base.sk); |
7830 |
++ if (sk != asoc->base.sk) |
7831 |
++ goto do_error; |
7832 |
+ lock_sock(sk); |
7833 |
+ |
7834 |
+ *timeo_p = current_timeo; |
7835 |
+diff --git a/net/socket.c b/net/socket.c |
7836 |
+index 7f61789c78ff..e72371710fe3 100644 |
7837 |
+--- a/net/socket.c |
7838 |
++++ b/net/socket.c |
7839 |
+@@ -2355,8 +2355,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, |
7840 |
+ return err; |
7841 |
+ |
7842 |
+ err = sock_error(sock->sk); |
7843 |
+- if (err) |
7844 |
++ if (err) { |
7845 |
++ datagrams = err; |
7846 |
+ goto out_put; |
7847 |
++ } |
7848 |
+ |
7849 |
+ entry = mmsg; |
7850 |
+ compat_entry = (struct compat_mmsghdr __user *)mmsg; |
7851 |
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c |
7852 |
+index 287087b10a7e..7950b4c26651 100644 |
7853 |
+--- a/net/unix/af_unix.c |
7854 |
++++ b/net/unix/af_unix.c |
7855 |
+@@ -940,20 +940,32 @@ fail: |
7856 |
+ return NULL; |
7857 |
+ } |
7858 |
+ |
7859 |
+-static int unix_mknod(struct dentry *dentry, struct path *path, umode_t mode, |
7860 |
+- struct path *res) |
7861 |
++static int unix_mknod(const char *sun_path, umode_t mode, struct path *res) |
7862 |
+ { |
7863 |
+- int err; |
7864 |
++ struct dentry *dentry; |
7865 |
++ struct path path; |
7866 |
++ int err = 0; |
7867 |
++ /* |
7868 |
++ * Get the parent directory, calculate the hash for last |
7869 |
++ * component. |
7870 |
++ */ |
7871 |
++ dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); |
7872 |
++ err = PTR_ERR(dentry); |
7873 |
++ if (IS_ERR(dentry)) |
7874 |
++ return err; |
7875 |
+ |
7876 |
+- err = security_path_mknod(path, dentry, mode, 0); |
7877 |
++ /* |
7878 |
++ * All right, let's create it. |
7879 |
++ */ |
7880 |
++ err = security_path_mknod(&path, dentry, mode, 0); |
7881 |
+ if (!err) { |
7882 |
+- err = vfs_mknod(d_inode(path->dentry), dentry, mode, 0); |
7883 |
++ err = vfs_mknod(d_inode(path.dentry), dentry, mode, 0); |
7884 |
+ if (!err) { |
7885 |
+- res->mnt = mntget(path->mnt); |
7886 |
++ res->mnt = mntget(path.mnt); |
7887 |
+ res->dentry = dget(dentry); |
7888 |
+ } |
7889 |
+ } |
7890 |
+- |
7891 |
++ done_path_create(&path, dentry); |
7892 |
+ return err; |
7893 |
+ } |
7894 |
+ |
7895 |
+@@ -964,12 +976,10 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) |
7896 |
+ struct unix_sock *u = unix_sk(sk); |
7897 |
+ struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr; |
7898 |
+ char *sun_path = sunaddr->sun_path; |
7899 |
+- int err, name_err; |
7900 |
++ int err; |
7901 |
+ unsigned int hash; |
7902 |
+ struct unix_address *addr; |
7903 |
+ struct hlist_head *list; |
7904 |
+- struct path path; |
7905 |
+- struct dentry *dentry; |
7906 |
+ |
7907 |
+ err = -EINVAL; |
7908 |
+ if (sunaddr->sun_family != AF_UNIX) |
7909 |
+@@ -985,34 +995,14 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) |
7910 |
+ goto out; |
7911 |
+ addr_len = err; |
7912 |
+ |
7913 |
+- name_err = 0; |
7914 |
+- dentry = NULL; |
7915 |
+- if (sun_path[0]) { |
7916 |
+- /* Get the parent directory, calculate the hash for last |
7917 |
+- * component. |
7918 |
+- */ |
7919 |
+- dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0); |
7920 |
+- |
7921 |
+- if (IS_ERR(dentry)) { |
7922 |
+- /* delay report until after 'already bound' check */ |
7923 |
+- name_err = PTR_ERR(dentry); |
7924 |
+- dentry = NULL; |
7925 |
+- } |
7926 |
+- } |
7927 |
+- |
7928 |
+ err = mutex_lock_interruptible(&u->readlock); |
7929 |
+ if (err) |
7930 |
+- goto out_path; |
7931 |
++ goto out; |
7932 |
+ |
7933 |
+ err = -EINVAL; |
7934 |
+ if (u->addr) |
7935 |
+ goto out_up; |
7936 |
+ |
7937 |
+- if (name_err) { |
7938 |
+- err = name_err == -EEXIST ? -EADDRINUSE : name_err; |
7939 |
+- goto out_up; |
7940 |
+- } |
7941 |
+- |
7942 |
+ err = -ENOMEM; |
7943 |
+ addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL); |
7944 |
+ if (!addr) |
7945 |
+@@ -1023,11 +1013,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) |
7946 |
+ addr->hash = hash ^ sk->sk_type; |
7947 |
+ atomic_set(&addr->refcnt, 1); |
7948 |
+ |
7949 |
+- if (dentry) { |
7950 |
+- struct path u_path; |
7951 |
++ if (sun_path[0]) { |
7952 |
++ struct path path; |
7953 |
+ umode_t mode = S_IFSOCK | |
7954 |
+ (SOCK_INODE(sock)->i_mode & ~current_umask()); |
7955 |
+- err = unix_mknod(dentry, &path, mode, &u_path); |
7956 |
++ err = unix_mknod(sun_path, mode, &path); |
7957 |
+ if (err) { |
7958 |
+ if (err == -EEXIST) |
7959 |
+ err = -EADDRINUSE; |
7960 |
+@@ -1035,9 +1025,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) |
7961 |
+ goto out_up; |
7962 |
+ } |
7963 |
+ addr->hash = UNIX_HASH_SIZE; |
7964 |
+- hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1); |
7965 |
++ hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE-1); |
7966 |
+ spin_lock(&unix_table_lock); |
7967 |
+- u->path = u_path; |
7968 |
++ u->path = path; |
7969 |
+ list = &unix_socket_table[hash]; |
7970 |
+ } else { |
7971 |
+ spin_lock(&unix_table_lock); |
7972 |
+@@ -1060,10 +1050,6 @@ out_unlock: |
7973 |
+ spin_unlock(&unix_table_lock); |
7974 |
+ out_up: |
7975 |
+ mutex_unlock(&u->readlock); |
7976 |
+-out_path: |
7977 |
+- if (dentry) |
7978 |
+- done_path_create(&path, dentry); |
7979 |
+- |
7980 |
+ out: |
7981 |
+ return err; |
7982 |
+ } |
7983 |
+diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c |
7984 |
+index 4769382d9478..64faba06be38 100644 |
7985 |
+--- a/net/xfrm/xfrm_policy.c |
7986 |
++++ b/net/xfrm/xfrm_policy.c |
7987 |
+@@ -3004,6 +3004,11 @@ static int __net_init xfrm_net_init(struct net *net) |
7988 |
+ { |
7989 |
+ int rv; |
7990 |
+ |
7991 |
++ /* Initialize the per-net locks here */ |
7992 |
++ spin_lock_init(&net->xfrm.xfrm_state_lock); |
7993 |
++ rwlock_init(&net->xfrm.xfrm_policy_lock); |
7994 |
++ mutex_init(&net->xfrm.xfrm_cfg_mutex); |
7995 |
++ |
7996 |
+ rv = xfrm_statistics_init(net); |
7997 |
+ if (rv < 0) |
7998 |
+ goto out_statistics; |
7999 |
+@@ -3020,11 +3025,6 @@ static int __net_init xfrm_net_init(struct net *net) |
8000 |
+ if (rv < 0) |
8001 |
+ goto out; |
8002 |
+ |
8003 |
+- /* Initialize the per-net locks here */ |
8004 |
+- spin_lock_init(&net->xfrm.xfrm_state_lock); |
8005 |
+- rwlock_init(&net->xfrm.xfrm_policy_lock); |
8006 |
+- mutex_init(&net->xfrm.xfrm_cfg_mutex); |
8007 |
+- |
8008 |
+ return 0; |
8009 |
+ |
8010 |
+ out: |
8011 |
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c |
8012 |
+index e812e988c111..b8170ae1461e 100644 |
8013 |
+--- a/net/xfrm/xfrm_user.c |
8014 |
++++ b/net/xfrm/xfrm_user.c |
8015 |
+@@ -386,7 +386,14 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es |
8016 |
+ up = nla_data(rp); |
8017 |
+ ulen = xfrm_replay_state_esn_len(up); |
8018 |
+ |
8019 |
+- if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen) |
8020 |
++ /* Check the overall length and the internal bitmap length to avoid |
8021 |
++ * potential overflow. */ |
8022 |
++ if (nla_len(rp) < ulen || |
8023 |
++ xfrm_replay_state_esn_len(replay_esn) != ulen || |
8024 |
++ replay_esn->bmp_len != up->bmp_len) |
8025 |
++ return -EINVAL; |
8026 |
++ |
8027 |
++ if (up->replay_window > up->bmp_len * sizeof(__u32) * 8) |
8028 |
+ return -EINVAL; |
8029 |
+ |
8030 |
+ return 0; |
8031 |
+diff --git a/samples/mic/mpssd/.gitignore b/samples/mic/mpssd/.gitignore |
8032 |
+new file mode 100644 |
8033 |
+index 000000000000..8b7c72f07c92 |
8034 |
+--- /dev/null |
8035 |
++++ b/samples/mic/mpssd/.gitignore |
8036 |
+@@ -0,0 +1 @@ |
8037 |
++mpssd |
8038 |
+diff --git a/samples/mic/mpssd/Makefile b/samples/mic/mpssd/Makefile |
8039 |
+new file mode 100644 |
8040 |
+index 000000000000..3e3ef91fed6b |
8041 |
+--- /dev/null |
8042 |
++++ b/samples/mic/mpssd/Makefile |
8043 |
+@@ -0,0 +1,27 @@ |
8044 |
++ifndef CROSS_COMPILE |
8045 |
++uname_M := $(shell uname -m 2>/dev/null || echo not) |
8046 |
++ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) |
8047 |
++ |
8048 |
++ifeq ($(ARCH),x86) |
8049 |
++ |
8050 |
++PROGS := mpssd |
8051 |
++CC = $(CROSS_COMPILE)gcc |
8052 |
++CFLAGS := -I../../../usr/include -I../../../tools/include |
8053 |
++ |
8054 |
++ifdef DEBUG |
8055 |
++CFLAGS += -DDEBUG=$(DEBUG) |
8056 |
++endif |
8057 |
++ |
8058 |
++all: $(PROGS) |
8059 |
++mpssd: mpssd.c sysfs.c |
8060 |
++ $(CC) $(CFLAGS) mpssd.c sysfs.c -o mpssd -lpthread |
8061 |
++ |
8062 |
++install: |
8063 |
++ install mpssd /usr/sbin/mpssd |
8064 |
++ install micctrl /usr/sbin/micctrl |
8065 |
++ |
8066 |
++clean: |
8067 |
++ rm -fr $(PROGS) |
8068 |
++ |
8069 |
++endif |
8070 |
++endif |
8071 |
+diff --git a/samples/mic/mpssd/micctrl b/samples/mic/mpssd/micctrl |
8072 |
+new file mode 100644 |
8073 |
+index 000000000000..8f2629b41c5f |
8074 |
+--- /dev/null |
8075 |
++++ b/samples/mic/mpssd/micctrl |
8076 |
+@@ -0,0 +1,173 @@ |
8077 |
++#!/bin/bash |
8078 |
++# Intel MIC Platform Software Stack (MPSS) |
8079 |
++# |
8080 |
++# Copyright(c) 2013 Intel Corporation. |
8081 |
++# |
8082 |
++# This program is free software; you can redistribute it and/or modify |
8083 |
++# it under the terms of the GNU General Public License, version 2, as |
8084 |
++# published by the Free Software Foundation. |
8085 |
++# |
8086 |
++# This program is distributed in the hope that it will be useful, but |
8087 |
++# WITHOUT ANY WARRANTY; without even the implied warranty of |
8088 |
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
8089 |
++# General Public License for more details. |
8090 |
++# |
8091 |
++# The full GNU General Public License is included in this distribution in |
8092 |
++# the file called "COPYING". |
8093 |
++# |
8094 |
++# Intel MIC User Space Tools. |
8095 |
++# |
8096 |
++# micctrl - Controls MIC boot/start/stop. |
8097 |
++# |
8098 |
++# chkconfig: 2345 95 05 |
8099 |
++# description: start MPSS stack processing. |
8100 |
++# |
8101 |
++### BEGIN INIT INFO |
8102 |
++# Provides: micctrl |
8103 |
++### END INIT INFO |
8104 |
++ |
8105 |
++# Source function library. |
8106 |
++. /etc/init.d/functions |
8107 |
++ |
8108 |
++sysfs="/sys/class/mic" |
8109 |
++ |
8110 |
++_status() |
8111 |
++{ |
8112 |
++ f=$sysfs/$1 |
8113 |
++ echo -e $1 state: "`cat $f/state`" shutdown_status: "`cat $f/shutdown_status`" |
8114 |
++} |
8115 |
++ |
8116 |
++status() |
8117 |
++{ |
8118 |
++ if [ "`echo $1 | head -c3`" == "mic" ]; then |
8119 |
++ _status $1 |
8120 |
++ return $? |
8121 |
++ fi |
8122 |
++ for f in $sysfs/* |
8123 |
++ do |
8124 |
++ _status `basename $f` |
8125 |
++ RETVAL=$? |
8126 |
++ [ $RETVAL -ne 0 ] && return $RETVAL |
8127 |
++ done |
8128 |
++ return 0 |
8129 |
++} |
8130 |
++ |
8131 |
++_reset() |
8132 |
++{ |
8133 |
++ f=$sysfs/$1 |
8134 |
++ echo reset > $f/state |
8135 |
++} |
8136 |
++ |
8137 |
++reset() |
8138 |
++{ |
8139 |
++ if [ "`echo $1 | head -c3`" == "mic" ]; then |
8140 |
++ _reset $1 |
8141 |
++ return $? |
8142 |
++ fi |
8143 |
++ for f in $sysfs/* |
8144 |
++ do |
8145 |
++ _reset `basename $f` |
8146 |
++ RETVAL=$? |
8147 |
++ [ $RETVAL -ne 0 ] && return $RETVAL |
8148 |
++ done |
8149 |
++ return 0 |
8150 |
++} |
8151 |
++ |
8152 |
++_boot() |
8153 |
++{ |
8154 |
++ f=$sysfs/$1 |
8155 |
++ echo "linux" > $f/bootmode |
8156 |
++ echo "mic/uos.img" > $f/firmware |
8157 |
++ echo "mic/$1.image" > $f/ramdisk |
8158 |
++ echo "boot" > $f/state |
8159 |
++} |
8160 |
++ |
8161 |
++boot() |
8162 |
++{ |
8163 |
++ if [ "`echo $1 | head -c3`" == "mic" ]; then |
8164 |
++ _boot $1 |
8165 |
++ return $? |
8166 |
++ fi |
8167 |
++ for f in $sysfs/* |
8168 |
++ do |
8169 |
++ _boot `basename $f` |
8170 |
++ RETVAL=$? |
8171 |
++ [ $RETVAL -ne 0 ] && return $RETVAL |
8172 |
++ done |
8173 |
++ return 0 |
8174 |
++} |
8175 |
++ |
8176 |
++_shutdown() |
8177 |
++{ |
8178 |
++ f=$sysfs/$1 |
8179 |
++ echo shutdown > $f/state |
8180 |
++} |
8181 |
++ |
8182 |
++shutdown() |
8183 |
++{ |
8184 |
++ if [ "`echo $1 | head -c3`" == "mic" ]; then |
8185 |
++ _shutdown $1 |
8186 |
++ return $? |
8187 |
++ fi |
8188 |
++ for f in $sysfs/* |
8189 |
++ do |
8190 |
++ _shutdown `basename $f` |
8191 |
++ RETVAL=$? |
8192 |
++ [ $RETVAL -ne 0 ] && return $RETVAL |
8193 |
++ done |
8194 |
++ return 0 |
8195 |
++} |
8196 |
++ |
8197 |
++_wait() |
8198 |
++{ |
8199 |
++ f=$sysfs/$1 |
8200 |
++ while [ "`cat $f/state`" != "offline" -a "`cat $f/state`" != "online" ] |
8201 |
++ do |
8202 |
++ sleep 1 |
8203 |
++ echo -e "Waiting for $1 to go offline" |
8204 |
++ done |
8205 |
++} |
8206 |
++ |
8207 |
++wait() |
8208 |
++{ |
8209 |
++ if [ "`echo $1 | head -c3`" == "mic" ]; then |
8210 |
++ _wait $1 |
8211 |
++ return $? |
8212 |
++ fi |
8213 |
++ # Wait for the cards to go offline |
8214 |
++ for f in $sysfs/* |
8215 |
++ do |
8216 |
++ _wait `basename $f` |
8217 |
++ RETVAL=$? |
8218 |
++ [ $RETVAL -ne 0 ] && return $RETVAL |
8219 |
++ done |
8220 |
++ return 0 |
8221 |
++} |
8222 |
++ |
8223 |
++if [ ! -d "$sysfs" ]; then |
8224 |
++ echo -e $"Module unloaded " |
8225 |
++ exit 3 |
8226 |
++fi |
8227 |
++ |
8228 |
++case $1 in |
8229 |
++ -s) |
8230 |
++ status $2 |
8231 |
++ ;; |
8232 |
++ -r) |
8233 |
++ reset $2 |
8234 |
++ ;; |
8235 |
++ -b) |
8236 |
++ boot $2 |
8237 |
++ ;; |
8238 |
++ -S) |
8239 |
++ shutdown $2 |
8240 |
++ ;; |
8241 |
++ -w) |
8242 |
++ wait $2 |
8243 |
++ ;; |
8244 |
++ *) |
8245 |
++ echo $"Usage: $0 {-s (status) |-r (reset) |-b (boot) |-S (shutdown) |-w (wait)}" |
8246 |
++ exit 2 |
8247 |
++esac |
8248 |
++ |
8249 |
++exit $? |
8250 |
+diff --git a/samples/mic/mpssd/mpss b/samples/mic/mpssd/mpss |
8251 |
+new file mode 100644 |
8252 |
+index 000000000000..cacbdb0aefb9 |
8253 |
+--- /dev/null |
8254 |
++++ b/samples/mic/mpssd/mpss |
8255 |
+@@ -0,0 +1,202 @@ |
8256 |
++#!/bin/bash |
8257 |
++# Intel MIC Platform Software Stack (MPSS) |
8258 |
++# |
8259 |
++# Copyright(c) 2013 Intel Corporation. |
8260 |
++# |
8261 |
++# This program is free software; you can redistribute it and/or modify |
8262 |
++# it under the terms of the GNU General Public License, version 2, as |
8263 |
++# published by the Free Software Foundation. |
8264 |
++# |
8265 |
++# This program is distributed in the hope that it will be useful, but |
8266 |
++# WITHOUT ANY WARRANTY; without even the implied warranty of |
8267 |
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
8268 |
++# General Public License for more details. |
8269 |
++# |
8270 |
++# The full GNU General Public License is included in this distribution in |
8271 |
++# the file called "COPYING". |
8272 |
++# |
8273 |
++# Intel MIC User Space Tools. |
8274 |
++# |
8275 |
++# mpss Start mpssd. |
8276 |
++# |
8277 |
++# chkconfig: 2345 95 05 |
8278 |
++# description: start MPSS stack processing. |
8279 |
++# |
8280 |
++### BEGIN INIT INFO |
8281 |
++# Provides: mpss |
8282 |
++# Required-Start: |
8283 |
++# Required-Stop: |
8284 |
++# Short-Description: MPSS stack control |
8285 |
++# Description: MPSS stack control |
8286 |
++### END INIT INFO |
8287 |
++ |
8288 |
++# Source function library. |
8289 |
++. /etc/init.d/functions |
8290 |
++ |
8291 |
++exec=/usr/sbin/mpssd |
8292 |
++sysfs="/sys/class/mic" |
8293 |
++ |
8294 |
++start() |
8295 |
++{ |
8296 |
++ [ -x $exec ] || exit 5 |
8297 |
++ |
8298 |
++ if [ "`ps -e | awk '{print $4}' | grep mpssd | head -1`" = "mpssd" ]; then |
8299 |
++ echo -e $"MPSSD already running! " |
8300 |
++ success |
8301 |
++ echo |
8302 |
++ return 0 |
8303 |
++ fi |
8304 |
++ |
8305 |
++ echo -e $"Starting MPSS Stack" |
8306 |
++ echo -e $"Loading MIC_X100_DMA & MIC_HOST Modules" |
8307 |
++ |
8308 |
++ for f in "mic_host" "mic_x100_dma" |
8309 |
++ do |
8310 |
++ modprobe $f |
8311 |
++ RETVAL=$? |
8312 |
++ if [ $RETVAL -ne 0 ]; then |
8313 |
++ failure |
8314 |
++ echo |
8315 |
++ return $RETVAL |
8316 |
++ fi |
8317 |
++ done |
8318 |
++ |
8319 |
++ # Start the daemon |
8320 |
++ echo -n $"Starting MPSSD " |
8321 |
++ $exec |
8322 |
++ RETVAL=$? |
8323 |
++ if [ $RETVAL -ne 0 ]; then |
8324 |
++ failure |
8325 |
++ echo |
8326 |
++ return $RETVAL |
8327 |
++ fi |
8328 |
++ success |
8329 |
++ echo |
8330 |
++ |
8331 |
++ sleep 5 |
8332 |
++ |
8333 |
++ # Boot the cards |
8334 |
++ micctrl -b |
8335 |
++ |
8336 |
++ # Wait till ping works |
8337 |
++ for f in $sysfs/* |
8338 |
++ do |
8339 |
++ count=100 |
8340 |
++ ipaddr=`cat $f/cmdline` |
8341 |
++ ipaddr=${ipaddr#*address,} |
8342 |
++ ipaddr=`echo $ipaddr | cut -d, -f1 | cut -d\; -f1` |
8343 |
++ while [ $count -ge 0 ] |
8344 |
++ do |
8345 |
++ echo -e "Pinging "`basename $f`" " |
8346 |
++ ping -c 1 $ipaddr &> /dev/null |
8347 |
++ RETVAL=$? |
8348 |
++ if [ $RETVAL -eq 0 ]; then |
8349 |
++ success |
8350 |
++ break |
8351 |
++ fi |
8352 |
++ sleep 1 |
8353 |
++ count=`expr $count - 1` |
8354 |
++ done |
8355 |
++ [ $RETVAL -ne 0 ] && failure || success |
8356 |
++ echo |
8357 |
++ done |
8358 |
++ return $RETVAL |
8359 |
++} |
8360 |
++ |
8361 |
++stop() |
8362 |
++{ |
8363 |
++ echo -e $"Shutting down MPSS Stack: " |
8364 |
++ |
8365 |
++ # Bail out if module is unloaded |
8366 |
++ if [ ! -d "$sysfs" ]; then |
8367 |
++ echo -n $"Module unloaded " |
8368 |
++ success |
8369 |
++ echo |
8370 |
++ return 0 |
8371 |
++ fi |
8372 |
++ |
8373 |
++ # Shut down the cards. |
8374 |
++ micctrl -S |
8375 |
++ |
8376 |
++ # Wait for the cards to go offline |
8377 |
++ for f in $sysfs/* |
8378 |
++ do |
8379 |
++ while [ "`cat $f/state`" != "offline" ] |
8380 |
++ do |
8381 |
++ sleep 1 |
8382 |
++ echo -e "Waiting for "`basename $f`" to go offline" |
8383 |
++ done |
8384 |
++ done |
8385 |
++ |
8386 |
++ # Display the status of the cards |
8387 |
++ micctrl -s |
8388 |
++ |
8389 |
++ # Kill MPSSD now |
8390 |
++ echo -n $"Killing MPSSD" |
8391 |
++ killall -9 mpssd 2>/dev/null |
8392 |
++ RETVAL=$? |
8393 |
++ [ $RETVAL -ne 0 ] && failure || success |
8394 |
++ echo |
8395 |
++ return $RETVAL |
8396 |
++} |
8397 |
++ |
8398 |
++restart() |
8399 |
++{ |
8400 |
++ stop |
8401 |
++ sleep 5 |
8402 |
++ start |
8403 |
++} |
8404 |
++ |
8405 |
++status() |
8406 |
++{ |
8407 |
++ micctrl -s |
8408 |
++ if [ "`ps -e | awk '{print $4}' | grep mpssd | head -n 1`" = "mpssd" ]; then |
8409 |
++ echo "mpssd is running" |
8410 |
++ else |
8411 |
++ echo "mpssd is stopped" |
8412 |
++ fi |
8413 |
++ return 0 |
8414 |
++} |
8415 |
++ |
8416 |
++unload() |
8417 |
++{ |
8418 |
++ if [ ! -d "$sysfs" ]; then |
8419 |
++ echo -n $"No MIC_HOST Module: " |
8420 |
++ success |
8421 |
++ echo |
8422 |
++ return |
8423 |
++ fi |
8424 |
++ |
8425 |
++ stop |
8426 |
++ |
8427 |
++ sleep 5 |
8428 |
++ echo -n $"Removing MIC_HOST & MIC_X100_DMA Modules: " |
8429 |
++ modprobe -r mic_host mic_x100_dma |
8430 |
++ RETVAL=$? |
8431 |
++ [ $RETVAL -ne 0 ] && failure || success |
8432 |
++ echo |
8433 |
++ return $RETVAL |
8434 |
++} |
8435 |
++ |
8436 |
++case $1 in |
8437 |
++ start) |
8438 |
++ start |
8439 |
++ ;; |
8440 |
++ stop) |
8441 |
++ stop |
8442 |
++ ;; |
8443 |
++ restart) |
8444 |
++ restart |
8445 |
++ ;; |
8446 |
++ status) |
8447 |
++ status |
8448 |
++ ;; |
8449 |
++ unload) |
8450 |
++ unload |
8451 |
++ ;; |
8452 |
++ *) |
8453 |
++ echo $"Usage: $0 {start|stop|restart|status|unload}" |
8454 |
++ exit 2 |
8455 |
++esac |
8456 |
++ |
8457 |
++exit $? |
8458 |
+diff --git a/samples/mic/mpssd/mpssd.c b/samples/mic/mpssd/mpssd.c |
8459 |
+new file mode 100644 |
8460 |
+index 000000000000..3c5c379fc29d |
8461 |
+--- /dev/null |
8462 |
++++ b/samples/mic/mpssd/mpssd.c |
8463 |
+@@ -0,0 +1,1728 @@ |
8464 |
++/* |
8465 |
++ * Intel MIC Platform Software Stack (MPSS) |
8466 |
++ * |
8467 |
++ * Copyright(c) 2013 Intel Corporation. |
8468 |
++ * |
8469 |
++ * This program is free software; you can redistribute it and/or modify |
8470 |
++ * it under the terms of the GNU General Public License, version 2, as |
8471 |
++ * published by the Free Software Foundation. |
8472 |
++ * |
8473 |
++ * This program is distributed in the hope that it will be useful, but |
8474 |
++ * WITHOUT ANY WARRANTY; without even the implied warranty of |
8475 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
8476 |
++ * General Public License for more details. |
8477 |
++ * |
8478 |
++ * The full GNU General Public License is included in this distribution in |
8479 |
++ * the file called "COPYING". |
8480 |
++ * |
8481 |
++ * Intel MIC User Space Tools. |
8482 |
++ */ |
8483 |
++ |
8484 |
++#define _GNU_SOURCE |
8485 |
++ |
8486 |
++#include <stdlib.h> |
8487 |
++#include <fcntl.h> |
8488 |
++#include <getopt.h> |
8489 |
++#include <assert.h> |
8490 |
++#include <unistd.h> |
8491 |
++#include <stdbool.h> |
8492 |
++#include <signal.h> |
8493 |
++#include <poll.h> |
8494 |
++#include <features.h> |
8495 |
++#include <sys/types.h> |
8496 |
++#include <sys/stat.h> |
8497 |
++#include <sys/mman.h> |
8498 |
++#include <sys/socket.h> |
8499 |
++#include <linux/virtio_ring.h> |
8500 |
++#include <linux/virtio_net.h> |
8501 |
++#include <linux/virtio_console.h> |
8502 |
++#include <linux/virtio_blk.h> |
8503 |
++#include <linux/version.h> |
8504 |
++#include "mpssd.h" |
8505 |
++#include <linux/mic_ioctl.h> |
8506 |
++#include <linux/mic_common.h> |
8507 |
++#include <tools/endian.h> |
8508 |
++ |
8509 |
++static void init_mic(struct mic_info *mic); |
8510 |
++ |
8511 |
++static FILE *logfp; |
8512 |
++static struct mic_info mic_list; |
8513 |
++ |
8514 |
++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
8515 |
++ |
8516 |
++#define min_t(type, x, y) ({ \ |
8517 |
++ type __min1 = (x); \ |
8518 |
++ type __min2 = (y); \ |
8519 |
++ __min1 < __min2 ? __min1 : __min2; }) |
8520 |
++ |
8521 |
++/* align addr on a size boundary - adjust address up/down if needed */ |
8522 |
++#define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1))) |
8523 |
++#define _ALIGN_UP(addr, size) _ALIGN_DOWN(addr + size - 1, size) |
8524 |
++ |
8525 |
++/* align addr on a size boundary - adjust address up if needed */ |
8526 |
++#define _ALIGN(addr, size) _ALIGN_UP(addr, size) |
8527 |
++ |
8528 |
++/* to align the pointer to the (next) page boundary */ |
8529 |
++#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) |
8530 |
++ |
8531 |
++#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) |
8532 |
++ |
8533 |
++#define GSO_ENABLED 1 |
8534 |
++#define MAX_GSO_SIZE (64 * 1024) |
8535 |
++#define ETH_H_LEN 14 |
8536 |
++#define MAX_NET_PKT_SIZE (_ALIGN_UP(MAX_GSO_SIZE + ETH_H_LEN, 64)) |
8537 |
++#define MIC_DEVICE_PAGE_END 0x1000 |
8538 |
++ |
8539 |
++#ifndef VIRTIO_NET_HDR_F_DATA_VALID |
8540 |
++#define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */ |
8541 |
++#endif |
8542 |
++ |
8543 |
++static struct { |
8544 |
++ struct mic_device_desc dd; |
8545 |
++ struct mic_vqconfig vqconfig[2]; |
8546 |
++ __u32 host_features, guest_acknowledgements; |
8547 |
++ struct virtio_console_config cons_config; |
8548 |
++} virtcons_dev_page = { |
8549 |
++ .dd = { |
8550 |
++ .type = VIRTIO_ID_CONSOLE, |
8551 |
++ .num_vq = ARRAY_SIZE(virtcons_dev_page.vqconfig), |
8552 |
++ .feature_len = sizeof(virtcons_dev_page.host_features), |
8553 |
++ .config_len = sizeof(virtcons_dev_page.cons_config), |
8554 |
++ }, |
8555 |
++ .vqconfig[0] = { |
8556 |
++ .num = htole16(MIC_VRING_ENTRIES), |
8557 |
++ }, |
8558 |
++ .vqconfig[1] = { |
8559 |
++ .num = htole16(MIC_VRING_ENTRIES), |
8560 |
++ }, |
8561 |
++}; |
8562 |
++ |
8563 |
++static struct { |
8564 |
++ struct mic_device_desc dd; |
8565 |
++ struct mic_vqconfig vqconfig[2]; |
8566 |
++ __u32 host_features, guest_acknowledgements; |
8567 |
++ struct virtio_net_config net_config; |
8568 |
++} virtnet_dev_page = { |
8569 |
++ .dd = { |
8570 |
++ .type = VIRTIO_ID_NET, |
8571 |
++ .num_vq = ARRAY_SIZE(virtnet_dev_page.vqconfig), |
8572 |
++ .feature_len = sizeof(virtnet_dev_page.host_features), |
8573 |
++ .config_len = sizeof(virtnet_dev_page.net_config), |
8574 |
++ }, |
8575 |
++ .vqconfig[0] = { |
8576 |
++ .num = htole16(MIC_VRING_ENTRIES), |
8577 |
++ }, |
8578 |
++ .vqconfig[1] = { |
8579 |
++ .num = htole16(MIC_VRING_ENTRIES), |
8580 |
++ }, |
8581 |
++#if GSO_ENABLED |
8582 |
++ .host_features = htole32( |
8583 |
++ 1 << VIRTIO_NET_F_CSUM | |
8584 |
++ 1 << VIRTIO_NET_F_GSO | |
8585 |
++ 1 << VIRTIO_NET_F_GUEST_TSO4 | |
8586 |
++ 1 << VIRTIO_NET_F_GUEST_TSO6 | |
8587 |
++ 1 << VIRTIO_NET_F_GUEST_ECN | |
8588 |
++ 1 << VIRTIO_NET_F_GUEST_UFO), |
8589 |
++#else |
8590 |
++ .host_features = 0, |
8591 |
++#endif |
8592 |
++}; |
8593 |
++ |
8594 |
++static const char *mic_config_dir = "/etc/sysconfig/mic"; |
8595 |
++static const char *virtblk_backend = "VIRTBLK_BACKEND"; |
8596 |
++static struct { |
8597 |
++ struct mic_device_desc dd; |
8598 |
++ struct mic_vqconfig vqconfig[1]; |
8599 |
++ __u32 host_features, guest_acknowledgements; |
8600 |
++ struct virtio_blk_config blk_config; |
8601 |
++} virtblk_dev_page = { |
8602 |
++ .dd = { |
8603 |
++ .type = VIRTIO_ID_BLOCK, |
8604 |
++ .num_vq = ARRAY_SIZE(virtblk_dev_page.vqconfig), |
8605 |
++ .feature_len = sizeof(virtblk_dev_page.host_features), |
8606 |
++ .config_len = sizeof(virtblk_dev_page.blk_config), |
8607 |
++ }, |
8608 |
++ .vqconfig[0] = { |
8609 |
++ .num = htole16(MIC_VRING_ENTRIES), |
8610 |
++ }, |
8611 |
++ .host_features = |
8612 |
++ htole32(1<<VIRTIO_BLK_F_SEG_MAX), |
8613 |
++ .blk_config = { |
8614 |
++ .seg_max = htole32(MIC_VRING_ENTRIES - 2), |
8615 |
++ .capacity = htole64(0), |
8616 |
++ } |
8617 |
++}; |
8618 |
++ |
8619 |
++static char *myname; |
8620 |
++ |
8621 |
++static int |
8622 |
++tap_configure(struct mic_info *mic, char *dev) |
8623 |
++{ |
8624 |
++ pid_t pid; |
8625 |
++ char *ifargv[7]; |
8626 |
++ char ipaddr[IFNAMSIZ]; |
8627 |
++ int ret = 0; |
8628 |
++ |
8629 |
++ pid = fork(); |
8630 |
++ if (pid == 0) { |
8631 |
++ ifargv[0] = "ip"; |
8632 |
++ ifargv[1] = "link"; |
8633 |
++ ifargv[2] = "set"; |
8634 |
++ ifargv[3] = dev; |
8635 |
++ ifargv[4] = "up"; |
8636 |
++ ifargv[5] = NULL; |
8637 |
++ mpsslog("Configuring %s\n", dev); |
8638 |
++ ret = execvp("ip", ifargv); |
8639 |
++ if (ret < 0) { |
8640 |
++ mpsslog("%s execvp failed errno %s\n", |
8641 |
++ mic->name, strerror(errno)); |
8642 |
++ return ret; |
8643 |
++ } |
8644 |
++ } |
8645 |
++ if (pid < 0) { |
8646 |
++ mpsslog("%s fork failed errno %s\n", |
8647 |
++ mic->name, strerror(errno)); |
8648 |
++ return ret; |
8649 |
++ } |
8650 |
++ |
8651 |
++ ret = waitpid(pid, NULL, 0); |
8652 |
++ if (ret < 0) { |
8653 |
++ mpsslog("%s waitpid failed errno %s\n", |
8654 |
++ mic->name, strerror(errno)); |
8655 |
++ return ret; |
8656 |
++ } |
8657 |
++ |
8658 |
++ snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id); |
8659 |
++ |
8660 |
++ pid = fork(); |
8661 |
++ if (pid == 0) { |
8662 |
++ ifargv[0] = "ip"; |
8663 |
++ ifargv[1] = "addr"; |
8664 |
++ ifargv[2] = "add"; |
8665 |
++ ifargv[3] = ipaddr; |
8666 |
++ ifargv[4] = "dev"; |
8667 |
++ ifargv[5] = dev; |
8668 |
++ ifargv[6] = NULL; |
8669 |
++ mpsslog("Configuring %s ipaddr %s\n", dev, ipaddr); |
8670 |
++ ret = execvp("ip", ifargv); |
8671 |
++ if (ret < 0) { |
8672 |
++ mpsslog("%s execvp failed errno %s\n", |
8673 |
++ mic->name, strerror(errno)); |
8674 |
++ return ret; |
8675 |
++ } |
8676 |
++ } |
8677 |
++ if (pid < 0) { |
8678 |
++ mpsslog("%s fork failed errno %s\n", |
8679 |
++ mic->name, strerror(errno)); |
8680 |
++ return ret; |
8681 |
++ } |
8682 |
++ |
8683 |
++ ret = waitpid(pid, NULL, 0); |
8684 |
++ if (ret < 0) { |
8685 |
++ mpsslog("%s waitpid failed errno %s\n", |
8686 |
++ mic->name, strerror(errno)); |
8687 |
++ return ret; |
8688 |
++ } |
8689 |
++ mpsslog("MIC name %s %s %d DONE!\n", |
8690 |
++ mic->name, __func__, __LINE__); |
8691 |
++ return 0; |
8692 |
++} |
8693 |
++ |
8694 |
++static int tun_alloc(struct mic_info *mic, char *dev) |
8695 |
++{ |
8696 |
++ struct ifreq ifr; |
8697 |
++ int fd, err; |
8698 |
++#if GSO_ENABLED |
8699 |
++ unsigned offload; |
8700 |
++#endif |
8701 |
++ fd = open("/dev/net/tun", O_RDWR); |
8702 |
++ if (fd < 0) { |
8703 |
++ mpsslog("Could not open /dev/net/tun %s\n", strerror(errno)); |
8704 |
++ goto done; |
8705 |
++ } |
8706 |
++ |
8707 |
++ memset(&ifr, 0, sizeof(ifr)); |
8708 |
++ |
8709 |
++ ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR; |
8710 |
++ if (*dev) |
8711 |
++ strncpy(ifr.ifr_name, dev, IFNAMSIZ); |
8712 |
++ |
8713 |
++ err = ioctl(fd, TUNSETIFF, (void *)&ifr); |
8714 |
++ if (err < 0) { |
8715 |
++ mpsslog("%s %s %d TUNSETIFF failed %s\n", |
8716 |
++ mic->name, __func__, __LINE__, strerror(errno)); |
8717 |
++ close(fd); |
8718 |
++ return err; |
8719 |
++ } |
8720 |
++#if GSO_ENABLED |
8721 |
++ offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | |
8722 |
++ TUN_F_TSO_ECN | TUN_F_UFO; |
8723 |
++ |
8724 |
++ err = ioctl(fd, TUNSETOFFLOAD, offload); |
8725 |
++ if (err < 0) { |
8726 |
++ mpsslog("%s %s %d TUNSETOFFLOAD failed %s\n", |
8727 |
++ mic->name, __func__, __LINE__, strerror(errno)); |
8728 |
++ close(fd); |
8729 |
++ return err; |
8730 |
++ } |
8731 |
++#endif |
8732 |
++ strcpy(dev, ifr.ifr_name); |
8733 |
++ mpsslog("Created TAP %s\n", dev); |
8734 |
++done: |
8735 |
++ return fd; |
8736 |
++} |
8737 |
++ |
8738 |
++#define NET_FD_VIRTIO_NET 0 |
8739 |
++#define NET_FD_TUN 1 |
8740 |
++#define MAX_NET_FD 2 |
8741 |
++ |
8742 |
++static void set_dp(struct mic_info *mic, int type, void *dp) |
8743 |
++{ |
8744 |
++ switch (type) { |
8745 |
++ case VIRTIO_ID_CONSOLE: |
8746 |
++ mic->mic_console.console_dp = dp; |
8747 |
++ return; |
8748 |
++ case VIRTIO_ID_NET: |
8749 |
++ mic->mic_net.net_dp = dp; |
8750 |
++ return; |
8751 |
++ case VIRTIO_ID_BLOCK: |
8752 |
++ mic->mic_virtblk.block_dp = dp; |
8753 |
++ return; |
8754 |
++ } |
8755 |
++ mpsslog("%s %s %d not found\n", mic->name, __func__, type); |
8756 |
++ assert(0); |
8757 |
++} |
8758 |
++ |
8759 |
++static void *get_dp(struct mic_info *mic, int type) |
8760 |
++{ |
8761 |
++ switch (type) { |
8762 |
++ case VIRTIO_ID_CONSOLE: |
8763 |
++ return mic->mic_console.console_dp; |
8764 |
++ case VIRTIO_ID_NET: |
8765 |
++ return mic->mic_net.net_dp; |
8766 |
++ case VIRTIO_ID_BLOCK: |
8767 |
++ return mic->mic_virtblk.block_dp; |
8768 |
++ } |
8769 |
++ mpsslog("%s %s %d not found\n", mic->name, __func__, type); |
8770 |
++ assert(0); |
8771 |
++ return NULL; |
8772 |
++} |
8773 |
++ |
8774 |
++static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type) |
8775 |
++{ |
8776 |
++ struct mic_device_desc *d; |
8777 |
++ int i; |
8778 |
++ void *dp = get_dp(mic, type); |
8779 |
++ |
8780 |
++ for (i = sizeof(struct mic_bootparam); i < PAGE_SIZE; |
8781 |
++ i += mic_total_desc_size(d)) { |
8782 |
++ d = dp + i; |
8783 |
++ |
8784 |
++ /* End of list */ |
8785 |
++ if (d->type == 0) |
8786 |
++ break; |
8787 |
++ |
8788 |
++ if (d->type == -1) |
8789 |
++ continue; |
8790 |
++ |
8791 |
++ mpsslog("%s %s d-> type %d d %p\n", |
8792 |
++ mic->name, __func__, d->type, d); |
8793 |
++ |
8794 |
++ if (d->type == (__u8)type) |
8795 |
++ return d; |
8796 |
++ } |
8797 |
++ mpsslog("%s %s %d not found\n", mic->name, __func__, type); |
8798 |
++ assert(0); |
8799 |
++ return NULL; |
8800 |
++} |
8801 |
++ |
8802 |
++/* See comments in vhost.c for explanation of next_desc() */ |
8803 |
++static unsigned next_desc(struct vring_desc *desc) |
8804 |
++{ |
8805 |
++ unsigned int next; |
8806 |
++ |
8807 |
++ if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT)) |
8808 |
++ return -1U; |
8809 |
++ next = le16toh(desc->next); |
8810 |
++ return next; |
8811 |
++} |
8812 |
++ |
8813 |
++/* Sum up all the IOVEC length */ |
8814 |
++static ssize_t |
8815 |
++sum_iovec_len(struct mic_copy_desc *copy) |
8816 |
++{ |
8817 |
++ ssize_t sum = 0; |
8818 |
++ int i; |
8819 |
++ |
8820 |
++ for (i = 0; i < copy->iovcnt; i++) |
8821 |
++ sum += copy->iov[i].iov_len; |
8822 |
++ return sum; |
8823 |
++} |
8824 |
++ |
8825 |
++static inline void verify_out_len(struct mic_info *mic, |
8826 |
++ struct mic_copy_desc *copy) |
8827 |
++{ |
8828 |
++ if (copy->out_len != sum_iovec_len(copy)) { |
8829 |
++ mpsslog("%s %s %d BUG copy->out_len 0x%x len 0x%zx\n", |
8830 |
++ mic->name, __func__, __LINE__, |
8831 |
++ copy->out_len, sum_iovec_len(copy)); |
8832 |
++ assert(copy->out_len == sum_iovec_len(copy)); |
8833 |
++ } |
8834 |
++} |
8835 |
++ |
8836 |
++/* Display an iovec */ |
8837 |
++static void |
8838 |
++disp_iovec(struct mic_info *mic, struct mic_copy_desc *copy, |
8839 |
++ const char *s, int line) |
8840 |
++{ |
8841 |
++ int i; |
8842 |
++ |
8843 |
++ for (i = 0; i < copy->iovcnt; i++) |
8844 |
++ mpsslog("%s %s %d copy->iov[%d] addr %p len 0x%zx\n", |
8845 |
++ mic->name, s, line, i, |
8846 |
++ copy->iov[i].iov_base, copy->iov[i].iov_len); |
8847 |
++} |
8848 |
++ |
8849 |
++static inline __u16 read_avail_idx(struct mic_vring *vr) |
8850 |
++{ |
8851 |
++ return ACCESS_ONCE(vr->info->avail_idx); |
8852 |
++} |
8853 |
++ |
8854 |
++static inline void txrx_prepare(int type, bool tx, struct mic_vring *vr, |
8855 |
++ struct mic_copy_desc *copy, ssize_t len) |
8856 |
++{ |
8857 |
++ copy->vr_idx = tx ? 0 : 1; |
8858 |
++ copy->update_used = true; |
8859 |
++ if (type == VIRTIO_ID_NET) |
8860 |
++ copy->iov[1].iov_len = len - sizeof(struct virtio_net_hdr); |
8861 |
++ else |
8862 |
++ copy->iov[0].iov_len = len; |
8863 |
++} |
8864 |
++ |
8865 |
++/* Central API which triggers the copies */ |
8866 |
++static int |
8867 |
++mic_virtio_copy(struct mic_info *mic, int fd, |
8868 |
++ struct mic_vring *vr, struct mic_copy_desc *copy) |
8869 |
++{ |
8870 |
++ int ret; |
8871 |
++ |
8872 |
++ ret = ioctl(fd, MIC_VIRTIO_COPY_DESC, copy); |
8873 |
++ if (ret) { |
8874 |
++ mpsslog("%s %s %d errno %s ret %d\n", |
8875 |
++ mic->name, __func__, __LINE__, |
8876 |
++ strerror(errno), ret); |
8877 |
++ } |
8878 |
++ return ret; |
8879 |
++} |
8880 |
++ |
8881 |
++/* |
8882 |
++ * This initialization routine requires at least one |
8883 |
++ * vring i.e. vr0. vr1 is optional. |
8884 |
++ */ |
8885 |
++static void * |
8886 |
++init_vr(struct mic_info *mic, int fd, int type, |
8887 |
++ struct mic_vring *vr0, struct mic_vring *vr1, int num_vq) |
8888 |
++{ |
8889 |
++ int vr_size; |
8890 |
++ char *va; |
8891 |
++ |
8892 |
++ vr_size = PAGE_ALIGN(vring_size(MIC_VRING_ENTRIES, |
8893 |
++ MIC_VIRTIO_RING_ALIGN) + sizeof(struct _mic_vring_info)); |
8894 |
++ va = mmap(NULL, MIC_DEVICE_PAGE_END + vr_size * num_vq, |
8895 |
++ PROT_READ, MAP_SHARED, fd, 0); |
8896 |
++ if (MAP_FAILED == va) { |
8897 |
++ mpsslog("%s %s %d mmap failed errno %s\n", |
8898 |
++ mic->name, __func__, __LINE__, |
8899 |
++ strerror(errno)); |
8900 |
++ goto done; |
8901 |
++ } |
8902 |
++ set_dp(mic, type, va); |
8903 |
++ vr0->va = (struct mic_vring *)&va[MIC_DEVICE_PAGE_END]; |
8904 |
++ vr0->info = vr0->va + |
8905 |
++ vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN); |
8906 |
++ vring_init(&vr0->vr, |
8907 |
++ MIC_VRING_ENTRIES, vr0->va, MIC_VIRTIO_RING_ALIGN); |
8908 |
++ mpsslog("%s %s vr0 %p vr0->info %p vr_size 0x%x vring 0x%x ", |
8909 |
++ __func__, mic->name, vr0->va, vr0->info, vr_size, |
8910 |
++ vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN)); |
8911 |
++ mpsslog("magic 0x%x expected 0x%x\n", |
8912 |
++ le32toh(vr0->info->magic), MIC_MAGIC + type); |
8913 |
++ assert(le32toh(vr0->info->magic) == MIC_MAGIC + type); |
8914 |
++ if (vr1) { |
8915 |
++ vr1->va = (struct mic_vring *) |
8916 |
++ &va[MIC_DEVICE_PAGE_END + vr_size]; |
8917 |
++ vr1->info = vr1->va + vring_size(MIC_VRING_ENTRIES, |
8918 |
++ MIC_VIRTIO_RING_ALIGN); |
8919 |
++ vring_init(&vr1->vr, |
8920 |
++ MIC_VRING_ENTRIES, vr1->va, MIC_VIRTIO_RING_ALIGN); |
8921 |
++ mpsslog("%s %s vr1 %p vr1->info %p vr_size 0x%x vring 0x%x ", |
8922 |
++ __func__, mic->name, vr1->va, vr1->info, vr_size, |
8923 |
++ vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN)); |
8924 |
++ mpsslog("magic 0x%x expected 0x%x\n", |
8925 |
++ le32toh(vr1->info->magic), MIC_MAGIC + type + 1); |
8926 |
++ assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1); |
8927 |
++ } |
8928 |
++done: |
8929 |
++ return va; |
8930 |
++} |
8931 |
++ |
8932 |
++static void |
8933 |
++wait_for_card_driver(struct mic_info *mic, int fd, int type) |
8934 |
++{ |
8935 |
++ struct pollfd pollfd; |
8936 |
++ int err; |
8937 |
++ struct mic_device_desc *desc = get_device_desc(mic, type); |
8938 |
++ |
8939 |
++ pollfd.fd = fd; |
8940 |
++ mpsslog("%s %s Waiting .... desc-> type %d status 0x%x\n", |
8941 |
++ mic->name, __func__, type, desc->status); |
8942 |
++ while (1) { |
8943 |
++ pollfd.events = POLLIN; |
8944 |
++ pollfd.revents = 0; |
8945 |
++ err = poll(&pollfd, 1, -1); |
8946 |
++ if (err < 0) { |
8947 |
++ mpsslog("%s %s poll failed %s\n", |
8948 |
++ mic->name, __func__, strerror(errno)); |
8949 |
++ continue; |
8950 |
++ } |
8951 |
++ |
8952 |
++ if (pollfd.revents) { |
8953 |
++ mpsslog("%s %s Waiting... desc-> type %d status 0x%x\n", |
8954 |
++ mic->name, __func__, type, desc->status); |
8955 |
++ if (desc->status & VIRTIO_CONFIG_S_DRIVER_OK) { |
8956 |
++ mpsslog("%s %s poll.revents %d\n", |
8957 |
++ mic->name, __func__, pollfd.revents); |
8958 |
++ mpsslog("%s %s desc-> type %d status 0x%x\n", |
8959 |
++ mic->name, __func__, type, |
8960 |
++ desc->status); |
8961 |
++ break; |
8962 |
++ } |
8963 |
++ } |
8964 |
++ } |
8965 |
++} |
8966 |
++ |
8967 |
++/* Spin till we have some descriptors */ |
8968 |
++static void |
8969 |
++spin_for_descriptors(struct mic_info *mic, struct mic_vring *vr) |
8970 |
++{ |
8971 |
++ __u16 avail_idx = read_avail_idx(vr); |
8972 |
++ |
8973 |
++ while (avail_idx == le16toh(ACCESS_ONCE(vr->vr.avail->idx))) { |
8974 |
++#ifdef DEBUG |
8975 |
++ mpsslog("%s %s waiting for desc avail %d info_avail %d\n", |
8976 |
++ mic->name, __func__, |
8977 |
++ le16toh(vr->vr.avail->idx), vr->info->avail_idx); |
8978 |
++#endif |
8979 |
++ sched_yield(); |
8980 |
++ } |
8981 |
++} |
8982 |
++ |
8983 |
++static void * |
8984 |
++virtio_net(void *arg) |
8985 |
++{ |
8986 |
++ static __u8 vnet_hdr[2][sizeof(struct virtio_net_hdr)]; |
8987 |
++ static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __attribute__ ((aligned(64))); |
8988 |
++ struct iovec vnet_iov[2][2] = { |
8989 |
++ { { .iov_base = vnet_hdr[0], .iov_len = sizeof(vnet_hdr[0]) }, |
8990 |
++ { .iov_base = vnet_buf[0], .iov_len = sizeof(vnet_buf[0]) } }, |
8991 |
++ { { .iov_base = vnet_hdr[1], .iov_len = sizeof(vnet_hdr[1]) }, |
8992 |
++ { .iov_base = vnet_buf[1], .iov_len = sizeof(vnet_buf[1]) } }, |
8993 |
++ }; |
8994 |
++ struct iovec *iov0 = vnet_iov[0], *iov1 = vnet_iov[1]; |
8995 |
++ struct mic_info *mic = (struct mic_info *)arg; |
8996 |
++ char if_name[IFNAMSIZ]; |
8997 |
++ struct pollfd net_poll[MAX_NET_FD]; |
8998 |
++ struct mic_vring tx_vr, rx_vr; |
8999 |
++ struct mic_copy_desc copy; |
9000 |
++ struct mic_device_desc *desc; |
9001 |
++ int err; |
9002 |
++ |
9003 |
++ snprintf(if_name, IFNAMSIZ, "mic%d", mic->id); |
9004 |
++ mic->mic_net.tap_fd = tun_alloc(mic, if_name); |
9005 |
++ if (mic->mic_net.tap_fd < 0) |
9006 |
++ goto done; |
9007 |
++ |
9008 |
++ if (tap_configure(mic, if_name)) |
9009 |
++ goto done; |
9010 |
++ mpsslog("MIC name %s id %d\n", mic->name, mic->id); |
9011 |
++ |
9012 |
++ net_poll[NET_FD_VIRTIO_NET].fd = mic->mic_net.virtio_net_fd; |
9013 |
++ net_poll[NET_FD_VIRTIO_NET].events = POLLIN; |
9014 |
++ net_poll[NET_FD_TUN].fd = mic->mic_net.tap_fd; |
9015 |
++ net_poll[NET_FD_TUN].events = POLLIN; |
9016 |
++ |
9017 |
++ if (MAP_FAILED == init_vr(mic, mic->mic_net.virtio_net_fd, |
9018 |
++ VIRTIO_ID_NET, &tx_vr, &rx_vr, |
9019 |
++ virtnet_dev_page.dd.num_vq)) { |
9020 |
++ mpsslog("%s init_vr failed %s\n", |
9021 |
++ mic->name, strerror(errno)); |
9022 |
++ goto done; |
9023 |
++ } |
9024 |
++ |
9025 |
++ copy.iovcnt = 2; |
9026 |
++ desc = get_device_desc(mic, VIRTIO_ID_NET); |
9027 |
++ |
9028 |
++ while (1) { |
9029 |
++ ssize_t len; |
9030 |
++ |
9031 |
++ net_poll[NET_FD_VIRTIO_NET].revents = 0; |
9032 |
++ net_poll[NET_FD_TUN].revents = 0; |
9033 |
++ |
9034 |
++ /* Start polling for data from tap and virtio net */ |
9035 |
++ err = poll(net_poll, 2, -1); |
9036 |
++ if (err < 0) { |
9037 |
++ mpsslog("%s poll failed %s\n", |
9038 |
++ __func__, strerror(errno)); |
9039 |
++ continue; |
9040 |
++ } |
9041 |
++ if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) |
9042 |
++ wait_for_card_driver(mic, mic->mic_net.virtio_net_fd, |
9043 |
++ VIRTIO_ID_NET); |
9044 |
++ /* |
9045 |
++ * Check if there is data to be read from TUN and write to |
9046 |
++ * virtio net fd if there is. |
9047 |
++ */ |
9048 |
++ if (net_poll[NET_FD_TUN].revents & POLLIN) { |
9049 |
++ copy.iov = iov0; |
9050 |
++ len = readv(net_poll[NET_FD_TUN].fd, |
9051 |
++ copy.iov, copy.iovcnt); |
9052 |
++ if (len > 0) { |
9053 |
++ struct virtio_net_hdr *hdr |
9054 |
++ = (struct virtio_net_hdr *)vnet_hdr[0]; |
9055 |
++ |
9056 |
++ /* Disable checksums on the card since we are on |
9057 |
++ a reliable PCIe link */ |
9058 |
++ hdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID; |
9059 |
++#ifdef DEBUG |
9060 |
++ mpsslog("%s %s %d hdr->flags 0x%x ", mic->name, |
9061 |
++ __func__, __LINE__, hdr->flags); |
9062 |
++ mpsslog("copy.out_len %d hdr->gso_type 0x%x\n", |
9063 |
++ copy.out_len, hdr->gso_type); |
9064 |
++#endif |
9065 |
++#ifdef DEBUG |
9066 |
++ disp_iovec(mic, copy, __func__, __LINE__); |
9067 |
++ mpsslog("%s %s %d read from tap 0x%lx\n", |
9068 |
++ mic->name, __func__, __LINE__, |
9069 |
++ len); |
9070 |
++#endif |
9071 |
++ spin_for_descriptors(mic, &tx_vr); |
9072 |
++ txrx_prepare(VIRTIO_ID_NET, 1, &tx_vr, ©, |
9073 |
++ len); |
9074 |
++ |
9075 |
++ err = mic_virtio_copy(mic, |
9076 |
++ mic->mic_net.virtio_net_fd, &tx_vr, |
9077 |
++ ©); |
9078 |
++ if (err < 0) { |
9079 |
++ mpsslog("%s %s %d mic_virtio_copy %s\n", |
9080 |
++ mic->name, __func__, __LINE__, |
9081 |
++ strerror(errno)); |
9082 |
++ } |
9083 |
++ if (!err) |
9084 |
++ verify_out_len(mic, ©); |
9085 |
++#ifdef DEBUG |
9086 |
++ disp_iovec(mic, copy, __func__, __LINE__); |
9087 |
++ mpsslog("%s %s %d wrote to net 0x%lx\n", |
9088 |
++ mic->name, __func__, __LINE__, |
9089 |
++ sum_iovec_len(©)); |
9090 |
++#endif |
9091 |
++ /* Reinitialize IOV for next run */ |
9092 |
++ iov0[1].iov_len = MAX_NET_PKT_SIZE; |
9093 |
++ } else if (len < 0) { |
9094 |
++ disp_iovec(mic, ©, __func__, __LINE__); |
9095 |
++ mpsslog("%s %s %d read failed %s ", mic->name, |
9096 |
++ __func__, __LINE__, strerror(errno)); |
9097 |
++ mpsslog("cnt %d sum %zd\n", |
9098 |
++ copy.iovcnt, sum_iovec_len(©)); |
9099 |
++ } |
9100 |
++ } |
9101 |
++ |
9102 |
++ /* |
9103 |
++ * Check if there is data to be read from virtio net and |
9104 |
++ * write to TUN if there is. |
9105 |
++ */ |
9106 |
++ if (net_poll[NET_FD_VIRTIO_NET].revents & POLLIN) { |
9107 |
++ while (rx_vr.info->avail_idx != |
9108 |
++ le16toh(rx_vr.vr.avail->idx)) { |
9109 |
++ copy.iov = iov1; |
9110 |
++ txrx_prepare(VIRTIO_ID_NET, 0, &rx_vr, ©, |
9111 |
++ MAX_NET_PKT_SIZE |
9112 |
++ + sizeof(struct virtio_net_hdr)); |
9113 |
++ |
9114 |
++ err = mic_virtio_copy(mic, |
9115 |
++ mic->mic_net.virtio_net_fd, &rx_vr, |
9116 |
++ ©); |
9117 |
++ if (!err) { |
9118 |
++#ifdef DEBUG |
9119 |
++ struct virtio_net_hdr *hdr |
9120 |
++ = (struct virtio_net_hdr *) |
9121 |
++ vnet_hdr[1]; |
9122 |
++ |
9123 |
++ mpsslog("%s %s %d hdr->flags 0x%x, ", |
9124 |
++ mic->name, __func__, __LINE__, |
9125 |
++ hdr->flags); |
9126 |
++ mpsslog("out_len %d gso_type 0x%x\n", |
9127 |
++ copy.out_len, |
9128 |
++ hdr->gso_type); |
9129 |
++#endif |
9130 |
++ /* Set the correct output iov_len */ |
9131 |
++ iov1[1].iov_len = copy.out_len - |
9132 |
++ sizeof(struct virtio_net_hdr); |
9133 |
++ verify_out_len(mic, ©); |
9134 |
++#ifdef DEBUG |
9135 |
++ disp_iovec(mic, copy, __func__, |
9136 |
++ __LINE__); |
9137 |
++ mpsslog("%s %s %d ", |
9138 |
++ mic->name, __func__, __LINE__); |
9139 |
++ mpsslog("read from net 0x%lx\n", |
9140 |
++ sum_iovec_len(copy)); |
9141 |
++#endif |
9142 |
++ len = writev(net_poll[NET_FD_TUN].fd, |
9143 |
++ copy.iov, copy.iovcnt); |
9144 |
++ if (len != sum_iovec_len(©)) { |
9145 |
++ mpsslog("Tun write failed %s ", |
9146 |
++ strerror(errno)); |
9147 |
++ mpsslog("len 0x%zx ", len); |
9148 |
++ mpsslog("read_len 0x%zx\n", |
9149 |
++ sum_iovec_len(©)); |
9150 |
++ } else { |
9151 |
++#ifdef DEBUG |
9152 |
++ disp_iovec(mic, ©, __func__, |
9153 |
++ __LINE__); |
9154 |
++ mpsslog("%s %s %d ", |
9155 |
++ mic->name, __func__, |
9156 |
++ __LINE__); |
9157 |
++ mpsslog("wrote to tap 0x%lx\n", |
9158 |
++ len); |
9159 |
++#endif |
9160 |
++ } |
9161 |
++ } else { |
9162 |
++ mpsslog("%s %s %d mic_virtio_copy %s\n", |
9163 |
++ mic->name, __func__, __LINE__, |
9164 |
++ strerror(errno)); |
9165 |
++ break; |
9166 |
++ } |
9167 |
++ } |
9168 |
++ } |
9169 |
++ if (net_poll[NET_FD_VIRTIO_NET].revents & POLLERR) |
9170 |
++ mpsslog("%s: %s: POLLERR\n", __func__, mic->name); |
9171 |
++ } |
9172 |
++done: |
9173 |
++ pthread_exit(NULL); |
9174 |
++} |
9175 |
++ |
9176 |
++/* virtio_console */ |
9177 |
++#define VIRTIO_CONSOLE_FD 0 |
9178 |
++#define MONITOR_FD (VIRTIO_CONSOLE_FD + 1) |
9179 |
++#define MAX_CONSOLE_FD (MONITOR_FD + 1) /* must be the last one + 1 */ |
9180 |
++#define MAX_BUFFER_SIZE PAGE_SIZE |
9181 |
++ |
9182 |
++static void * |
9183 |
++virtio_console(void *arg) |
9184 |
++{ |
9185 |
++ static __u8 vcons_buf[2][PAGE_SIZE]; |
9186 |
++ struct iovec vcons_iov[2] = { |
9187 |
++ { .iov_base = vcons_buf[0], .iov_len = sizeof(vcons_buf[0]) }, |
9188 |
++ { .iov_base = vcons_buf[1], .iov_len = sizeof(vcons_buf[1]) }, |
9189 |
++ }; |
9190 |
++ struct iovec *iov0 = &vcons_iov[0], *iov1 = &vcons_iov[1]; |
9191 |
++ struct mic_info *mic = (struct mic_info *)arg; |
9192 |
++ int err; |
9193 |
++ struct pollfd console_poll[MAX_CONSOLE_FD]; |
9194 |
++ int pty_fd; |
9195 |
++ char *pts_name; |
9196 |
++ ssize_t len; |
9197 |
++ struct mic_vring tx_vr, rx_vr; |
9198 |
++ struct mic_copy_desc copy; |
9199 |
++ struct mic_device_desc *desc; |
9200 |
++ |
9201 |
++ pty_fd = posix_openpt(O_RDWR); |
9202 |
++ if (pty_fd < 0) { |
9203 |
++ mpsslog("can't open a pseudoterminal master device: %s\n", |
9204 |
++ strerror(errno)); |
9205 |
++ goto _return; |
9206 |
++ } |
9207 |
++ pts_name = ptsname(pty_fd); |
9208 |
++ if (pts_name == NULL) { |
9209 |
++ mpsslog("can't get pts name\n"); |
9210 |
++ goto _close_pty; |
9211 |
++ } |
9212 |
++ printf("%s console message goes to %s\n", mic->name, pts_name); |
9213 |
++ mpsslog("%s console message goes to %s\n", mic->name, pts_name); |
9214 |
++ err = grantpt(pty_fd); |
9215 |
++ if (err < 0) { |
9216 |
++ mpsslog("can't grant access: %s %s\n", |
9217 |
++ pts_name, strerror(errno)); |
9218 |
++ goto _close_pty; |
9219 |
++ } |
9220 |
++ err = unlockpt(pty_fd); |
9221 |
++ if (err < 0) { |
9222 |
++ mpsslog("can't unlock a pseudoterminal: %s %s\n", |
9223 |
++ pts_name, strerror(errno)); |
9224 |
++ goto _close_pty; |
9225 |
++ } |
9226 |
++ console_poll[MONITOR_FD].fd = pty_fd; |
9227 |
++ console_poll[MONITOR_FD].events = POLLIN; |
9228 |
++ |
9229 |
++ console_poll[VIRTIO_CONSOLE_FD].fd = mic->mic_console.virtio_console_fd; |
9230 |
++ console_poll[VIRTIO_CONSOLE_FD].events = POLLIN; |
9231 |
++ |
9232 |
++ if (MAP_FAILED == init_vr(mic, mic->mic_console.virtio_console_fd, |
9233 |
++ VIRTIO_ID_CONSOLE, &tx_vr, &rx_vr, |
9234 |
++ virtcons_dev_page.dd.num_vq)) { |
9235 |
++ mpsslog("%s init_vr failed %s\n", |
9236 |
++ mic->name, strerror(errno)); |
9237 |
++ goto _close_pty; |
9238 |
++ } |
9239 |
++ |
9240 |
++ copy.iovcnt = 1; |
9241 |
++ desc = get_device_desc(mic, VIRTIO_ID_CONSOLE); |
9242 |
++ |
9243 |
++ for (;;) { |
9244 |
++ console_poll[MONITOR_FD].revents = 0; |
9245 |
++ console_poll[VIRTIO_CONSOLE_FD].revents = 0; |
9246 |
++ err = poll(console_poll, MAX_CONSOLE_FD, -1); |
9247 |
++ if (err < 0) { |
9248 |
++ mpsslog("%s %d: poll failed: %s\n", __func__, __LINE__, |
9249 |
++ strerror(errno)); |
9250 |
++ continue; |
9251 |
++ } |
9252 |
++ if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) |
9253 |
++ wait_for_card_driver(mic, |
9254 |
++ mic->mic_console.virtio_console_fd, |
9255 |
++ VIRTIO_ID_CONSOLE); |
9256 |
++ |
9257 |
++ if (console_poll[MONITOR_FD].revents & POLLIN) { |
9258 |
++ copy.iov = iov0; |
9259 |
++ len = readv(pty_fd, copy.iov, copy.iovcnt); |
9260 |
++ if (len > 0) { |
9261 |
++#ifdef DEBUG |
9262 |
++ disp_iovec(mic, copy, __func__, __LINE__); |
9263 |
++ mpsslog("%s %s %d read from tap 0x%lx\n", |
9264 |
++ mic->name, __func__, __LINE__, |
9265 |
++ len); |
9266 |
++#endif |
9267 |
++ spin_for_descriptors(mic, &tx_vr); |
9268 |
++ txrx_prepare(VIRTIO_ID_CONSOLE, 1, &tx_vr, |
9269 |
++ ©, len); |
9270 |
++ |
9271 |
++ err = mic_virtio_copy(mic, |
9272 |
++ mic->mic_console.virtio_console_fd, |
9273 |
++ &tx_vr, ©); |
9274 |
++ if (err < 0) { |
9275 |
++ mpsslog("%s %s %d mic_virtio_copy %s\n", |
9276 |
++ mic->name, __func__, __LINE__, |
9277 |
++ strerror(errno)); |
9278 |
++ } |
9279 |
++ if (!err) |
9280 |
++ verify_out_len(mic, ©); |
9281 |
++#ifdef DEBUG |
9282 |
++ disp_iovec(mic, copy, __func__, __LINE__); |
9283 |
++ mpsslog("%s %s %d wrote to net 0x%lx\n", |
9284 |
++ mic->name, __func__, __LINE__, |
9285 |
++ sum_iovec_len(copy)); |
9286 |
++#endif |
9287 |
++ /* Reinitialize IOV for next run */ |
9288 |
++ iov0->iov_len = PAGE_SIZE; |
9289 |
++ } else if (len < 0) { |
9290 |
++ disp_iovec(mic, ©, __func__, __LINE__); |
9291 |
++ mpsslog("%s %s %d read failed %s ", |
9292 |
++ mic->name, __func__, __LINE__, |
9293 |
++ strerror(errno)); |
9294 |
++ mpsslog("cnt %d sum %zd\n", |
9295 |
++ copy.iovcnt, sum_iovec_len(©)); |
9296 |
++ } |
9297 |
++ } |
9298 |
++ |
9299 |
++ if (console_poll[VIRTIO_CONSOLE_FD].revents & POLLIN) { |
9300 |
++ while (rx_vr.info->avail_idx != |
9301 |
++ le16toh(rx_vr.vr.avail->idx)) { |
9302 |
++ copy.iov = iov1; |
9303 |
++ txrx_prepare(VIRTIO_ID_CONSOLE, 0, &rx_vr, |
9304 |
++ ©, PAGE_SIZE); |
9305 |
++ |
9306 |
++ err = mic_virtio_copy(mic, |
9307 |
++ mic->mic_console.virtio_console_fd, |
9308 |
++ &rx_vr, ©); |
9309 |
++ if (!err) { |
9310 |
++ /* Set the correct output iov_len */ |
9311 |
++ iov1->iov_len = copy.out_len; |
9312 |
++ verify_out_len(mic, ©); |
9313 |
++#ifdef DEBUG |
9314 |
++ disp_iovec(mic, copy, __func__, |
9315 |
++ __LINE__); |
9316 |
++ mpsslog("%s %s %d ", |
9317 |
++ mic->name, __func__, __LINE__); |
9318 |
++ mpsslog("read from net 0x%lx\n", |
9319 |
++ sum_iovec_len(copy)); |
9320 |
++#endif |
9321 |
++ len = writev(pty_fd, |
9322 |
++ copy.iov, copy.iovcnt); |
9323 |
++ if (len != sum_iovec_len(©)) { |
9324 |
++ mpsslog("Tun write failed %s ", |
9325 |
++ strerror(errno)); |
9326 |
++ mpsslog("len 0x%zx ", len); |
9327 |
++ mpsslog("read_len 0x%zx\n", |
9328 |
++ sum_iovec_len(©)); |
9329 |
++ } else { |
9330 |
++#ifdef DEBUG |
9331 |
++ disp_iovec(mic, copy, __func__, |
9332 |
++ __LINE__); |
9333 |
++ mpsslog("%s %s %d ", |
9334 |
++ mic->name, __func__, |
9335 |
++ __LINE__); |
9336 |
++ mpsslog("wrote to tap 0x%lx\n", |
9337 |
++ len); |
9338 |
++#endif |
9339 |
++ } |
9340 |
++ } else { |
9341 |
++ mpsslog("%s %s %d mic_virtio_copy %s\n", |
9342 |
++ mic->name, __func__, __LINE__, |
9343 |
++ strerror(errno)); |
9344 |
++ break; |
9345 |
++ } |
9346 |
++ } |
9347 |
++ } |
9348 |
++ if (console_poll[NET_FD_VIRTIO_NET].revents & POLLERR) |
9349 |
++ mpsslog("%s: %s: POLLERR\n", __func__, mic->name); |
9350 |
++ } |
9351 |
++_close_pty: |
9352 |
++ close(pty_fd); |
9353 |
++_return: |
9354 |
++ pthread_exit(NULL); |
9355 |
++} |
9356 |
++ |
9357 |
++static void |
9358 |
++add_virtio_device(struct mic_info *mic, struct mic_device_desc *dd) |
9359 |
++{ |
9360 |
++ char path[PATH_MAX]; |
9361 |
++ int fd, err; |
9362 |
++ |
9363 |
++ snprintf(path, PATH_MAX, "/dev/mic%d", mic->id); |
9364 |
++ fd = open(path, O_RDWR); |
9365 |
++ if (fd < 0) { |
9366 |
++ mpsslog("Could not open %s %s\n", path, strerror(errno)); |
9367 |
++ return; |
9368 |
++ } |
9369 |
++ |
9370 |
++ err = ioctl(fd, MIC_VIRTIO_ADD_DEVICE, dd); |
9371 |
++ if (err < 0) { |
9372 |
++ mpsslog("Could not add %d %s\n", dd->type, strerror(errno)); |
9373 |
++ close(fd); |
9374 |
++ return; |
9375 |
++ } |
9376 |
++ switch (dd->type) { |
9377 |
++ case VIRTIO_ID_NET: |
9378 |
++ mic->mic_net.virtio_net_fd = fd; |
9379 |
++ mpsslog("Added VIRTIO_ID_NET for %s\n", mic->name); |
9380 |
++ break; |
9381 |
++ case VIRTIO_ID_CONSOLE: |
9382 |
++ mic->mic_console.virtio_console_fd = fd; |
9383 |
++ mpsslog("Added VIRTIO_ID_CONSOLE for %s\n", mic->name); |
9384 |
++ break; |
9385 |
++ case VIRTIO_ID_BLOCK: |
9386 |
++ mic->mic_virtblk.virtio_block_fd = fd; |
9387 |
++ mpsslog("Added VIRTIO_ID_BLOCK for %s\n", mic->name); |
9388 |
++ break; |
9389 |
++ } |
9390 |
++} |
9391 |
++ |
9392 |
++static bool |
9393 |
++set_backend_file(struct mic_info *mic) |
9394 |
++{ |
9395 |
++ FILE *config; |
9396 |
++ char buff[PATH_MAX], *line, *evv, *p; |
9397 |
++ |
9398 |
++ snprintf(buff, PATH_MAX, "%s/mpssd%03d.conf", mic_config_dir, mic->id); |
9399 |
++ config = fopen(buff, "r"); |
9400 |
++ if (config == NULL) |
9401 |
++ return false; |
9402 |
++ do { /* look for "virtblk_backend=XXXX" */ |
9403 |
++ line = fgets(buff, PATH_MAX, config); |
9404 |
++ if (line == NULL) |
9405 |
++ break; |
9406 |
++ if (*line == '#') |
9407 |
++ continue; |
9408 |
++ p = strchr(line, '\n'); |
9409 |
++ if (p) |
9410 |
++ *p = '\0'; |
9411 |
++ } while (strncmp(line, virtblk_backend, strlen(virtblk_backend)) != 0); |
9412 |
++ fclose(config); |
9413 |
++ if (line == NULL) |
9414 |
++ return false; |
9415 |
++ evv = strchr(line, '='); |
9416 |
++ if (evv == NULL) |
9417 |
++ return false; |
9418 |
++ mic->mic_virtblk.backend_file = malloc(strlen(evv) + 1); |
9419 |
++ if (mic->mic_virtblk.backend_file == NULL) { |
9420 |
++ mpsslog("%s %d can't allocate memory\n", mic->name, mic->id); |
9421 |
++ return false; |
9422 |
++ } |
9423 |
++ strcpy(mic->mic_virtblk.backend_file, evv + 1); |
9424 |
++ return true; |
9425 |
++} |
9426 |
++ |
9427 |
++#define SECTOR_SIZE 512 |
9428 |
++static bool |
9429 |
++set_backend_size(struct mic_info *mic) |
9430 |
++{ |
9431 |
++ mic->mic_virtblk.backend_size = lseek(mic->mic_virtblk.backend, 0, |
9432 |
++ SEEK_END); |
9433 |
++ if (mic->mic_virtblk.backend_size < 0) { |
9434 |
++ mpsslog("%s: can't seek: %s\n", |
9435 |
++ mic->name, mic->mic_virtblk.backend_file); |
9436 |
++ return false; |
9437 |
++ } |
9438 |
++ virtblk_dev_page.blk_config.capacity = |
9439 |
++ mic->mic_virtblk.backend_size / SECTOR_SIZE; |
9440 |
++ if ((mic->mic_virtblk.backend_size % SECTOR_SIZE) != 0) |
9441 |
++ virtblk_dev_page.blk_config.capacity++; |
9442 |
++ |
9443 |
++ virtblk_dev_page.blk_config.capacity = |
9444 |
++ htole64(virtblk_dev_page.blk_config.capacity); |
9445 |
++ |
9446 |
++ return true; |
9447 |
++} |
9448 |
++ |
9449 |
++static bool |
9450 |
++open_backend(struct mic_info *mic) |
9451 |
++{ |
9452 |
++ if (!set_backend_file(mic)) |
9453 |
++ goto _error_exit; |
9454 |
++ mic->mic_virtblk.backend = open(mic->mic_virtblk.backend_file, O_RDWR); |
9455 |
++ if (mic->mic_virtblk.backend < 0) { |
9456 |
++ mpsslog("%s: can't open: %s\n", mic->name, |
9457 |
++ mic->mic_virtblk.backend_file); |
9458 |
++ goto _error_free; |
9459 |
++ } |
9460 |
++ if (!set_backend_size(mic)) |
9461 |
++ goto _error_close; |
9462 |
++ mic->mic_virtblk.backend_addr = mmap(NULL, |
9463 |
++ mic->mic_virtblk.backend_size, |
9464 |
++ PROT_READ|PROT_WRITE, MAP_SHARED, |
9465 |
++ mic->mic_virtblk.backend, 0L); |
9466 |
++ if (mic->mic_virtblk.backend_addr == MAP_FAILED) { |
9467 |
++ mpsslog("%s: can't map: %s %s\n", |
9468 |
++ mic->name, mic->mic_virtblk.backend_file, |
9469 |
++ strerror(errno)); |
9470 |
++ goto _error_close; |
9471 |
++ } |
9472 |
++ return true; |
9473 |
++ |
9474 |
++ _error_close: |
9475 |
++ close(mic->mic_virtblk.backend); |
9476 |
++ _error_free: |
9477 |
++ free(mic->mic_virtblk.backend_file); |
9478 |
++ _error_exit: |
9479 |
++ return false; |
9480 |
++} |
9481 |
++ |
9482 |
++static void |
9483 |
++close_backend(struct mic_info *mic) |
9484 |
++{ |
9485 |
++ munmap(mic->mic_virtblk.backend_addr, mic->mic_virtblk.backend_size); |
9486 |
++ close(mic->mic_virtblk.backend); |
9487 |
++ free(mic->mic_virtblk.backend_file); |
9488 |
++} |
9489 |
++ |
9490 |
++static bool |
9491 |
++start_virtblk(struct mic_info *mic, struct mic_vring *vring) |
9492 |
++{ |
9493 |
++ if (((unsigned long)&virtblk_dev_page.blk_config % 8) != 0) { |
9494 |
++ mpsslog("%s: blk_config is not 8 byte aligned.\n", |
9495 |
++ mic->name); |
9496 |
++ return false; |
9497 |
++ } |
9498 |
++ add_virtio_device(mic, &virtblk_dev_page.dd); |
9499 |
++ if (MAP_FAILED == init_vr(mic, mic->mic_virtblk.virtio_block_fd, |
9500 |
++ VIRTIO_ID_BLOCK, vring, NULL, |
9501 |
++ virtblk_dev_page.dd.num_vq)) { |
9502 |
++ mpsslog("%s init_vr failed %s\n", |
9503 |
++ mic->name, strerror(errno)); |
9504 |
++ return false; |
9505 |
++ } |
9506 |
++ return true; |
9507 |
++} |
9508 |
++ |
9509 |
++static void |
9510 |
++stop_virtblk(struct mic_info *mic) |
9511 |
++{ |
9512 |
++ int vr_size, ret; |
9513 |
++ |
9514 |
++ vr_size = PAGE_ALIGN(vring_size(MIC_VRING_ENTRIES, |
9515 |
++ MIC_VIRTIO_RING_ALIGN) + sizeof(struct _mic_vring_info)); |
9516 |
++ ret = munmap(mic->mic_virtblk.block_dp, |
9517 |
++ MIC_DEVICE_PAGE_END + vr_size * virtblk_dev_page.dd.num_vq); |
9518 |
++ if (ret < 0) |
9519 |
++ mpsslog("%s munmap errno %d\n", mic->name, errno); |
9520 |
++ close(mic->mic_virtblk.virtio_block_fd); |
9521 |
++} |
9522 |
++ |
9523 |
++static __u8 |
9524 |
++header_error_check(struct vring_desc *desc) |
9525 |
++{ |
9526 |
++ if (le32toh(desc->len) != sizeof(struct virtio_blk_outhdr)) { |
9527 |
++ mpsslog("%s() %d: length is not sizeof(virtio_blk_outhd)\n", |
9528 |
++ __func__, __LINE__); |
9529 |
++ return -EIO; |
9530 |
++ } |
9531 |
++ if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT)) { |
9532 |
++ mpsslog("%s() %d: alone\n", |
9533 |
++ __func__, __LINE__); |
9534 |
++ return -EIO; |
9535 |
++ } |
9536 |
++ if (le16toh(desc->flags) & VRING_DESC_F_WRITE) { |
9537 |
++ mpsslog("%s() %d: not read\n", |
9538 |
++ __func__, __LINE__); |
9539 |
++ return -EIO; |
9540 |
++ } |
9541 |
++ return 0; |
9542 |
++} |
9543 |
++ |
9544 |
++static int |
9545 |
++read_header(int fd, struct virtio_blk_outhdr *hdr, __u32 desc_idx) |
9546 |
++{ |
9547 |
++ struct iovec iovec; |
9548 |
++ struct mic_copy_desc copy; |
9549 |
++ |
9550 |
++ iovec.iov_len = sizeof(*hdr); |
9551 |
++ iovec.iov_base = hdr; |
9552 |
++ copy.iov = &iovec; |
9553 |
++ copy.iovcnt = 1; |
9554 |
++ copy.vr_idx = 0; /* only one vring on virtio_block */ |
9555 |
++ copy.update_used = false; /* do not update used index */ |
9556 |
++ return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
9557 |
++} |
9558 |
++ |
9559 |
++static int |
9560 |
++transfer_blocks(int fd, struct iovec *iovec, __u32 iovcnt) |
9561 |
++{ |
9562 |
++ struct mic_copy_desc copy; |
9563 |
++ |
9564 |
++ copy.iov = iovec; |
9565 |
++ copy.iovcnt = iovcnt; |
9566 |
++ copy.vr_idx = 0; /* only one vring on virtio_block */ |
9567 |
++ copy.update_used = false; /* do not update used index */ |
9568 |
++ return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
9569 |
++} |
9570 |
++ |
9571 |
++static __u8 |
9572 |
++status_error_check(struct vring_desc *desc) |
9573 |
++{ |
9574 |
++ if (le32toh(desc->len) != sizeof(__u8)) { |
9575 |
++ mpsslog("%s() %d: length is not sizeof(status)\n", |
9576 |
++ __func__, __LINE__); |
9577 |
++ return -EIO; |
9578 |
++ } |
9579 |
++ return 0; |
9580 |
++} |
9581 |
++ |
9582 |
++static int |
9583 |
++write_status(int fd, __u8 *status) |
9584 |
++{ |
9585 |
++ struct iovec iovec; |
9586 |
++ struct mic_copy_desc copy; |
9587 |
++ |
9588 |
++ iovec.iov_base = status; |
9589 |
++ iovec.iov_len = sizeof(*status); |
9590 |
++ copy.iov = &iovec; |
9591 |
++ copy.iovcnt = 1; |
9592 |
++ copy.vr_idx = 0; /* only one vring on virtio_block */ |
9593 |
++ copy.update_used = true; /* Update used index */ |
9594 |
++ return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
9595 |
++} |
9596 |
++ |
9597 |
++static void * |
9598 |
++virtio_block(void *arg) |
9599 |
++{ |
9600 |
++ struct mic_info *mic = (struct mic_info *)arg; |
9601 |
++ int ret; |
9602 |
++ struct pollfd block_poll; |
9603 |
++ struct mic_vring vring; |
9604 |
++ __u16 avail_idx; |
9605 |
++ __u32 desc_idx; |
9606 |
++ struct vring_desc *desc; |
9607 |
++ struct iovec *iovec, *piov; |
9608 |
++ __u8 status; |
9609 |
++ __u32 buffer_desc_idx; |
9610 |
++ struct virtio_blk_outhdr hdr; |
9611 |
++ void *fos; |
9612 |
++ |
9613 |
++ for (;;) { /* forever */ |
9614 |
++ if (!open_backend(mic)) { /* No virtblk */ |
9615 |
++ for (mic->mic_virtblk.signaled = 0; |
9616 |
++ !mic->mic_virtblk.signaled;) |
9617 |
++ sleep(1); |
9618 |
++ continue; |
9619 |
++ } |
9620 |
++ |
9621 |
++ /* backend file is specified. */ |
9622 |
++ if (!start_virtblk(mic, &vring)) |
9623 |
++ goto _close_backend; |
9624 |
++ iovec = malloc(sizeof(*iovec) * |
9625 |
++ le32toh(virtblk_dev_page.blk_config.seg_max)); |
9626 |
++ if (!iovec) { |
9627 |
++ mpsslog("%s: can't alloc iovec: %s\n", |
9628 |
++ mic->name, strerror(ENOMEM)); |
9629 |
++ goto _stop_virtblk; |
9630 |
++ } |
9631 |
++ |
9632 |
++ block_poll.fd = mic->mic_virtblk.virtio_block_fd; |
9633 |
++ block_poll.events = POLLIN; |
9634 |
++ for (mic->mic_virtblk.signaled = 0; |
9635 |
++ !mic->mic_virtblk.signaled;) { |
9636 |
++ block_poll.revents = 0; |
9637 |
++ /* timeout in 1 sec to see signaled */ |
9638 |
++ ret = poll(&block_poll, 1, 1000); |
9639 |
++ if (ret < 0) { |
9640 |
++ mpsslog("%s %d: poll failed: %s\n", |
9641 |
++ __func__, __LINE__, |
9642 |
++ strerror(errno)); |
9643 |
++ continue; |
9644 |
++ } |
9645 |
++ |
9646 |
++ if (!(block_poll.revents & POLLIN)) { |
9647 |
++#ifdef DEBUG |
9648 |
++ mpsslog("%s %d: block_poll.revents=0x%x\n", |
9649 |
++ __func__, __LINE__, block_poll.revents); |
9650 |
++#endif |
9651 |
++ continue; |
9652 |
++ } |
9653 |
++ |
9654 |
++ /* POLLIN */ |
9655 |
++ while (vring.info->avail_idx != |
9656 |
++ le16toh(vring.vr.avail->idx)) { |
9657 |
++ /* read header element */ |
9658 |
++ avail_idx = |
9659 |
++ vring.info->avail_idx & |
9660 |
++ (vring.vr.num - 1); |
9661 |
++ desc_idx = le16toh( |
9662 |
++ vring.vr.avail->ring[avail_idx]); |
9663 |
++ desc = &vring.vr.desc[desc_idx]; |
9664 |
++#ifdef DEBUG |
9665 |
++ mpsslog("%s() %d: avail_idx=%d ", |
9666 |
++ __func__, __LINE__, |
9667 |
++ vring.info->avail_idx); |
9668 |
++ mpsslog("vring.vr.num=%d desc=%p\n", |
9669 |
++ vring.vr.num, desc); |
9670 |
++#endif |
9671 |
++ status = header_error_check(desc); |
9672 |
++ ret = read_header( |
9673 |
++ mic->mic_virtblk.virtio_block_fd, |
9674 |
++ &hdr, desc_idx); |
9675 |
++ if (ret < 0) { |
9676 |
++ mpsslog("%s() %d %s: ret=%d %s\n", |
9677 |
++ __func__, __LINE__, |
9678 |
++ mic->name, ret, |
9679 |
++ strerror(errno)); |
9680 |
++ break; |
9681 |
++ } |
9682 |
++ /* buffer element */ |
9683 |
++ piov = iovec; |
9684 |
++ status = 0; |
9685 |
++ fos = mic->mic_virtblk.backend_addr + |
9686 |
++ (hdr.sector * SECTOR_SIZE); |
9687 |
++ buffer_desc_idx = next_desc(desc); |
9688 |
++ desc_idx = buffer_desc_idx; |
9689 |
++ for (desc = &vring.vr.desc[buffer_desc_idx]; |
9690 |
++ desc->flags & VRING_DESC_F_NEXT; |
9691 |
++ desc_idx = next_desc(desc), |
9692 |
++ desc = &vring.vr.desc[desc_idx]) { |
9693 |
++ piov->iov_len = desc->len; |
9694 |
++ piov->iov_base = fos; |
9695 |
++ piov++; |
9696 |
++ fos += desc->len; |
9697 |
++ } |
9698 |
++ /* Returning NULLs for VIRTIO_BLK_T_GET_ID. */ |
9699 |
++ if (hdr.type & ~(VIRTIO_BLK_T_OUT | |
9700 |
++ VIRTIO_BLK_T_GET_ID)) { |
9701 |
++ /* |
9702 |
++ VIRTIO_BLK_T_IN - does not do |
9703 |
++ anything. Probably for documenting. |
9704 |
++ VIRTIO_BLK_T_SCSI_CMD - for |
9705 |
++ virtio_scsi. |
9706 |
++ VIRTIO_BLK_T_FLUSH - turned off in |
9707 |
++ config space. |
9708 |
++ VIRTIO_BLK_T_BARRIER - defined but not |
9709 |
++ used in anywhere. |
9710 |
++ */ |
9711 |
++ mpsslog("%s() %d: type %x ", |
9712 |
++ __func__, __LINE__, |
9713 |
++ hdr.type); |
9714 |
++ mpsslog("is not supported\n"); |
9715 |
++ status = -ENOTSUP; |
9716 |
++ |
9717 |
++ } else { |
9718 |
++ ret = transfer_blocks( |
9719 |
++ mic->mic_virtblk.virtio_block_fd, |
9720 |
++ iovec, |
9721 |
++ piov - iovec); |
9722 |
++ if (ret < 0 && |
9723 |
++ status != 0) |
9724 |
++ status = ret; |
9725 |
++ } |
9726 |
++ /* write status and update used pointer */ |
9727 |
++ if (status != 0) |
9728 |
++ status = status_error_check(desc); |
9729 |
++ ret = write_status( |
9730 |
++ mic->mic_virtblk.virtio_block_fd, |
9731 |
++ &status); |
9732 |
++#ifdef DEBUG |
9733 |
++ mpsslog("%s() %d: write status=%d on desc=%p\n", |
9734 |
++ __func__, __LINE__, |
9735 |
++ status, desc); |
9736 |
++#endif |
9737 |
++ } |
9738 |
++ } |
9739 |
++ free(iovec); |
9740 |
++_stop_virtblk: |
9741 |
++ stop_virtblk(mic); |
9742 |
++_close_backend: |
9743 |
++ close_backend(mic); |
9744 |
++ } /* forever */ |
9745 |
++ |
9746 |
++ pthread_exit(NULL); |
9747 |
++} |
9748 |
++ |
9749 |
++static void |
9750 |
++reset(struct mic_info *mic) |
9751 |
++{ |
9752 |
++#define RESET_TIMEOUT 120 |
9753 |
++ int i = RESET_TIMEOUT; |
9754 |
++ setsysfs(mic->name, "state", "reset"); |
9755 |
++ while (i) { |
9756 |
++ char *state; |
9757 |
++ state = readsysfs(mic->name, "state"); |
9758 |
++ if (!state) |
9759 |
++ goto retry; |
9760 |
++ mpsslog("%s: %s %d state %s\n", |
9761 |
++ mic->name, __func__, __LINE__, state); |
9762 |
++ |
9763 |
++ /* |
9764 |
++ * If the shutdown was initiated by OSPM, the state stays |
9765 |
++ * in "suspended" which is also a valid condition for reset. |
9766 |
++ */ |
9767 |
++ if ((!strcmp(state, "offline")) || |
9768 |
++ (!strcmp(state, "suspended"))) { |
9769 |
++ free(state); |
9770 |
++ break; |
9771 |
++ } |
9772 |
++ free(state); |
9773 |
++retry: |
9774 |
++ sleep(1); |
9775 |
++ i--; |
9776 |
++ } |
9777 |
++} |
9778 |
++ |
9779 |
++static int |
9780 |
++get_mic_shutdown_status(struct mic_info *mic, char *shutdown_status) |
9781 |
++{ |
9782 |
++ if (!strcmp(shutdown_status, "nop")) |
9783 |
++ return MIC_NOP; |
9784 |
++ if (!strcmp(shutdown_status, "crashed")) |
9785 |
++ return MIC_CRASHED; |
9786 |
++ if (!strcmp(shutdown_status, "halted")) |
9787 |
++ return MIC_HALTED; |
9788 |
++ if (!strcmp(shutdown_status, "poweroff")) |
9789 |
++ return MIC_POWER_OFF; |
9790 |
++ if (!strcmp(shutdown_status, "restart")) |
9791 |
++ return MIC_RESTART; |
9792 |
++ mpsslog("%s: BUG invalid status %s\n", mic->name, shutdown_status); |
9793 |
++ /* Invalid state */ |
9794 |
++ assert(0); |
9795 |
++}; |
9796 |
++ |
9797 |
++static int get_mic_state(struct mic_info *mic, char *state) |
9798 |
++{ |
9799 |
++ if (!strcmp(state, "offline")) |
9800 |
++ return MIC_OFFLINE; |
9801 |
++ if (!strcmp(state, "online")) |
9802 |
++ return MIC_ONLINE; |
9803 |
++ if (!strcmp(state, "shutting_down")) |
9804 |
++ return MIC_SHUTTING_DOWN; |
9805 |
++ if (!strcmp(state, "reset_failed")) |
9806 |
++ return MIC_RESET_FAILED; |
9807 |
++ if (!strcmp(state, "suspending")) |
9808 |
++ return MIC_SUSPENDING; |
9809 |
++ if (!strcmp(state, "suspended")) |
9810 |
++ return MIC_SUSPENDED; |
9811 |
++ mpsslog("%s: BUG invalid state %s\n", mic->name, state); |
9812 |
++ /* Invalid state */ |
9813 |
++ assert(0); |
9814 |
++}; |
9815 |
++ |
9816 |
++static void mic_handle_shutdown(struct mic_info *mic) |
9817 |
++{ |
9818 |
++#define SHUTDOWN_TIMEOUT 60 |
9819 |
++ int i = SHUTDOWN_TIMEOUT, ret, stat = 0; |
9820 |
++ char *shutdown_status; |
9821 |
++ while (i) { |
9822 |
++ shutdown_status = readsysfs(mic->name, "shutdown_status"); |
9823 |
++ if (!shutdown_status) |
9824 |
++ continue; |
9825 |
++ mpsslog("%s: %s %d shutdown_status %s\n", |
9826 |
++ mic->name, __func__, __LINE__, shutdown_status); |
9827 |
++ switch (get_mic_shutdown_status(mic, shutdown_status)) { |
9828 |
++ case MIC_RESTART: |
9829 |
++ mic->restart = 1; |
9830 |
++ case MIC_HALTED: |
9831 |
++ case MIC_POWER_OFF: |
9832 |
++ case MIC_CRASHED: |
9833 |
++ free(shutdown_status); |
9834 |
++ goto reset; |
9835 |
++ default: |
9836 |
++ break; |
9837 |
++ } |
9838 |
++ free(shutdown_status); |
9839 |
++ sleep(1); |
9840 |
++ i--; |
9841 |
++ } |
9842 |
++reset: |
9843 |
++ ret = kill(mic->pid, SIGTERM); |
9844 |
++ mpsslog("%s: %s %d kill pid %d ret %d\n", |
9845 |
++ mic->name, __func__, __LINE__, |
9846 |
++ mic->pid, ret); |
9847 |
++ if (!ret) { |
9848 |
++ ret = waitpid(mic->pid, &stat, |
9849 |
++ WIFSIGNALED(stat)); |
9850 |
++ mpsslog("%s: %s %d waitpid ret %d pid %d\n", |
9851 |
++ mic->name, __func__, __LINE__, |
9852 |
++ ret, mic->pid); |
9853 |
++ } |
9854 |
++ if (ret == mic->pid) |
9855 |
++ reset(mic); |
9856 |
++} |
9857 |
++ |
9858 |
++static void * |
9859 |
++mic_config(void *arg) |
9860 |
++{ |
9861 |
++ struct mic_info *mic = (struct mic_info *)arg; |
9862 |
++ char *state = NULL; |
9863 |
++ char pathname[PATH_MAX]; |
9864 |
++ int fd, ret; |
9865 |
++ struct pollfd ufds[1]; |
9866 |
++ char value[4096]; |
9867 |
++ |
9868 |
++ snprintf(pathname, PATH_MAX - 1, "%s/%s/%s", |
9869 |
++ MICSYSFSDIR, mic->name, "state"); |
9870 |
++ |
9871 |
++ fd = open(pathname, O_RDONLY); |
9872 |
++ if (fd < 0) { |
9873 |
++ mpsslog("%s: opening file %s failed %s\n", |
9874 |
++ mic->name, pathname, strerror(errno)); |
9875 |
++ goto error; |
9876 |
++ } |
9877 |
++ |
9878 |
++ do { |
9879 |
++ ret = lseek(fd, 0, SEEK_SET); |
9880 |
++ if (ret < 0) { |
9881 |
++ mpsslog("%s: Failed to seek to file start '%s': %s\n", |
9882 |
++ mic->name, pathname, strerror(errno)); |
9883 |
++ goto close_error1; |
9884 |
++ } |
9885 |
++ ret = read(fd, value, sizeof(value)); |
9886 |
++ if (ret < 0) { |
9887 |
++ mpsslog("%s: Failed to read sysfs entry '%s': %s\n", |
9888 |
++ mic->name, pathname, strerror(errno)); |
9889 |
++ goto close_error1; |
9890 |
++ } |
9891 |
++retry: |
9892 |
++ state = readsysfs(mic->name, "state"); |
9893 |
++ if (!state) |
9894 |
++ goto retry; |
9895 |
++ mpsslog("%s: %s %d state %s\n", |
9896 |
++ mic->name, __func__, __LINE__, state); |
9897 |
++ switch (get_mic_state(mic, state)) { |
9898 |
++ case MIC_SHUTTING_DOWN: |
9899 |
++ mic_handle_shutdown(mic); |
9900 |
++ goto close_error; |
9901 |
++ case MIC_SUSPENDING: |
9902 |
++ mic->boot_on_resume = 1; |
9903 |
++ setsysfs(mic->name, "state", "suspend"); |
9904 |
++ mic_handle_shutdown(mic); |
9905 |
++ goto close_error; |
9906 |
++ case MIC_OFFLINE: |
9907 |
++ if (mic->boot_on_resume) { |
9908 |
++ setsysfs(mic->name, "state", "boot"); |
9909 |
++ mic->boot_on_resume = 0; |
9910 |
++ } |
9911 |
++ break; |
9912 |
++ default: |
9913 |
++ break; |
9914 |
++ } |
9915 |
++ free(state); |
9916 |
++ |
9917 |
++ ufds[0].fd = fd; |
9918 |
++ ufds[0].events = POLLERR | POLLPRI; |
9919 |
++ ret = poll(ufds, 1, -1); |
9920 |
++ if (ret < 0) { |
9921 |
++ mpsslog("%s: poll failed %s\n", |
9922 |
++ mic->name, strerror(errno)); |
9923 |
++ goto close_error1; |
9924 |
++ } |
9925 |
++ } while (1); |
9926 |
++close_error: |
9927 |
++ free(state); |
9928 |
++close_error1: |
9929 |
++ close(fd); |
9930 |
++error: |
9931 |
++ init_mic(mic); |
9932 |
++ pthread_exit(NULL); |
9933 |
++} |
9934 |
++ |
9935 |
++static void |
9936 |
++set_cmdline(struct mic_info *mic) |
9937 |
++{ |
9938 |
++ char buffer[PATH_MAX]; |
9939 |
++ int len; |
9940 |
++ |
9941 |
++ len = snprintf(buffer, PATH_MAX, |
9942 |
++ "clocksource=tsc highres=off nohz=off "); |
9943 |
++ len += snprintf(buffer + len, PATH_MAX - len, |
9944 |
++ "cpufreq_on;corec6_off;pc3_off;pc6_off "); |
9945 |
++ len += snprintf(buffer + len, PATH_MAX - len, |
9946 |
++ "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0", |
9947 |
++ mic->id); |
9948 |
++ |
9949 |
++ setsysfs(mic->name, "cmdline", buffer); |
9950 |
++ mpsslog("%s: Command line: \"%s\"\n", mic->name, buffer); |
9951 |
++ snprintf(buffer, PATH_MAX, "172.31.%d.1", mic->id); |
9952 |
++ mpsslog("%s: IPADDR: \"%s\"\n", mic->name, buffer); |
9953 |
++} |
9954 |
++ |
9955 |
++static void |
9956 |
++set_log_buf_info(struct mic_info *mic) |
9957 |
++{ |
9958 |
++ int fd; |
9959 |
++ off_t len; |
9960 |
++ char system_map[] = "/lib/firmware/mic/System.map"; |
9961 |
++ char *map, *temp, log_buf[17] = {'\0'}; |
9962 |
++ |
9963 |
++ fd = open(system_map, O_RDONLY); |
9964 |
++ if (fd < 0) { |
9965 |
++ mpsslog("%s: Opening System.map failed: %d\n", |
9966 |
++ mic->name, errno); |
9967 |
++ return; |
9968 |
++ } |
9969 |
++ len = lseek(fd, 0, SEEK_END); |
9970 |
++ if (len < 0) { |
9971 |
++ mpsslog("%s: Reading System.map size failed: %d\n", |
9972 |
++ mic->name, errno); |
9973 |
++ close(fd); |
9974 |
++ return; |
9975 |
++ } |
9976 |
++ map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); |
9977 |
++ if (map == MAP_FAILED) { |
9978 |
++ mpsslog("%s: mmap of System.map failed: %d\n", |
9979 |
++ mic->name, errno); |
9980 |
++ close(fd); |
9981 |
++ return; |
9982 |
++ } |
9983 |
++ temp = strstr(map, "__log_buf"); |
9984 |
++ if (!temp) { |
9985 |
++ mpsslog("%s: __log_buf not found: %d\n", mic->name, errno); |
9986 |
++ munmap(map, len); |
9987 |
++ close(fd); |
9988 |
++ return; |
9989 |
++ } |
9990 |
++ strncpy(log_buf, temp - 19, 16); |
9991 |
++ setsysfs(mic->name, "log_buf_addr", log_buf); |
9992 |
++ mpsslog("%s: log_buf_addr: %s\n", mic->name, log_buf); |
9993 |
++ temp = strstr(map, "log_buf_len"); |
9994 |
++ if (!temp) { |
9995 |
++ mpsslog("%s: log_buf_len not found: %d\n", mic->name, errno); |
9996 |
++ munmap(map, len); |
9997 |
++ close(fd); |
9998 |
++ return; |
9999 |
++ } |
10000 |
++ strncpy(log_buf, temp - 19, 16); |
10001 |
++ setsysfs(mic->name, "log_buf_len", log_buf); |
10002 |
++ mpsslog("%s: log_buf_len: %s\n", mic->name, log_buf); |
10003 |
++ munmap(map, len); |
10004 |
++ close(fd); |
10005 |
++} |
10006 |
++ |
10007 |
++static void init_mic(struct mic_info *mic); |
10008 |
++ |
10009 |
++static void |
10010 |
++change_virtblk_backend(int x, siginfo_t *siginfo, void *p) |
10011 |
++{ |
10012 |
++ struct mic_info *mic; |
10013 |
++ |
10014 |
++ for (mic = mic_list.next; mic != NULL; mic = mic->next) |
10015 |
++ mic->mic_virtblk.signaled = 1/* true */; |
10016 |
++} |
10017 |
++ |
10018 |
++static void |
10019 |
++init_mic(struct mic_info *mic) |
10020 |
++{ |
10021 |
++ struct sigaction ignore = { |
10022 |
++ .sa_flags = 0, |
10023 |
++ .sa_handler = SIG_IGN |
10024 |
++ }; |
10025 |
++ struct sigaction act = { |
10026 |
++ .sa_flags = SA_SIGINFO, |
10027 |
++ .sa_sigaction = change_virtblk_backend, |
10028 |
++ }; |
10029 |
++ char buffer[PATH_MAX]; |
10030 |
++ int err; |
10031 |
++ |
10032 |
++ /* |
10033 |
++ * Currently, one virtio block device is supported for each MIC card |
10034 |
++ * at a time. Any user (or test) can send a SIGUSR1 to the MIC daemon. |
10035 |
++ * The signal informs the virtio block backend about a change in the |
10036 |
++ * configuration file which specifies the virtio backend file name on |
10037 |
++ * the host. Virtio block backend then re-reads the configuration file |
10038 |
++ * and switches to the new block device. This signalling mechanism may |
10039 |
++ * not be required once multiple virtio block devices are supported by |
10040 |
++ * the MIC daemon. |
10041 |
++ */ |
10042 |
++ sigaction(SIGUSR1, &ignore, NULL); |
10043 |
++ |
10044 |
++ mic->pid = fork(); |
10045 |
++ switch (mic->pid) { |
10046 |
++ case 0: |
10047 |
++ set_log_buf_info(mic); |
10048 |
++ set_cmdline(mic); |
10049 |
++ add_virtio_device(mic, &virtcons_dev_page.dd); |
10050 |
++ add_virtio_device(mic, &virtnet_dev_page.dd); |
10051 |
++ err = pthread_create(&mic->mic_console.console_thread, NULL, |
10052 |
++ virtio_console, mic); |
10053 |
++ if (err) |
10054 |
++ mpsslog("%s virtcons pthread_create failed %s\n", |
10055 |
++ mic->name, strerror(err)); |
10056 |
++ err = pthread_create(&mic->mic_net.net_thread, NULL, |
10057 |
++ virtio_net, mic); |
10058 |
++ if (err) |
10059 |
++ mpsslog("%s virtnet pthread_create failed %s\n", |
10060 |
++ mic->name, strerror(err)); |
10061 |
++ err = pthread_create(&mic->mic_virtblk.block_thread, NULL, |
10062 |
++ virtio_block, mic); |
10063 |
++ if (err) |
10064 |
++ mpsslog("%s virtblk pthread_create failed %s\n", |
10065 |
++ mic->name, strerror(err)); |
10066 |
++ sigemptyset(&act.sa_mask); |
10067 |
++ err = sigaction(SIGUSR1, &act, NULL); |
10068 |
++ if (err) |
10069 |
++ mpsslog("%s sigaction SIGUSR1 failed %s\n", |
10070 |
++ mic->name, strerror(errno)); |
10071 |
++ while (1) |
10072 |
++ sleep(60); |
10073 |
++ case -1: |
10074 |
++ mpsslog("fork failed MIC name %s id %d errno %d\n", |
10075 |
++ mic->name, mic->id, errno); |
10076 |
++ break; |
10077 |
++ default: |
10078 |
++ if (mic->restart) { |
10079 |
++ snprintf(buffer, PATH_MAX, "boot"); |
10080 |
++ setsysfs(mic->name, "state", buffer); |
10081 |
++ mpsslog("%s restarting mic %d\n", |
10082 |
++ mic->name, mic->restart); |
10083 |
++ mic->restart = 0; |
10084 |
++ } |
10085 |
++ pthread_create(&mic->config_thread, NULL, mic_config, mic); |
10086 |
++ } |
10087 |
++} |
10088 |
++ |
10089 |
++static void |
10090 |
++start_daemon(void) |
10091 |
++{ |
10092 |
++ struct mic_info *mic; |
10093 |
++ |
10094 |
++ for (mic = mic_list.next; mic != NULL; mic = mic->next) |
10095 |
++ init_mic(mic); |
10096 |
++ |
10097 |
++ while (1) |
10098 |
++ sleep(60); |
10099 |
++} |
10100 |
++ |
10101 |
++static int |
10102 |
++init_mic_list(void) |
10103 |
++{ |
10104 |
++ struct mic_info *mic = &mic_list; |
10105 |
++ struct dirent *file; |
10106 |
++ DIR *dp; |
10107 |
++ int cnt = 0; |
10108 |
++ |
10109 |
++ dp = opendir(MICSYSFSDIR); |
10110 |
++ if (!dp) |
10111 |
++ return 0; |
10112 |
++ |
10113 |
++ while ((file = readdir(dp)) != NULL) { |
10114 |
++ if (!strncmp(file->d_name, "mic", 3)) { |
10115 |
++ mic->next = calloc(1, sizeof(struct mic_info)); |
10116 |
++ if (mic->next) { |
10117 |
++ mic = mic->next; |
10118 |
++ mic->id = atoi(&file->d_name[3]); |
10119 |
++ mic->name = malloc(strlen(file->d_name) + 16); |
10120 |
++ if (mic->name) |
10121 |
++ strcpy(mic->name, file->d_name); |
10122 |
++ mpsslog("MIC name %s id %d\n", mic->name, |
10123 |
++ mic->id); |
10124 |
++ cnt++; |
10125 |
++ } |
10126 |
++ } |
10127 |
++ } |
10128 |
++ |
10129 |
++ closedir(dp); |
10130 |
++ return cnt; |
10131 |
++} |
10132 |
++ |
10133 |
++void |
10134 |
++mpsslog(char *format, ...) |
10135 |
++{ |
10136 |
++ va_list args; |
10137 |
++ char buffer[4096]; |
10138 |
++ char ts[52], *ts1; |
10139 |
++ time_t t; |
10140 |
++ |
10141 |
++ if (logfp == NULL) |
10142 |
++ return; |
10143 |
++ |
10144 |
++ va_start(args, format); |
10145 |
++ vsprintf(buffer, format, args); |
10146 |
++ va_end(args); |
10147 |
++ |
10148 |
++ time(&t); |
10149 |
++ ts1 = ctime_r(&t, ts); |
10150 |
++ ts1[strlen(ts1) - 1] = '\0'; |
10151 |
++ fprintf(logfp, "%s: %s", ts1, buffer); |
10152 |
++ |
10153 |
++ fflush(logfp); |
10154 |
++} |
10155 |
++ |
10156 |
++int |
10157 |
++main(int argc, char *argv[]) |
10158 |
++{ |
10159 |
++ int cnt; |
10160 |
++ pid_t pid; |
10161 |
++ |
10162 |
++ myname = argv[0]; |
10163 |
++ |
10164 |
++ logfp = fopen(LOGFILE_NAME, "a+"); |
10165 |
++ if (!logfp) { |
10166 |
++ fprintf(stderr, "cannot open logfile '%s'\n", LOGFILE_NAME); |
10167 |
++ exit(1); |
10168 |
++ } |
10169 |
++ pid = fork(); |
10170 |
++ switch (pid) { |
10171 |
++ case 0: |
10172 |
++ break; |
10173 |
++ case -1: |
10174 |
++ exit(2); |
10175 |
++ default: |
10176 |
++ exit(0); |
10177 |
++ } |
10178 |
++ |
10179 |
++ mpsslog("MIC Daemon start\n"); |
10180 |
++ |
10181 |
++ cnt = init_mic_list(); |
10182 |
++ if (cnt == 0) { |
10183 |
++ mpsslog("MIC module not loaded\n"); |
10184 |
++ exit(3); |
10185 |
++ } |
10186 |
++ mpsslog("MIC found %d devices\n", cnt); |
10187 |
++ |
10188 |
++ start_daemon(); |
10189 |
++ |
10190 |
++ exit(0); |
10191 |
++} |
10192 |
+diff --git a/samples/mic/mpssd/mpssd.h b/samples/mic/mpssd/mpssd.h |
10193 |
+new file mode 100644 |
10194 |
+index 000000000000..f5f18b15d9a0 |
10195 |
+--- /dev/null |
10196 |
++++ b/samples/mic/mpssd/mpssd.h |
10197 |
+@@ -0,0 +1,102 @@ |
10198 |
++/* |
10199 |
++ * Intel MIC Platform Software Stack (MPSS) |
10200 |
++ * |
10201 |
++ * Copyright(c) 2013 Intel Corporation. |
10202 |
++ * |
10203 |
++ * This program is free software; you can redistribute it and/or modify |
10204 |
++ * it under the terms of the GNU General Public License, version 2, as |
10205 |
++ * published by the Free Software Foundation. |
10206 |
++ * |
10207 |
++ * This program is distributed in the hope that it will be useful, but |
10208 |
++ * WITHOUT ANY WARRANTY; without even the implied warranty of |
10209 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
10210 |
++ * General Public License for more details. |
10211 |
++ * |
10212 |
++ * The full GNU General Public License is included in this distribution in |
10213 |
++ * the file called "COPYING". |
10214 |
++ * |
10215 |
++ * Intel MIC User Space Tools. |
10216 |
++ */ |
10217 |
++#ifndef _MPSSD_H_ |
10218 |
++#define _MPSSD_H_ |
10219 |
++ |
10220 |
++#include <stdio.h> |
10221 |
++#include <stdlib.h> |
10222 |
++#include <string.h> |
10223 |
++#include <fcntl.h> |
10224 |
++#include <unistd.h> |
10225 |
++#include <dirent.h> |
10226 |
++#include <libgen.h> |
10227 |
++#include <pthread.h> |
10228 |
++#include <stdarg.h> |
10229 |
++#include <time.h> |
10230 |
++#include <errno.h> |
10231 |
++#include <sys/dir.h> |
10232 |
++#include <sys/ioctl.h> |
10233 |
++#include <sys/poll.h> |
10234 |
++#include <sys/types.h> |
10235 |
++#include <sys/socket.h> |
10236 |
++#include <sys/stat.h> |
10237 |
++#include <sys/types.h> |
10238 |
++#include <sys/mman.h> |
10239 |
++#include <sys/utsname.h> |
10240 |
++#include <sys/wait.h> |
10241 |
++#include <netinet/in.h> |
10242 |
++#include <arpa/inet.h> |
10243 |
++#include <netdb.h> |
10244 |
++#include <pthread.h> |
10245 |
++#include <signal.h> |
10246 |
++#include <limits.h> |
10247 |
++#include <syslog.h> |
10248 |
++#include <getopt.h> |
10249 |
++#include <net/if.h> |
10250 |
++#include <linux/if_tun.h> |
10251 |
++#include <linux/if_tun.h> |
10252 |
++#include <linux/virtio_ids.h> |
10253 |
++ |
10254 |
++#define MICSYSFSDIR "/sys/class/mic" |
10255 |
++#define LOGFILE_NAME "/var/log/mpssd" |
10256 |
++#define PAGE_SIZE 4096 |
10257 |
++ |
10258 |
++struct mic_console_info { |
10259 |
++ pthread_t console_thread; |
10260 |
++ int virtio_console_fd; |
10261 |
++ void *console_dp; |
10262 |
++}; |
10263 |
++ |
10264 |
++struct mic_net_info { |
10265 |
++ pthread_t net_thread; |
10266 |
++ int virtio_net_fd; |
10267 |
++ int tap_fd; |
10268 |
++ void *net_dp; |
10269 |
++}; |
10270 |
++ |
10271 |
++struct mic_virtblk_info { |
10272 |
++ pthread_t block_thread; |
10273 |
++ int virtio_block_fd; |
10274 |
++ void *block_dp; |
10275 |
++ volatile sig_atomic_t signaled; |
10276 |
++ char *backend_file; |
10277 |
++ int backend; |
10278 |
++ void *backend_addr; |
10279 |
++ long backend_size; |
10280 |
++}; |
10281 |
++ |
10282 |
++struct mic_info { |
10283 |
++ int id; |
10284 |
++ char *name; |
10285 |
++ pthread_t config_thread; |
10286 |
++ pid_t pid; |
10287 |
++ struct mic_console_info mic_console; |
10288 |
++ struct mic_net_info mic_net; |
10289 |
++ struct mic_virtblk_info mic_virtblk; |
10290 |
++ int restart; |
10291 |
++ int boot_on_resume; |
10292 |
++ struct mic_info *next; |
10293 |
++}; |
10294 |
++ |
10295 |
++__attribute__((format(printf, 1, 2))) |
10296 |
++void mpsslog(char *format, ...); |
10297 |
++char *readsysfs(char *dir, char *entry); |
10298 |
++int setsysfs(char *dir, char *entry, char *value); |
10299 |
++#endif |
10300 |
+diff --git a/samples/mic/mpssd/sysfs.c b/samples/mic/mpssd/sysfs.c |
10301 |
+new file mode 100644 |
10302 |
+index 000000000000..8dd326936083 |
10303 |
+--- /dev/null |
10304 |
++++ b/samples/mic/mpssd/sysfs.c |
10305 |
+@@ -0,0 +1,102 @@ |
10306 |
++/* |
10307 |
++ * Intel MIC Platform Software Stack (MPSS) |
10308 |
++ * |
10309 |
++ * Copyright(c) 2013 Intel Corporation. |
10310 |
++ * |
10311 |
++ * This program is free software; you can redistribute it and/or modify |
10312 |
++ * it under the terms of the GNU General Public License, version 2, as |
10313 |
++ * published by the Free Software Foundation. |
10314 |
++ * |
10315 |
++ * This program is distributed in the hope that it will be useful, but |
10316 |
++ * WITHOUT ANY WARRANTY; without even the implied warranty of |
10317 |
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
10318 |
++ * General Public License for more details. |
10319 |
++ * |
10320 |
++ * The full GNU General Public License is included in this distribution in |
10321 |
++ * the file called "COPYING". |
10322 |
++ * |
10323 |
++ * Intel MIC User Space Tools. |
10324 |
++ */ |
10325 |
++ |
10326 |
++#include "mpssd.h" |
10327 |
++ |
10328 |
++#define PAGE_SIZE 4096 |
10329 |
++ |
10330 |
++char * |
10331 |
++readsysfs(char *dir, char *entry) |
10332 |
++{ |
10333 |
++ char filename[PATH_MAX]; |
10334 |
++ char value[PAGE_SIZE]; |
10335 |
++ char *string = NULL; |
10336 |
++ int fd; |
10337 |
++ int len; |
10338 |
++ |
10339 |
++ if (dir == NULL) |
10340 |
++ snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry); |
10341 |
++ else |
10342 |
++ snprintf(filename, PATH_MAX, |
10343 |
++ "%s/%s/%s", MICSYSFSDIR, dir, entry); |
10344 |
++ |
10345 |
++ fd = open(filename, O_RDONLY); |
10346 |
++ if (fd < 0) { |
10347 |
++ mpsslog("Failed to open sysfs entry '%s': %s\n", |
10348 |
++ filename, strerror(errno)); |
10349 |
++ return NULL; |
10350 |
++ } |
10351 |
++ |
10352 |
++ len = read(fd, value, sizeof(value)); |
10353 |
++ if (len < 0) { |
10354 |
++ mpsslog("Failed to read sysfs entry '%s': %s\n", |
10355 |
++ filename, strerror(errno)); |
10356 |
++ goto readsys_ret; |
10357 |
++ } |
10358 |
++ if (len == 0) |
10359 |
++ goto readsys_ret; |
10360 |
++ |
10361 |
++ value[len - 1] = '\0'; |
10362 |
++ |
10363 |
++ string = malloc(strlen(value) + 1); |
10364 |
++ if (string) |
10365 |
++ strcpy(string, value); |
10366 |
++ |
10367 |
++readsys_ret: |
10368 |
++ close(fd); |
10369 |
++ return string; |
10370 |
++} |
10371 |
++ |
10372 |
++int |
10373 |
++setsysfs(char *dir, char *entry, char *value) |
10374 |
++{ |
10375 |
++ char filename[PATH_MAX]; |
10376 |
++ char *oldvalue; |
10377 |
++ int fd, ret = 0; |
10378 |
++ |
10379 |
++ if (dir == NULL) |
10380 |
++ snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry); |
10381 |
++ else |
10382 |
++ snprintf(filename, PATH_MAX, "%s/%s/%s", |
10383 |
++ MICSYSFSDIR, dir, entry); |
10384 |
++ |
10385 |
++ oldvalue = readsysfs(dir, entry); |
10386 |
++ |
10387 |
++ fd = open(filename, O_RDWR); |
10388 |
++ if (fd < 0) { |
10389 |
++ ret = errno; |
10390 |
++ mpsslog("Failed to open sysfs entry '%s': %s\n", |
10391 |
++ filename, strerror(errno)); |
10392 |
++ goto done; |
10393 |
++ } |
10394 |
++ |
10395 |
++ if (!oldvalue || strcmp(value, oldvalue)) { |
10396 |
++ if (write(fd, value, strlen(value)) < 0) { |
10397 |
++ ret = errno; |
10398 |
++ mpsslog("Failed to write new sysfs entry '%s': %s\n", |
10399 |
++ filename, strerror(errno)); |
10400 |
++ } |
10401 |
++ } |
10402 |
++ close(fd); |
10403 |
++done: |
10404 |
++ if (oldvalue) |
10405 |
++ free(oldvalue); |
10406 |
++ return ret; |
10407 |
++} |
10408 |
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c |
10409 |
+index b1e455b47b82..be04b056c1bd 100644 |
10410 |
+--- a/security/selinux/hooks.c |
10411 |
++++ b/security/selinux/hooks.c |
10412 |
+@@ -5594,7 +5594,7 @@ static int selinux_setprocattr(struct task_struct *p, |
10413 |
+ return error; |
10414 |
+ |
10415 |
+ /* Obtain a SID for the context, if one was specified. */ |
10416 |
+- if (size && str[1] && str[1] != '\n') { |
10417 |
++ if (size && str[0] && str[0] != '\n') { |
10418 |
+ if (str[size-1] == '\n') { |
10419 |
+ str[size-1] = 0; |
10420 |
+ size--; |
10421 |
+diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c |
10422 |
+index e6d4ff9fd992..736c1ea8e31e 100644 |
10423 |
+--- a/sound/soc/codecs/cs4270.c |
10424 |
++++ b/sound/soc/codecs/cs4270.c |
10425 |
+@@ -148,11 +148,11 @@ SND_SOC_DAPM_OUTPUT("AOUTR"), |
10426 |
+ }; |
10427 |
+ |
10428 |
+ static const struct snd_soc_dapm_route cs4270_dapm_routes[] = { |
10429 |
+- { "Capture", NULL, "AINA" }, |
10430 |
+- { "Capture", NULL, "AINB" }, |
10431 |
++ { "Capture", NULL, "AINL" }, |
10432 |
++ { "Capture", NULL, "AINR" }, |
10433 |
+ |
10434 |
+- { "AOUTA", NULL, "Playback" }, |
10435 |
+- { "AOUTB", NULL, "Playback" }, |
10436 |
++ { "AOUTL", NULL, "Playback" }, |
10437 |
++ { "AOUTR", NULL, "Playback" }, |
10438 |
+ }; |
10439 |
+ |
10440 |
+ /** |
10441 |
+diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h |
10442 |
+index 0051077a7b9d..814a118d2ef6 100644 |
10443 |
+--- a/sound/usb/quirks-table.h |
10444 |
++++ b/sound/usb/quirks-table.h |
10445 |
+@@ -2959,6 +2959,23 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), |
10446 |
+ } |
10447 |
+ }, |
10448 |
+ |
10449 |
++/* Syntek STK1160 */ |
10450 |
++{ |
10451 |
++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | |
10452 |
++ USB_DEVICE_ID_MATCH_INT_CLASS | |
10453 |
++ USB_DEVICE_ID_MATCH_INT_SUBCLASS, |
10454 |
++ .idVendor = 0x05e1, |
10455 |
++ .idProduct = 0x0408, |
10456 |
++ .bInterfaceClass = USB_CLASS_AUDIO, |
10457 |
++ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, |
10458 |
++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { |
10459 |
++ .vendor_name = "Syntek", |
10460 |
++ .product_name = "STK1160", |
10461 |
++ .ifnum = QUIRK_ANY_INTERFACE, |
10462 |
++ .type = QUIRK_AUDIO_ALIGN_TRANSFER |
10463 |
++ } |
10464 |
++}, |
10465 |
++ |
10466 |
+ /* Digidesign Mbox */ |
10467 |
+ { |
10468 |
+ /* Thanks to Clemens Ladisch <clemens@×××××××.de> */ |
10469 |
+diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl |
10470 |
+index dcb1e9ac949c..d9d10f3c8ca3 100755 |
10471 |
+--- a/tools/testing/ktest/ktest.pl |
10472 |
++++ b/tools/testing/ktest/ktest.pl |
10473 |
+@@ -2450,7 +2450,7 @@ sub do_run_test { |
10474 |
+ } |
10475 |
+ |
10476 |
+ waitpid $child_pid, 0; |
10477 |
+- $child_exit = $?; |
10478 |
++ $child_exit = $? >> 8; |
10479 |
+ |
10480 |
+ if (!$bug && $in_bisect) { |
10481 |
+ if (defined($bisect_ret_good)) { |