Contents of /trunk/kernel-alx/patches-4.4/0152-4.4.53-all-fixes.patch
Parent Directory | Revision Log
Revision 2888 -
(show annotations)
(download)
Mon Mar 27 13:49:25 2017 UTC (7 years, 6 months ago) by niro
File size: 233641 byte(s)
Mon Mar 27 13:49:25 2017 UTC (7 years, 6 months ago) by niro
File size: 233641 byte(s)
linux-4.4.53
1 | diff --git a/Documentation/Makefile b/Documentation/Makefile |
2 | index bc0548201755..fc759598c4c9 100644 |
3 | --- a/Documentation/Makefile |
4 | +++ b/Documentation/Makefile |
5 | @@ -1,4 +1,4 @@ |
6 | subdir-y := accounting auxdisplay blackfin connector \ |
7 | - filesystems filesystems ia64 laptops mic misc-devices \ |
8 | + filesystems filesystems ia64 laptops misc-devices \ |
9 | networking pcmcia prctl ptp spi timers vDSO video4linux \ |
10 | watchdog |
11 | diff --git a/Documentation/mic/Makefile b/Documentation/mic/Makefile |
12 | deleted file mode 100644 |
13 | index a191d453badf..000000000000 |
14 | --- a/Documentation/mic/Makefile |
15 | +++ /dev/null |
16 | @@ -1 +0,0 @@ |
17 | -subdir-y := mpssd |
18 | diff --git a/Documentation/mic/mpssd/.gitignore b/Documentation/mic/mpssd/.gitignore |
19 | deleted file mode 100644 |
20 | index 8b7c72f07c92..000000000000 |
21 | --- a/Documentation/mic/mpssd/.gitignore |
22 | +++ /dev/null |
23 | @@ -1 +0,0 @@ |
24 | -mpssd |
25 | diff --git a/Documentation/mic/mpssd/Makefile b/Documentation/mic/mpssd/Makefile |
26 | deleted file mode 100644 |
27 | index 06871b0c08a6..000000000000 |
28 | --- a/Documentation/mic/mpssd/Makefile |
29 | +++ /dev/null |
30 | @@ -1,21 +0,0 @@ |
31 | -ifndef CROSS_COMPILE |
32 | -# List of programs to build |
33 | -hostprogs-$(CONFIG_X86_64) := mpssd |
34 | - |
35 | -mpssd-objs := mpssd.o sysfs.o |
36 | - |
37 | -# Tell kbuild to always build the programs |
38 | -always := $(hostprogs-y) |
39 | - |
40 | -HOSTCFLAGS += -I$(objtree)/usr/include -I$(srctree)/tools/include |
41 | - |
42 | -ifdef DEBUG |
43 | -HOSTCFLAGS += -DDEBUG=$(DEBUG) |
44 | -endif |
45 | - |
46 | -HOSTLOADLIBES_mpssd := -lpthread |
47 | - |
48 | -install: |
49 | - install mpssd /usr/sbin/mpssd |
50 | - install micctrl /usr/sbin/micctrl |
51 | -endif |
52 | diff --git a/Documentation/mic/mpssd/micctrl b/Documentation/mic/mpssd/micctrl |
53 | deleted file mode 100755 |
54 | index 8f2629b41c5f..000000000000 |
55 | --- a/Documentation/mic/mpssd/micctrl |
56 | +++ /dev/null |
57 | @@ -1,173 +0,0 @@ |
58 | -#!/bin/bash |
59 | -# Intel MIC Platform Software Stack (MPSS) |
60 | -# |
61 | -# Copyright(c) 2013 Intel Corporation. |
62 | -# |
63 | -# This program is free software; you can redistribute it and/or modify |
64 | -# it under the terms of the GNU General Public License, version 2, as |
65 | -# published by the Free Software Foundation. |
66 | -# |
67 | -# This program is distributed in the hope that it will be useful, but |
68 | -# WITHOUT ANY WARRANTY; without even the implied warranty of |
69 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
70 | -# General Public License for more details. |
71 | -# |
72 | -# The full GNU General Public License is included in this distribution in |
73 | -# the file called "COPYING". |
74 | -# |
75 | -# Intel MIC User Space Tools. |
76 | -# |
77 | -# micctrl - Controls MIC boot/start/stop. |
78 | -# |
79 | -# chkconfig: 2345 95 05 |
80 | -# description: start MPSS stack processing. |
81 | -# |
82 | -### BEGIN INIT INFO |
83 | -# Provides: micctrl |
84 | -### END INIT INFO |
85 | - |
86 | -# Source function library. |
87 | -. /etc/init.d/functions |
88 | - |
89 | -sysfs="/sys/class/mic" |
90 | - |
91 | -_status() |
92 | -{ |
93 | - f=$sysfs/$1 |
94 | - echo -e $1 state: "`cat $f/state`" shutdown_status: "`cat $f/shutdown_status`" |
95 | -} |
96 | - |
97 | -status() |
98 | -{ |
99 | - if [ "`echo $1 | head -c3`" == "mic" ]; then |
100 | - _status $1 |
101 | - return $? |
102 | - fi |
103 | - for f in $sysfs/* |
104 | - do |
105 | - _status `basename $f` |
106 | - RETVAL=$? |
107 | - [ $RETVAL -ne 0 ] && return $RETVAL |
108 | - done |
109 | - return 0 |
110 | -} |
111 | - |
112 | -_reset() |
113 | -{ |
114 | - f=$sysfs/$1 |
115 | - echo reset > $f/state |
116 | -} |
117 | - |
118 | -reset() |
119 | -{ |
120 | - if [ "`echo $1 | head -c3`" == "mic" ]; then |
121 | - _reset $1 |
122 | - return $? |
123 | - fi |
124 | - for f in $sysfs/* |
125 | - do |
126 | - _reset `basename $f` |
127 | - RETVAL=$? |
128 | - [ $RETVAL -ne 0 ] && return $RETVAL |
129 | - done |
130 | - return 0 |
131 | -} |
132 | - |
133 | -_boot() |
134 | -{ |
135 | - f=$sysfs/$1 |
136 | - echo "linux" > $f/bootmode |
137 | - echo "mic/uos.img" > $f/firmware |
138 | - echo "mic/$1.image" > $f/ramdisk |
139 | - echo "boot" > $f/state |
140 | -} |
141 | - |
142 | -boot() |
143 | -{ |
144 | - if [ "`echo $1 | head -c3`" == "mic" ]; then |
145 | - _boot $1 |
146 | - return $? |
147 | - fi |
148 | - for f in $sysfs/* |
149 | - do |
150 | - _boot `basename $f` |
151 | - RETVAL=$? |
152 | - [ $RETVAL -ne 0 ] && return $RETVAL |
153 | - done |
154 | - return 0 |
155 | -} |
156 | - |
157 | -_shutdown() |
158 | -{ |
159 | - f=$sysfs/$1 |
160 | - echo shutdown > $f/state |
161 | -} |
162 | - |
163 | -shutdown() |
164 | -{ |
165 | - if [ "`echo $1 | head -c3`" == "mic" ]; then |
166 | - _shutdown $1 |
167 | - return $? |
168 | - fi |
169 | - for f in $sysfs/* |
170 | - do |
171 | - _shutdown `basename $f` |
172 | - RETVAL=$? |
173 | - [ $RETVAL -ne 0 ] && return $RETVAL |
174 | - done |
175 | - return 0 |
176 | -} |
177 | - |
178 | -_wait() |
179 | -{ |
180 | - f=$sysfs/$1 |
181 | - while [ "`cat $f/state`" != "offline" -a "`cat $f/state`" != "online" ] |
182 | - do |
183 | - sleep 1 |
184 | - echo -e "Waiting for $1 to go offline" |
185 | - done |
186 | -} |
187 | - |
188 | -wait() |
189 | -{ |
190 | - if [ "`echo $1 | head -c3`" == "mic" ]; then |
191 | - _wait $1 |
192 | - return $? |
193 | - fi |
194 | - # Wait for the cards to go offline |
195 | - for f in $sysfs/* |
196 | - do |
197 | - _wait `basename $f` |
198 | - RETVAL=$? |
199 | - [ $RETVAL -ne 0 ] && return $RETVAL |
200 | - done |
201 | - return 0 |
202 | -} |
203 | - |
204 | -if [ ! -d "$sysfs" ]; then |
205 | - echo -e $"Module unloaded " |
206 | - exit 3 |
207 | -fi |
208 | - |
209 | -case $1 in |
210 | - -s) |
211 | - status $2 |
212 | - ;; |
213 | - -r) |
214 | - reset $2 |
215 | - ;; |
216 | - -b) |
217 | - boot $2 |
218 | - ;; |
219 | - -S) |
220 | - shutdown $2 |
221 | - ;; |
222 | - -w) |
223 | - wait $2 |
224 | - ;; |
225 | - *) |
226 | - echo $"Usage: $0 {-s (status) |-r (reset) |-b (boot) |-S (shutdown) |-w (wait)}" |
227 | - exit 2 |
228 | -esac |
229 | - |
230 | -exit $? |
231 | diff --git a/Documentation/mic/mpssd/mpss b/Documentation/mic/mpssd/mpss |
232 | deleted file mode 100755 |
233 | index 09ea90931649..000000000000 |
234 | --- a/Documentation/mic/mpssd/mpss |
235 | +++ /dev/null |
236 | @@ -1,200 +0,0 @@ |
237 | -#!/bin/bash |
238 | -# Intel MIC Platform Software Stack (MPSS) |
239 | -# |
240 | -# Copyright(c) 2013 Intel Corporation. |
241 | -# |
242 | -# This program is free software; you can redistribute it and/or modify |
243 | -# it under the terms of the GNU General Public License, version 2, as |
244 | -# published by the Free Software Foundation. |
245 | -# |
246 | -# This program is distributed in the hope that it will be useful, but |
247 | -# WITHOUT ANY WARRANTY; without even the implied warranty of |
248 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
249 | -# General Public License for more details. |
250 | -# |
251 | -# The full GNU General Public License is included in this distribution in |
252 | -# the file called "COPYING". |
253 | -# |
254 | -# Intel MIC User Space Tools. |
255 | -# |
256 | -# mpss Start mpssd. |
257 | -# |
258 | -# chkconfig: 2345 95 05 |
259 | -# description: start MPSS stack processing. |
260 | -# |
261 | -### BEGIN INIT INFO |
262 | -# Provides: mpss |
263 | -# Required-Start: |
264 | -# Required-Stop: |
265 | -# Short-Description: MPSS stack control |
266 | -# Description: MPSS stack control |
267 | -### END INIT INFO |
268 | - |
269 | -# Source function library. |
270 | -. /etc/init.d/functions |
271 | - |
272 | -exec=/usr/sbin/mpssd |
273 | -sysfs="/sys/class/mic" |
274 | -mic_modules="mic_host mic_x100_dma scif" |
275 | - |
276 | -start() |
277 | -{ |
278 | - [ -x $exec ] || exit 5 |
279 | - |
280 | - if [ "`ps -e | awk '{print $4}' | grep mpssd | head -1`" = "mpssd" ]; then |
281 | - echo -e $"MPSSD already running! " |
282 | - success |
283 | - echo |
284 | - return 0 |
285 | - fi |
286 | - |
287 | - echo -e $"Starting MPSS Stack" |
288 | - echo -e $"Loading MIC drivers:" $mic_modules |
289 | - |
290 | - modprobe -a $mic_modules |
291 | - RETVAL=$? |
292 | - if [ $RETVAL -ne 0 ]; then |
293 | - failure |
294 | - echo |
295 | - return $RETVAL |
296 | - fi |
297 | - |
298 | - # Start the daemon |
299 | - echo -n $"Starting MPSSD " |
300 | - $exec |
301 | - RETVAL=$? |
302 | - if [ $RETVAL -ne 0 ]; then |
303 | - failure |
304 | - echo |
305 | - return $RETVAL |
306 | - fi |
307 | - success |
308 | - echo |
309 | - |
310 | - sleep 5 |
311 | - |
312 | - # Boot the cards |
313 | - micctrl -b |
314 | - |
315 | - # Wait till ping works |
316 | - for f in $sysfs/* |
317 | - do |
318 | - count=100 |
319 | - ipaddr=`cat $f/cmdline` |
320 | - ipaddr=${ipaddr#*address,} |
321 | - ipaddr=`echo $ipaddr | cut -d, -f1 | cut -d\; -f1` |
322 | - while [ $count -ge 0 ] |
323 | - do |
324 | - echo -e "Pinging "`basename $f`" " |
325 | - ping -c 1 $ipaddr &> /dev/null |
326 | - RETVAL=$? |
327 | - if [ $RETVAL -eq 0 ]; then |
328 | - success |
329 | - break |
330 | - fi |
331 | - sleep 1 |
332 | - count=`expr $count - 1` |
333 | - done |
334 | - [ $RETVAL -ne 0 ] && failure || success |
335 | - echo |
336 | - done |
337 | - return $RETVAL |
338 | -} |
339 | - |
340 | -stop() |
341 | -{ |
342 | - echo -e $"Shutting down MPSS Stack: " |
343 | - |
344 | - # Bail out if module is unloaded |
345 | - if [ ! -d "$sysfs" ]; then |
346 | - echo -n $"Module unloaded " |
347 | - success |
348 | - echo |
349 | - return 0 |
350 | - fi |
351 | - |
352 | - # Shut down the cards. |
353 | - micctrl -S |
354 | - |
355 | - # Wait for the cards to go offline |
356 | - for f in $sysfs/* |
357 | - do |
358 | - while [ "`cat $f/state`" != "ready" ] |
359 | - do |
360 | - sleep 1 |
361 | - echo -e "Waiting for "`basename $f`" to become ready" |
362 | - done |
363 | - done |
364 | - |
365 | - # Display the status of the cards |
366 | - micctrl -s |
367 | - |
368 | - # Kill MPSSD now |
369 | - echo -n $"Killing MPSSD" |
370 | - killall -9 mpssd 2>/dev/null |
371 | - RETVAL=$? |
372 | - [ $RETVAL -ne 0 ] && failure || success |
373 | - echo |
374 | - return $RETVAL |
375 | -} |
376 | - |
377 | -restart() |
378 | -{ |
379 | - stop |
380 | - sleep 5 |
381 | - start |
382 | -} |
383 | - |
384 | -status() |
385 | -{ |
386 | - micctrl -s |
387 | - if [ "`ps -e | awk '{print $4}' | grep mpssd | head -n 1`" = "mpssd" ]; then |
388 | - echo "mpssd is running" |
389 | - else |
390 | - echo "mpssd is stopped" |
391 | - fi |
392 | - return 0 |
393 | -} |
394 | - |
395 | -unload() |
396 | -{ |
397 | - if [ ! -d "$sysfs" ]; then |
398 | - echo -n $"No MIC_HOST Module: " |
399 | - success |
400 | - echo |
401 | - return |
402 | - fi |
403 | - |
404 | - stop |
405 | - |
406 | - sleep 5 |
407 | - echo -n $"Removing MIC drivers:" $mic_modules |
408 | - modprobe -r $mic_modules |
409 | - RETVAL=$? |
410 | - [ $RETVAL -ne 0 ] && failure || success |
411 | - echo |
412 | - return $RETVAL |
413 | -} |
414 | - |
415 | -case $1 in |
416 | - start) |
417 | - start |
418 | - ;; |
419 | - stop) |
420 | - stop |
421 | - ;; |
422 | - restart) |
423 | - restart |
424 | - ;; |
425 | - status) |
426 | - status |
427 | - ;; |
428 | - unload) |
429 | - unload |
430 | - ;; |
431 | - *) |
432 | - echo $"Usage: $0 {start|stop|restart|status|unload}" |
433 | - exit 2 |
434 | -esac |
435 | - |
436 | -exit $? |
437 | diff --git a/Documentation/mic/mpssd/mpssd.c b/Documentation/mic/mpssd/mpssd.c |
438 | deleted file mode 100644 |
439 | index c99a75968c01..000000000000 |
440 | --- a/Documentation/mic/mpssd/mpssd.c |
441 | +++ /dev/null |
442 | @@ -1,1826 +0,0 @@ |
443 | -/* |
444 | - * Intel MIC Platform Software Stack (MPSS) |
445 | - * |
446 | - * Copyright(c) 2013 Intel Corporation. |
447 | - * |
448 | - * This program is free software; you can redistribute it and/or modify |
449 | - * it under the terms of the GNU General Public License, version 2, as |
450 | - * published by the Free Software Foundation. |
451 | - * |
452 | - * This program is distributed in the hope that it will be useful, but |
453 | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
454 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
455 | - * General Public License for more details. |
456 | - * |
457 | - * The full GNU General Public License is included in this distribution in |
458 | - * the file called "COPYING". |
459 | - * |
460 | - * Intel MIC User Space Tools. |
461 | - */ |
462 | - |
463 | -#define _GNU_SOURCE |
464 | - |
465 | -#include <stdlib.h> |
466 | -#include <fcntl.h> |
467 | -#include <getopt.h> |
468 | -#include <assert.h> |
469 | -#include <unistd.h> |
470 | -#include <stdbool.h> |
471 | -#include <signal.h> |
472 | -#include <poll.h> |
473 | -#include <features.h> |
474 | -#include <sys/types.h> |
475 | -#include <sys/stat.h> |
476 | -#include <sys/mman.h> |
477 | -#include <sys/socket.h> |
478 | -#include <linux/virtio_ring.h> |
479 | -#include <linux/virtio_net.h> |
480 | -#include <linux/virtio_console.h> |
481 | -#include <linux/virtio_blk.h> |
482 | -#include <linux/version.h> |
483 | -#include "mpssd.h" |
484 | -#include <linux/mic_ioctl.h> |
485 | -#include <linux/mic_common.h> |
486 | -#include <tools/endian.h> |
487 | - |
488 | -static void *init_mic(void *arg); |
489 | - |
490 | -static FILE *logfp; |
491 | -static struct mic_info mic_list; |
492 | - |
493 | -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
494 | - |
495 | -#define min_t(type, x, y) ({ \ |
496 | - type __min1 = (x); \ |
497 | - type __min2 = (y); \ |
498 | - __min1 < __min2 ? __min1 : __min2; }) |
499 | - |
500 | -/* align addr on a size boundary - adjust address up/down if needed */ |
501 | -#define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1))) |
502 | -#define _ALIGN_UP(addr, size) _ALIGN_DOWN(addr + size - 1, size) |
503 | - |
504 | -/* align addr on a size boundary - adjust address up if needed */ |
505 | -#define _ALIGN(addr, size) _ALIGN_UP(addr, size) |
506 | - |
507 | -/* to align the pointer to the (next) page boundary */ |
508 | -#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) |
509 | - |
510 | -#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) |
511 | - |
512 | -#define GSO_ENABLED 1 |
513 | -#define MAX_GSO_SIZE (64 * 1024) |
514 | -#define ETH_H_LEN 14 |
515 | -#define MAX_NET_PKT_SIZE (_ALIGN_UP(MAX_GSO_SIZE + ETH_H_LEN, 64)) |
516 | -#define MIC_DEVICE_PAGE_END 0x1000 |
517 | - |
518 | -#ifndef VIRTIO_NET_HDR_F_DATA_VALID |
519 | -#define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */ |
520 | -#endif |
521 | - |
522 | -static struct { |
523 | - struct mic_device_desc dd; |
524 | - struct mic_vqconfig vqconfig[2]; |
525 | - __u32 host_features, guest_acknowledgements; |
526 | - struct virtio_console_config cons_config; |
527 | -} virtcons_dev_page = { |
528 | - .dd = { |
529 | - .type = VIRTIO_ID_CONSOLE, |
530 | - .num_vq = ARRAY_SIZE(virtcons_dev_page.vqconfig), |
531 | - .feature_len = sizeof(virtcons_dev_page.host_features), |
532 | - .config_len = sizeof(virtcons_dev_page.cons_config), |
533 | - }, |
534 | - .vqconfig[0] = { |
535 | - .num = htole16(MIC_VRING_ENTRIES), |
536 | - }, |
537 | - .vqconfig[1] = { |
538 | - .num = htole16(MIC_VRING_ENTRIES), |
539 | - }, |
540 | -}; |
541 | - |
542 | -static struct { |
543 | - struct mic_device_desc dd; |
544 | - struct mic_vqconfig vqconfig[2]; |
545 | - __u32 host_features, guest_acknowledgements; |
546 | - struct virtio_net_config net_config; |
547 | -} virtnet_dev_page = { |
548 | - .dd = { |
549 | - .type = VIRTIO_ID_NET, |
550 | - .num_vq = ARRAY_SIZE(virtnet_dev_page.vqconfig), |
551 | - .feature_len = sizeof(virtnet_dev_page.host_features), |
552 | - .config_len = sizeof(virtnet_dev_page.net_config), |
553 | - }, |
554 | - .vqconfig[0] = { |
555 | - .num = htole16(MIC_VRING_ENTRIES), |
556 | - }, |
557 | - .vqconfig[1] = { |
558 | - .num = htole16(MIC_VRING_ENTRIES), |
559 | - }, |
560 | -#if GSO_ENABLED |
561 | - .host_features = htole32( |
562 | - 1 << VIRTIO_NET_F_CSUM | |
563 | - 1 << VIRTIO_NET_F_GSO | |
564 | - 1 << VIRTIO_NET_F_GUEST_TSO4 | |
565 | - 1 << VIRTIO_NET_F_GUEST_TSO6 | |
566 | - 1 << VIRTIO_NET_F_GUEST_ECN), |
567 | -#else |
568 | - .host_features = 0, |
569 | -#endif |
570 | -}; |
571 | - |
572 | -static const char *mic_config_dir = "/etc/mpss"; |
573 | -static const char *virtblk_backend = "VIRTBLK_BACKEND"; |
574 | -static struct { |
575 | - struct mic_device_desc dd; |
576 | - struct mic_vqconfig vqconfig[1]; |
577 | - __u32 host_features, guest_acknowledgements; |
578 | - struct virtio_blk_config blk_config; |
579 | -} virtblk_dev_page = { |
580 | - .dd = { |
581 | - .type = VIRTIO_ID_BLOCK, |
582 | - .num_vq = ARRAY_SIZE(virtblk_dev_page.vqconfig), |
583 | - .feature_len = sizeof(virtblk_dev_page.host_features), |
584 | - .config_len = sizeof(virtblk_dev_page.blk_config), |
585 | - }, |
586 | - .vqconfig[0] = { |
587 | - .num = htole16(MIC_VRING_ENTRIES), |
588 | - }, |
589 | - .host_features = |
590 | - htole32(1<<VIRTIO_BLK_F_SEG_MAX), |
591 | - .blk_config = { |
592 | - .seg_max = htole32(MIC_VRING_ENTRIES - 2), |
593 | - .capacity = htole64(0), |
594 | - } |
595 | -}; |
596 | - |
597 | -static char *myname; |
598 | - |
599 | -static int |
600 | -tap_configure(struct mic_info *mic, char *dev) |
601 | -{ |
602 | - pid_t pid; |
603 | - char *ifargv[7]; |
604 | - char ipaddr[IFNAMSIZ]; |
605 | - int ret = 0; |
606 | - |
607 | - pid = fork(); |
608 | - if (pid == 0) { |
609 | - ifargv[0] = "ip"; |
610 | - ifargv[1] = "link"; |
611 | - ifargv[2] = "set"; |
612 | - ifargv[3] = dev; |
613 | - ifargv[4] = "up"; |
614 | - ifargv[5] = NULL; |
615 | - mpsslog("Configuring %s\n", dev); |
616 | - ret = execvp("ip", ifargv); |
617 | - if (ret < 0) { |
618 | - mpsslog("%s execvp failed errno %s\n", |
619 | - mic->name, strerror(errno)); |
620 | - return ret; |
621 | - } |
622 | - } |
623 | - if (pid < 0) { |
624 | - mpsslog("%s fork failed errno %s\n", |
625 | - mic->name, strerror(errno)); |
626 | - return ret; |
627 | - } |
628 | - |
629 | - ret = waitpid(pid, NULL, 0); |
630 | - if (ret < 0) { |
631 | - mpsslog("%s waitpid failed errno %s\n", |
632 | - mic->name, strerror(errno)); |
633 | - return ret; |
634 | - } |
635 | - |
636 | - snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id + 1); |
637 | - |
638 | - pid = fork(); |
639 | - if (pid == 0) { |
640 | - ifargv[0] = "ip"; |
641 | - ifargv[1] = "addr"; |
642 | - ifargv[2] = "add"; |
643 | - ifargv[3] = ipaddr; |
644 | - ifargv[4] = "dev"; |
645 | - ifargv[5] = dev; |
646 | - ifargv[6] = NULL; |
647 | - mpsslog("Configuring %s ipaddr %s\n", dev, ipaddr); |
648 | - ret = execvp("ip", ifargv); |
649 | - if (ret < 0) { |
650 | - mpsslog("%s execvp failed errno %s\n", |
651 | - mic->name, strerror(errno)); |
652 | - return ret; |
653 | - } |
654 | - } |
655 | - if (pid < 0) { |
656 | - mpsslog("%s fork failed errno %s\n", |
657 | - mic->name, strerror(errno)); |
658 | - return ret; |
659 | - } |
660 | - |
661 | - ret = waitpid(pid, NULL, 0); |
662 | - if (ret < 0) { |
663 | - mpsslog("%s waitpid failed errno %s\n", |
664 | - mic->name, strerror(errno)); |
665 | - return ret; |
666 | - } |
667 | - mpsslog("MIC name %s %s %d DONE!\n", |
668 | - mic->name, __func__, __LINE__); |
669 | - return 0; |
670 | -} |
671 | - |
672 | -static int tun_alloc(struct mic_info *mic, char *dev) |
673 | -{ |
674 | - struct ifreq ifr; |
675 | - int fd, err; |
676 | -#if GSO_ENABLED |
677 | - unsigned offload; |
678 | -#endif |
679 | - fd = open("/dev/net/tun", O_RDWR); |
680 | - if (fd < 0) { |
681 | - mpsslog("Could not open /dev/net/tun %s\n", strerror(errno)); |
682 | - goto done; |
683 | - } |
684 | - |
685 | - memset(&ifr, 0, sizeof(ifr)); |
686 | - |
687 | - ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR; |
688 | - if (*dev) |
689 | - strncpy(ifr.ifr_name, dev, IFNAMSIZ); |
690 | - |
691 | - err = ioctl(fd, TUNSETIFF, (void *)&ifr); |
692 | - if (err < 0) { |
693 | - mpsslog("%s %s %d TUNSETIFF failed %s\n", |
694 | - mic->name, __func__, __LINE__, strerror(errno)); |
695 | - close(fd); |
696 | - return err; |
697 | - } |
698 | -#if GSO_ENABLED |
699 | - offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_TSO_ECN; |
700 | - |
701 | - err = ioctl(fd, TUNSETOFFLOAD, offload); |
702 | - if (err < 0) { |
703 | - mpsslog("%s %s %d TUNSETOFFLOAD failed %s\n", |
704 | - mic->name, __func__, __LINE__, strerror(errno)); |
705 | - close(fd); |
706 | - return err; |
707 | - } |
708 | -#endif |
709 | - strcpy(dev, ifr.ifr_name); |
710 | - mpsslog("Created TAP %s\n", dev); |
711 | -done: |
712 | - return fd; |
713 | -} |
714 | - |
715 | -#define NET_FD_VIRTIO_NET 0 |
716 | -#define NET_FD_TUN 1 |
717 | -#define MAX_NET_FD 2 |
718 | - |
719 | -static void set_dp(struct mic_info *mic, int type, void *dp) |
720 | -{ |
721 | - switch (type) { |
722 | - case VIRTIO_ID_CONSOLE: |
723 | - mic->mic_console.console_dp = dp; |
724 | - return; |
725 | - case VIRTIO_ID_NET: |
726 | - mic->mic_net.net_dp = dp; |
727 | - return; |
728 | - case VIRTIO_ID_BLOCK: |
729 | - mic->mic_virtblk.block_dp = dp; |
730 | - return; |
731 | - } |
732 | - mpsslog("%s %s %d not found\n", mic->name, __func__, type); |
733 | - assert(0); |
734 | -} |
735 | - |
736 | -static void *get_dp(struct mic_info *mic, int type) |
737 | -{ |
738 | - switch (type) { |
739 | - case VIRTIO_ID_CONSOLE: |
740 | - return mic->mic_console.console_dp; |
741 | - case VIRTIO_ID_NET: |
742 | - return mic->mic_net.net_dp; |
743 | - case VIRTIO_ID_BLOCK: |
744 | - return mic->mic_virtblk.block_dp; |
745 | - } |
746 | - mpsslog("%s %s %d not found\n", mic->name, __func__, type); |
747 | - assert(0); |
748 | - return NULL; |
749 | -} |
750 | - |
751 | -static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type) |
752 | -{ |
753 | - struct mic_device_desc *d; |
754 | - int i; |
755 | - void *dp = get_dp(mic, type); |
756 | - |
757 | - for (i = sizeof(struct mic_bootparam); i < PAGE_SIZE; |
758 | - i += mic_total_desc_size(d)) { |
759 | - d = dp + i; |
760 | - |
761 | - /* End of list */ |
762 | - if (d->type == 0) |
763 | - break; |
764 | - |
765 | - if (d->type == -1) |
766 | - continue; |
767 | - |
768 | - mpsslog("%s %s d-> type %d d %p\n", |
769 | - mic->name, __func__, d->type, d); |
770 | - |
771 | - if (d->type == (__u8)type) |
772 | - return d; |
773 | - } |
774 | - mpsslog("%s %s %d not found\n", mic->name, __func__, type); |
775 | - return NULL; |
776 | -} |
777 | - |
778 | -/* See comments in vhost.c for explanation of next_desc() */ |
779 | -static unsigned next_desc(struct vring_desc *desc) |
780 | -{ |
781 | - unsigned int next; |
782 | - |
783 | - if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT)) |
784 | - return -1U; |
785 | - next = le16toh(desc->next); |
786 | - return next; |
787 | -} |
788 | - |
789 | -/* Sum up all the IOVEC length */ |
790 | -static ssize_t |
791 | -sum_iovec_len(struct mic_copy_desc *copy) |
792 | -{ |
793 | - ssize_t sum = 0; |
794 | - int i; |
795 | - |
796 | - for (i = 0; i < copy->iovcnt; i++) |
797 | - sum += copy->iov[i].iov_len; |
798 | - return sum; |
799 | -} |
800 | - |
801 | -static inline void verify_out_len(struct mic_info *mic, |
802 | - struct mic_copy_desc *copy) |
803 | -{ |
804 | - if (copy->out_len != sum_iovec_len(copy)) { |
805 | - mpsslog("%s %s %d BUG copy->out_len 0x%x len 0x%zx\n", |
806 | - mic->name, __func__, __LINE__, |
807 | - copy->out_len, sum_iovec_len(copy)); |
808 | - assert(copy->out_len == sum_iovec_len(copy)); |
809 | - } |
810 | -} |
811 | - |
812 | -/* Display an iovec */ |
813 | -static void |
814 | -disp_iovec(struct mic_info *mic, struct mic_copy_desc *copy, |
815 | - const char *s, int line) |
816 | -{ |
817 | - int i; |
818 | - |
819 | - for (i = 0; i < copy->iovcnt; i++) |
820 | - mpsslog("%s %s %d copy->iov[%d] addr %p len 0x%zx\n", |
821 | - mic->name, s, line, i, |
822 | - copy->iov[i].iov_base, copy->iov[i].iov_len); |
823 | -} |
824 | - |
825 | -static inline __u16 read_avail_idx(struct mic_vring *vr) |
826 | -{ |
827 | - return ACCESS_ONCE(vr->info->avail_idx); |
828 | -} |
829 | - |
830 | -static inline void txrx_prepare(int type, bool tx, struct mic_vring *vr, |
831 | - struct mic_copy_desc *copy, ssize_t len) |
832 | -{ |
833 | - copy->vr_idx = tx ? 0 : 1; |
834 | - copy->update_used = true; |
835 | - if (type == VIRTIO_ID_NET) |
836 | - copy->iov[1].iov_len = len - sizeof(struct virtio_net_hdr); |
837 | - else |
838 | - copy->iov[0].iov_len = len; |
839 | -} |
840 | - |
841 | -/* Central API which triggers the copies */ |
842 | -static int |
843 | -mic_virtio_copy(struct mic_info *mic, int fd, |
844 | - struct mic_vring *vr, struct mic_copy_desc *copy) |
845 | -{ |
846 | - int ret; |
847 | - |
848 | - ret = ioctl(fd, MIC_VIRTIO_COPY_DESC, copy); |
849 | - if (ret) { |
850 | - mpsslog("%s %s %d errno %s ret %d\n", |
851 | - mic->name, __func__, __LINE__, |
852 | - strerror(errno), ret); |
853 | - } |
854 | - return ret; |
855 | -} |
856 | - |
857 | -static inline unsigned _vring_size(unsigned int num, unsigned long align) |
858 | -{ |
859 | - return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (3 + num) |
860 | - + align - 1) & ~(align - 1)) |
861 | - + sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num; |
862 | -} |
863 | - |
864 | -/* |
865 | - * This initialization routine requires at least one |
866 | - * vring i.e. vr0. vr1 is optional. |
867 | - */ |
868 | -static void * |
869 | -init_vr(struct mic_info *mic, int fd, int type, |
870 | - struct mic_vring *vr0, struct mic_vring *vr1, int num_vq) |
871 | -{ |
872 | - int vr_size; |
873 | - char *va; |
874 | - |
875 | - vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES, |
876 | - MIC_VIRTIO_RING_ALIGN) + |
877 | - sizeof(struct _mic_vring_info)); |
878 | - va = mmap(NULL, MIC_DEVICE_PAGE_END + vr_size * num_vq, |
879 | - PROT_READ, MAP_SHARED, fd, 0); |
880 | - if (MAP_FAILED == va) { |
881 | - mpsslog("%s %s %d mmap failed errno %s\n", |
882 | - mic->name, __func__, __LINE__, |
883 | - strerror(errno)); |
884 | - goto done; |
885 | - } |
886 | - set_dp(mic, type, va); |
887 | - vr0->va = (struct mic_vring *)&va[MIC_DEVICE_PAGE_END]; |
888 | - vr0->info = vr0->va + |
889 | - _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN); |
890 | - vring_init(&vr0->vr, |
891 | - MIC_VRING_ENTRIES, vr0->va, MIC_VIRTIO_RING_ALIGN); |
892 | - mpsslog("%s %s vr0 %p vr0->info %p vr_size 0x%x vring 0x%x ", |
893 | - __func__, mic->name, vr0->va, vr0->info, vr_size, |
894 | - _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN)); |
895 | - mpsslog("magic 0x%x expected 0x%x\n", |
896 | - le32toh(vr0->info->magic), MIC_MAGIC + type); |
897 | - assert(le32toh(vr0->info->magic) == MIC_MAGIC + type); |
898 | - if (vr1) { |
899 | - vr1->va = (struct mic_vring *) |
900 | - &va[MIC_DEVICE_PAGE_END + vr_size]; |
901 | - vr1->info = vr1->va + _vring_size(MIC_VRING_ENTRIES, |
902 | - MIC_VIRTIO_RING_ALIGN); |
903 | - vring_init(&vr1->vr, |
904 | - MIC_VRING_ENTRIES, vr1->va, MIC_VIRTIO_RING_ALIGN); |
905 | - mpsslog("%s %s vr1 %p vr1->info %p vr_size 0x%x vring 0x%x ", |
906 | - __func__, mic->name, vr1->va, vr1->info, vr_size, |
907 | - _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN)); |
908 | - mpsslog("magic 0x%x expected 0x%x\n", |
909 | - le32toh(vr1->info->magic), MIC_MAGIC + type + 1); |
910 | - assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1); |
911 | - } |
912 | -done: |
913 | - return va; |
914 | -} |
915 | - |
916 | -static int |
917 | -wait_for_card_driver(struct mic_info *mic, int fd, int type) |
918 | -{ |
919 | - struct pollfd pollfd; |
920 | - int err; |
921 | - struct mic_device_desc *desc = get_device_desc(mic, type); |
922 | - __u8 prev_status; |
923 | - |
924 | - if (!desc) |
925 | - return -ENODEV; |
926 | - prev_status = desc->status; |
927 | - pollfd.fd = fd; |
928 | - mpsslog("%s %s Waiting .... desc-> type %d status 0x%x\n", |
929 | - mic->name, __func__, type, desc->status); |
930 | - |
931 | - while (1) { |
932 | - pollfd.events = POLLIN; |
933 | - pollfd.revents = 0; |
934 | - err = poll(&pollfd, 1, -1); |
935 | - if (err < 0) { |
936 | - mpsslog("%s %s poll failed %s\n", |
937 | - mic->name, __func__, strerror(errno)); |
938 | - continue; |
939 | - } |
940 | - |
941 | - if (pollfd.revents) { |
942 | - if (desc->status != prev_status) { |
943 | - mpsslog("%s %s Waiting... desc-> type %d " |
944 | - "status 0x%x\n", |
945 | - mic->name, __func__, type, |
946 | - desc->status); |
947 | - prev_status = desc->status; |
948 | - } |
949 | - if (desc->status & VIRTIO_CONFIG_S_DRIVER_OK) { |
950 | - mpsslog("%s %s poll.revents %d\n", |
951 | - mic->name, __func__, pollfd.revents); |
952 | - mpsslog("%s %s desc-> type %d status 0x%x\n", |
953 | - mic->name, __func__, type, |
954 | - desc->status); |
955 | - break; |
956 | - } |
957 | - } |
958 | - } |
959 | - return 0; |
960 | -} |
961 | - |
962 | -/* Spin till we have some descriptors */ |
963 | -static void |
964 | -spin_for_descriptors(struct mic_info *mic, struct mic_vring *vr) |
965 | -{ |
966 | - __u16 avail_idx = read_avail_idx(vr); |
967 | - |
968 | - while (avail_idx == le16toh(ACCESS_ONCE(vr->vr.avail->idx))) { |
969 | -#ifdef DEBUG |
970 | - mpsslog("%s %s waiting for desc avail %d info_avail %d\n", |
971 | - mic->name, __func__, |
972 | - le16toh(vr->vr.avail->idx), vr->info->avail_idx); |
973 | -#endif |
974 | - sched_yield(); |
975 | - } |
976 | -} |
977 | - |
978 | -static void * |
979 | -virtio_net(void *arg) |
980 | -{ |
981 | - static __u8 vnet_hdr[2][sizeof(struct virtio_net_hdr)]; |
982 | - static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __attribute__ ((aligned(64))); |
983 | - struct iovec vnet_iov[2][2] = { |
984 | - { { .iov_base = vnet_hdr[0], .iov_len = sizeof(vnet_hdr[0]) }, |
985 | - { .iov_base = vnet_buf[0], .iov_len = sizeof(vnet_buf[0]) } }, |
986 | - { { .iov_base = vnet_hdr[1], .iov_len = sizeof(vnet_hdr[1]) }, |
987 | - { .iov_base = vnet_buf[1], .iov_len = sizeof(vnet_buf[1]) } }, |
988 | - }; |
989 | - struct iovec *iov0 = vnet_iov[0], *iov1 = vnet_iov[1]; |
990 | - struct mic_info *mic = (struct mic_info *)arg; |
991 | - char if_name[IFNAMSIZ]; |
992 | - struct pollfd net_poll[MAX_NET_FD]; |
993 | - struct mic_vring tx_vr, rx_vr; |
994 | - struct mic_copy_desc copy; |
995 | - struct mic_device_desc *desc; |
996 | - int err; |
997 | - |
998 | - snprintf(if_name, IFNAMSIZ, "mic%d", mic->id); |
999 | - mic->mic_net.tap_fd = tun_alloc(mic, if_name); |
1000 | - if (mic->mic_net.tap_fd < 0) |
1001 | - goto done; |
1002 | - |
1003 | - if (tap_configure(mic, if_name)) |
1004 | - goto done; |
1005 | - mpsslog("MIC name %s id %d\n", mic->name, mic->id); |
1006 | - |
1007 | - net_poll[NET_FD_VIRTIO_NET].fd = mic->mic_net.virtio_net_fd; |
1008 | - net_poll[NET_FD_VIRTIO_NET].events = POLLIN; |
1009 | - net_poll[NET_FD_TUN].fd = mic->mic_net.tap_fd; |
1010 | - net_poll[NET_FD_TUN].events = POLLIN; |
1011 | - |
1012 | - if (MAP_FAILED == init_vr(mic, mic->mic_net.virtio_net_fd, |
1013 | - VIRTIO_ID_NET, &tx_vr, &rx_vr, |
1014 | - virtnet_dev_page.dd.num_vq)) { |
1015 | - mpsslog("%s init_vr failed %s\n", |
1016 | - mic->name, strerror(errno)); |
1017 | - goto done; |
1018 | - } |
1019 | - |
1020 | - copy.iovcnt = 2; |
1021 | - desc = get_device_desc(mic, VIRTIO_ID_NET); |
1022 | - |
1023 | - while (1) { |
1024 | - ssize_t len; |
1025 | - |
1026 | - net_poll[NET_FD_VIRTIO_NET].revents = 0; |
1027 | - net_poll[NET_FD_TUN].revents = 0; |
1028 | - |
1029 | - /* Start polling for data from tap and virtio net */ |
1030 | - err = poll(net_poll, 2, -1); |
1031 | - if (err < 0) { |
1032 | - mpsslog("%s poll failed %s\n", |
1033 | - __func__, strerror(errno)); |
1034 | - continue; |
1035 | - } |
1036 | - if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) { |
1037 | - err = wait_for_card_driver(mic, |
1038 | - mic->mic_net.virtio_net_fd, |
1039 | - VIRTIO_ID_NET); |
1040 | - if (err) { |
1041 | - mpsslog("%s %s %d Exiting...\n", |
1042 | - mic->name, __func__, __LINE__); |
1043 | - break; |
1044 | - } |
1045 | - } |
1046 | - /* |
1047 | - * Check if there is data to be read from TUN and write to |
1048 | - * virtio net fd if there is. |
1049 | - */ |
1050 | - if (net_poll[NET_FD_TUN].revents & POLLIN) { |
1051 | - copy.iov = iov0; |
1052 | - len = readv(net_poll[NET_FD_TUN].fd, |
1053 | - copy.iov, copy.iovcnt); |
1054 | - if (len > 0) { |
1055 | - struct virtio_net_hdr *hdr |
1056 | - = (struct virtio_net_hdr *)vnet_hdr[0]; |
1057 | - |
1058 | - /* Disable checksums on the card since we are on |
1059 | - a reliable PCIe link */ |
1060 | - hdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID; |
1061 | -#ifdef DEBUG |
1062 | - mpsslog("%s %s %d hdr->flags 0x%x ", mic->name, |
1063 | - __func__, __LINE__, hdr->flags); |
1064 | - mpsslog("copy.out_len %d hdr->gso_type 0x%x\n", |
1065 | - copy.out_len, hdr->gso_type); |
1066 | -#endif |
1067 | -#ifdef DEBUG |
1068 | - disp_iovec(mic, copy, __func__, __LINE__); |
1069 | - mpsslog("%s %s %d read from tap 0x%lx\n", |
1070 | - mic->name, __func__, __LINE__, |
1071 | - len); |
1072 | -#endif |
1073 | - spin_for_descriptors(mic, &tx_vr); |
1074 | - txrx_prepare(VIRTIO_ID_NET, 1, &tx_vr, ©, |
1075 | - len); |
1076 | - |
1077 | - err = mic_virtio_copy(mic, |
1078 | - mic->mic_net.virtio_net_fd, &tx_vr, |
1079 | - ©); |
1080 | - if (err < 0) { |
1081 | - mpsslog("%s %s %d mic_virtio_copy %s\n", |
1082 | - mic->name, __func__, __LINE__, |
1083 | - strerror(errno)); |
1084 | - } |
1085 | - if (!err) |
1086 | - verify_out_len(mic, ©); |
1087 | -#ifdef DEBUG |
1088 | - disp_iovec(mic, copy, __func__, __LINE__); |
1089 | - mpsslog("%s %s %d wrote to net 0x%lx\n", |
1090 | - mic->name, __func__, __LINE__, |
1091 | - sum_iovec_len(©)); |
1092 | -#endif |
1093 | - /* Reinitialize IOV for next run */ |
1094 | - iov0[1].iov_len = MAX_NET_PKT_SIZE; |
1095 | - } else if (len < 0) { |
1096 | - disp_iovec(mic, ©, __func__, __LINE__); |
1097 | - mpsslog("%s %s %d read failed %s ", mic->name, |
1098 | - __func__, __LINE__, strerror(errno)); |
1099 | - mpsslog("cnt %d sum %zd\n", |
1100 | - copy.iovcnt, sum_iovec_len(©)); |
1101 | - } |
1102 | - } |
1103 | - |
1104 | - /* |
1105 | - * Check if there is data to be read from virtio net and |
1106 | - * write to TUN if there is. |
1107 | - */ |
1108 | - if (net_poll[NET_FD_VIRTIO_NET].revents & POLLIN) { |
1109 | - while (rx_vr.info->avail_idx != |
1110 | - le16toh(rx_vr.vr.avail->idx)) { |
1111 | - copy.iov = iov1; |
1112 | - txrx_prepare(VIRTIO_ID_NET, 0, &rx_vr, ©, |
1113 | - MAX_NET_PKT_SIZE |
1114 | - + sizeof(struct virtio_net_hdr)); |
1115 | - |
1116 | - err = mic_virtio_copy(mic, |
1117 | - mic->mic_net.virtio_net_fd, &rx_vr, |
1118 | - ©); |
1119 | - if (!err) { |
1120 | -#ifdef DEBUG |
1121 | - struct virtio_net_hdr *hdr |
1122 | - = (struct virtio_net_hdr *) |
1123 | - vnet_hdr[1]; |
1124 | - |
1125 | - mpsslog("%s %s %d hdr->flags 0x%x, ", |
1126 | - mic->name, __func__, __LINE__, |
1127 | - hdr->flags); |
1128 | - mpsslog("out_len %d gso_type 0x%x\n", |
1129 | - copy.out_len, |
1130 | - hdr->gso_type); |
1131 | -#endif |
1132 | - /* Set the correct output iov_len */ |
1133 | - iov1[1].iov_len = copy.out_len - |
1134 | - sizeof(struct virtio_net_hdr); |
1135 | - verify_out_len(mic, ©); |
1136 | -#ifdef DEBUG |
1137 | - disp_iovec(mic, copy, __func__, |
1138 | - __LINE__); |
1139 | - mpsslog("%s %s %d ", |
1140 | - mic->name, __func__, __LINE__); |
1141 | - mpsslog("read from net 0x%lx\n", |
1142 | - sum_iovec_len(copy)); |
1143 | -#endif |
1144 | - len = writev(net_poll[NET_FD_TUN].fd, |
1145 | - copy.iov, copy.iovcnt); |
1146 | - if (len != sum_iovec_len(©)) { |
1147 | - mpsslog("Tun write failed %s ", |
1148 | - strerror(errno)); |
1149 | - mpsslog("len 0x%zx ", len); |
1150 | - mpsslog("read_len 0x%zx\n", |
1151 | - sum_iovec_len(©)); |
1152 | - } else { |
1153 | -#ifdef DEBUG |
1154 | - disp_iovec(mic, ©, __func__, |
1155 | - __LINE__); |
1156 | - mpsslog("%s %s %d ", |
1157 | - mic->name, __func__, |
1158 | - __LINE__); |
1159 | - mpsslog("wrote to tap 0x%lx\n", |
1160 | - len); |
1161 | -#endif |
1162 | - } |
1163 | - } else { |
1164 | - mpsslog("%s %s %d mic_virtio_copy %s\n", |
1165 | - mic->name, __func__, __LINE__, |
1166 | - strerror(errno)); |
1167 | - break; |
1168 | - } |
1169 | - } |
1170 | - } |
1171 | - if (net_poll[NET_FD_VIRTIO_NET].revents & POLLERR) |
1172 | - mpsslog("%s: %s: POLLERR\n", __func__, mic->name); |
1173 | - } |
1174 | -done: |
1175 | - pthread_exit(NULL); |
1176 | -} |
1177 | - |
1178 | -/* virtio_console */ |
1179 | -#define VIRTIO_CONSOLE_FD 0 |
1180 | -#define MONITOR_FD (VIRTIO_CONSOLE_FD + 1) |
1181 | -#define MAX_CONSOLE_FD (MONITOR_FD + 1) /* must be the last one + 1 */ |
1182 | -#define MAX_BUFFER_SIZE PAGE_SIZE |
1183 | - |
1184 | -static void * |
1185 | -virtio_console(void *arg) |
1186 | -{ |
1187 | - static __u8 vcons_buf[2][PAGE_SIZE]; |
1188 | - struct iovec vcons_iov[2] = { |
1189 | - { .iov_base = vcons_buf[0], .iov_len = sizeof(vcons_buf[0]) }, |
1190 | - { .iov_base = vcons_buf[1], .iov_len = sizeof(vcons_buf[1]) }, |
1191 | - }; |
1192 | - struct iovec *iov0 = &vcons_iov[0], *iov1 = &vcons_iov[1]; |
1193 | - struct mic_info *mic = (struct mic_info *)arg; |
1194 | - int err; |
1195 | - struct pollfd console_poll[MAX_CONSOLE_FD]; |
1196 | - int pty_fd; |
1197 | - char *pts_name; |
1198 | - ssize_t len; |
1199 | - struct mic_vring tx_vr, rx_vr; |
1200 | - struct mic_copy_desc copy; |
1201 | - struct mic_device_desc *desc; |
1202 | - |
1203 | - pty_fd = posix_openpt(O_RDWR); |
1204 | - if (pty_fd < 0) { |
1205 | - mpsslog("can't open a pseudoterminal master device: %s\n", |
1206 | - strerror(errno)); |
1207 | - goto _return; |
1208 | - } |
1209 | - pts_name = ptsname(pty_fd); |
1210 | - if (pts_name == NULL) { |
1211 | - mpsslog("can't get pts name\n"); |
1212 | - goto _close_pty; |
1213 | - } |
1214 | - printf("%s console message goes to %s\n", mic->name, pts_name); |
1215 | - mpsslog("%s console message goes to %s\n", mic->name, pts_name); |
1216 | - err = grantpt(pty_fd); |
1217 | - if (err < 0) { |
1218 | - mpsslog("can't grant access: %s %s\n", |
1219 | - pts_name, strerror(errno)); |
1220 | - goto _close_pty; |
1221 | - } |
1222 | - err = unlockpt(pty_fd); |
1223 | - if (err < 0) { |
1224 | - mpsslog("can't unlock a pseudoterminal: %s %s\n", |
1225 | - pts_name, strerror(errno)); |
1226 | - goto _close_pty; |
1227 | - } |
1228 | - console_poll[MONITOR_FD].fd = pty_fd; |
1229 | - console_poll[MONITOR_FD].events = POLLIN; |
1230 | - |
1231 | - console_poll[VIRTIO_CONSOLE_FD].fd = mic->mic_console.virtio_console_fd; |
1232 | - console_poll[VIRTIO_CONSOLE_FD].events = POLLIN; |
1233 | - |
1234 | - if (MAP_FAILED == init_vr(mic, mic->mic_console.virtio_console_fd, |
1235 | - VIRTIO_ID_CONSOLE, &tx_vr, &rx_vr, |
1236 | - virtcons_dev_page.dd.num_vq)) { |
1237 | - mpsslog("%s init_vr failed %s\n", |
1238 | - mic->name, strerror(errno)); |
1239 | - goto _close_pty; |
1240 | - } |
1241 | - |
1242 | - copy.iovcnt = 1; |
1243 | - desc = get_device_desc(mic, VIRTIO_ID_CONSOLE); |
1244 | - |
1245 | - for (;;) { |
1246 | - console_poll[MONITOR_FD].revents = 0; |
1247 | - console_poll[VIRTIO_CONSOLE_FD].revents = 0; |
1248 | - err = poll(console_poll, MAX_CONSOLE_FD, -1); |
1249 | - if (err < 0) { |
1250 | - mpsslog("%s %d: poll failed: %s\n", __func__, __LINE__, |
1251 | - strerror(errno)); |
1252 | - continue; |
1253 | - } |
1254 | - if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) { |
1255 | - err = wait_for_card_driver(mic, |
1256 | - mic->mic_console.virtio_console_fd, |
1257 | - VIRTIO_ID_CONSOLE); |
1258 | - if (err) { |
1259 | - mpsslog("%s %s %d Exiting...\n", |
1260 | - mic->name, __func__, __LINE__); |
1261 | - break; |
1262 | - } |
1263 | - } |
1264 | - |
1265 | - if (console_poll[MONITOR_FD].revents & POLLIN) { |
1266 | - copy.iov = iov0; |
1267 | - len = readv(pty_fd, copy.iov, copy.iovcnt); |
1268 | - if (len > 0) { |
1269 | -#ifdef DEBUG |
1270 | - disp_iovec(mic, copy, __func__, __LINE__); |
1271 | - mpsslog("%s %s %d read from tap 0x%lx\n", |
1272 | - mic->name, __func__, __LINE__, |
1273 | - len); |
1274 | -#endif |
1275 | - spin_for_descriptors(mic, &tx_vr); |
1276 | - txrx_prepare(VIRTIO_ID_CONSOLE, 1, &tx_vr, |
1277 | - ©, len); |
1278 | - |
1279 | - err = mic_virtio_copy(mic, |
1280 | - mic->mic_console.virtio_console_fd, |
1281 | - &tx_vr, ©); |
1282 | - if (err < 0) { |
1283 | - mpsslog("%s %s %d mic_virtio_copy %s\n", |
1284 | - mic->name, __func__, __LINE__, |
1285 | - strerror(errno)); |
1286 | - } |
1287 | - if (!err) |
1288 | - verify_out_len(mic, ©); |
1289 | -#ifdef DEBUG |
1290 | - disp_iovec(mic, copy, __func__, __LINE__); |
1291 | - mpsslog("%s %s %d wrote to net 0x%lx\n", |
1292 | - mic->name, __func__, __LINE__, |
1293 | - sum_iovec_len(copy)); |
1294 | -#endif |
1295 | - /* Reinitialize IOV for next run */ |
1296 | - iov0->iov_len = PAGE_SIZE; |
1297 | - } else if (len < 0) { |
1298 | - disp_iovec(mic, ©, __func__, __LINE__); |
1299 | - mpsslog("%s %s %d read failed %s ", |
1300 | - mic->name, __func__, __LINE__, |
1301 | - strerror(errno)); |
1302 | - mpsslog("cnt %d sum %zd\n", |
1303 | - copy.iovcnt, sum_iovec_len(©)); |
1304 | - } |
1305 | - } |
1306 | - |
1307 | - if (console_poll[VIRTIO_CONSOLE_FD].revents & POLLIN) { |
1308 | - while (rx_vr.info->avail_idx != |
1309 | - le16toh(rx_vr.vr.avail->idx)) { |
1310 | - copy.iov = iov1; |
1311 | - txrx_prepare(VIRTIO_ID_CONSOLE, 0, &rx_vr, |
1312 | - ©, PAGE_SIZE); |
1313 | - |
1314 | - err = mic_virtio_copy(mic, |
1315 | - mic->mic_console.virtio_console_fd, |
1316 | - &rx_vr, ©); |
1317 | - if (!err) { |
1318 | - /* Set the correct output iov_len */ |
1319 | - iov1->iov_len = copy.out_len; |
1320 | - verify_out_len(mic, ©); |
1321 | -#ifdef DEBUG |
1322 | - disp_iovec(mic, copy, __func__, |
1323 | - __LINE__); |
1324 | - mpsslog("%s %s %d ", |
1325 | - mic->name, __func__, __LINE__); |
1326 | - mpsslog("read from net 0x%lx\n", |
1327 | - sum_iovec_len(copy)); |
1328 | -#endif |
1329 | - len = writev(pty_fd, |
1330 | - copy.iov, copy.iovcnt); |
1331 | - if (len != sum_iovec_len(©)) { |
1332 | - mpsslog("Tun write failed %s ", |
1333 | - strerror(errno)); |
1334 | - mpsslog("len 0x%zx ", len); |
1335 | - mpsslog("read_len 0x%zx\n", |
1336 | - sum_iovec_len(©)); |
1337 | - } else { |
1338 | -#ifdef DEBUG |
1339 | - disp_iovec(mic, copy, __func__, |
1340 | - __LINE__); |
1341 | - mpsslog("%s %s %d ", |
1342 | - mic->name, __func__, |
1343 | - __LINE__); |
1344 | - mpsslog("wrote to tap 0x%lx\n", |
1345 | - len); |
1346 | -#endif |
1347 | - } |
1348 | - } else { |
1349 | - mpsslog("%s %s %d mic_virtio_copy %s\n", |
1350 | - mic->name, __func__, __LINE__, |
1351 | - strerror(errno)); |
1352 | - break; |
1353 | - } |
1354 | - } |
1355 | - } |
1356 | - if (console_poll[NET_FD_VIRTIO_NET].revents & POLLERR) |
1357 | - mpsslog("%s: %s: POLLERR\n", __func__, mic->name); |
1358 | - } |
1359 | -_close_pty: |
1360 | - close(pty_fd); |
1361 | -_return: |
1362 | - pthread_exit(NULL); |
1363 | -} |
1364 | - |
1365 | -static void |
1366 | -add_virtio_device(struct mic_info *mic, struct mic_device_desc *dd) |
1367 | -{ |
1368 | - char path[PATH_MAX]; |
1369 | - int fd, err; |
1370 | - |
1371 | - snprintf(path, PATH_MAX, "/dev/mic%d", mic->id); |
1372 | - fd = open(path, O_RDWR); |
1373 | - if (fd < 0) { |
1374 | - mpsslog("Could not open %s %s\n", path, strerror(errno)); |
1375 | - return; |
1376 | - } |
1377 | - |
1378 | - err = ioctl(fd, MIC_VIRTIO_ADD_DEVICE, dd); |
1379 | - if (err < 0) { |
1380 | - mpsslog("Could not add %d %s\n", dd->type, strerror(errno)); |
1381 | - close(fd); |
1382 | - return; |
1383 | - } |
1384 | - switch (dd->type) { |
1385 | - case VIRTIO_ID_NET: |
1386 | - mic->mic_net.virtio_net_fd = fd; |
1387 | - mpsslog("Added VIRTIO_ID_NET for %s\n", mic->name); |
1388 | - break; |
1389 | - case VIRTIO_ID_CONSOLE: |
1390 | - mic->mic_console.virtio_console_fd = fd; |
1391 | - mpsslog("Added VIRTIO_ID_CONSOLE for %s\n", mic->name); |
1392 | - break; |
1393 | - case VIRTIO_ID_BLOCK: |
1394 | - mic->mic_virtblk.virtio_block_fd = fd; |
1395 | - mpsslog("Added VIRTIO_ID_BLOCK for %s\n", mic->name); |
1396 | - break; |
1397 | - } |
1398 | -} |
1399 | - |
1400 | -static bool |
1401 | -set_backend_file(struct mic_info *mic) |
1402 | -{ |
1403 | - FILE *config; |
1404 | - char buff[PATH_MAX], *line, *evv, *p; |
1405 | - |
1406 | - snprintf(buff, PATH_MAX, "%s/mpssd%03d.conf", mic_config_dir, mic->id); |
1407 | - config = fopen(buff, "r"); |
1408 | - if (config == NULL) |
1409 | - return false; |
1410 | - do { /* look for "virtblk_backend=XXXX" */ |
1411 | - line = fgets(buff, PATH_MAX, config); |
1412 | - if (line == NULL) |
1413 | - break; |
1414 | - if (*line == '#') |
1415 | - continue; |
1416 | - p = strchr(line, '\n'); |
1417 | - if (p) |
1418 | - *p = '\0'; |
1419 | - } while (strncmp(line, virtblk_backend, strlen(virtblk_backend)) != 0); |
1420 | - fclose(config); |
1421 | - if (line == NULL) |
1422 | - return false; |
1423 | - evv = strchr(line, '='); |
1424 | - if (evv == NULL) |
1425 | - return false; |
1426 | - mic->mic_virtblk.backend_file = malloc(strlen(evv) + 1); |
1427 | - if (mic->mic_virtblk.backend_file == NULL) { |
1428 | - mpsslog("%s %d can't allocate memory\n", mic->name, mic->id); |
1429 | - return false; |
1430 | - } |
1431 | - strcpy(mic->mic_virtblk.backend_file, evv + 1); |
1432 | - return true; |
1433 | -} |
1434 | - |
1435 | -#define SECTOR_SIZE 512 |
1436 | -static bool |
1437 | -set_backend_size(struct mic_info *mic) |
1438 | -{ |
1439 | - mic->mic_virtblk.backend_size = lseek(mic->mic_virtblk.backend, 0, |
1440 | - SEEK_END); |
1441 | - if (mic->mic_virtblk.backend_size < 0) { |
1442 | - mpsslog("%s: can't seek: %s\n", |
1443 | - mic->name, mic->mic_virtblk.backend_file); |
1444 | - return false; |
1445 | - } |
1446 | - virtblk_dev_page.blk_config.capacity = |
1447 | - mic->mic_virtblk.backend_size / SECTOR_SIZE; |
1448 | - if ((mic->mic_virtblk.backend_size % SECTOR_SIZE) != 0) |
1449 | - virtblk_dev_page.blk_config.capacity++; |
1450 | - |
1451 | - virtblk_dev_page.blk_config.capacity = |
1452 | - htole64(virtblk_dev_page.blk_config.capacity); |
1453 | - |
1454 | - return true; |
1455 | -} |
1456 | - |
1457 | -static bool |
1458 | -open_backend(struct mic_info *mic) |
1459 | -{ |
1460 | - if (!set_backend_file(mic)) |
1461 | - goto _error_exit; |
1462 | - mic->mic_virtblk.backend = open(mic->mic_virtblk.backend_file, O_RDWR); |
1463 | - if (mic->mic_virtblk.backend < 0) { |
1464 | - mpsslog("%s: can't open: %s\n", mic->name, |
1465 | - mic->mic_virtblk.backend_file); |
1466 | - goto _error_free; |
1467 | - } |
1468 | - if (!set_backend_size(mic)) |
1469 | - goto _error_close; |
1470 | - mic->mic_virtblk.backend_addr = mmap(NULL, |
1471 | - mic->mic_virtblk.backend_size, |
1472 | - PROT_READ|PROT_WRITE, MAP_SHARED, |
1473 | - mic->mic_virtblk.backend, 0L); |
1474 | - if (mic->mic_virtblk.backend_addr == MAP_FAILED) { |
1475 | - mpsslog("%s: can't map: %s %s\n", |
1476 | - mic->name, mic->mic_virtblk.backend_file, |
1477 | - strerror(errno)); |
1478 | - goto _error_close; |
1479 | - } |
1480 | - return true; |
1481 | - |
1482 | - _error_close: |
1483 | - close(mic->mic_virtblk.backend); |
1484 | - _error_free: |
1485 | - free(mic->mic_virtblk.backend_file); |
1486 | - _error_exit: |
1487 | - return false; |
1488 | -} |
1489 | - |
1490 | -static void |
1491 | -close_backend(struct mic_info *mic) |
1492 | -{ |
1493 | - munmap(mic->mic_virtblk.backend_addr, mic->mic_virtblk.backend_size); |
1494 | - close(mic->mic_virtblk.backend); |
1495 | - free(mic->mic_virtblk.backend_file); |
1496 | -} |
1497 | - |
1498 | -static bool |
1499 | -start_virtblk(struct mic_info *mic, struct mic_vring *vring) |
1500 | -{ |
1501 | - if (((unsigned long)&virtblk_dev_page.blk_config % 8) != 0) { |
1502 | - mpsslog("%s: blk_config is not 8 byte aligned.\n", |
1503 | - mic->name); |
1504 | - return false; |
1505 | - } |
1506 | - add_virtio_device(mic, &virtblk_dev_page.dd); |
1507 | - if (MAP_FAILED == init_vr(mic, mic->mic_virtblk.virtio_block_fd, |
1508 | - VIRTIO_ID_BLOCK, vring, NULL, |
1509 | - virtblk_dev_page.dd.num_vq)) { |
1510 | - mpsslog("%s init_vr failed %s\n", |
1511 | - mic->name, strerror(errno)); |
1512 | - return false; |
1513 | - } |
1514 | - return true; |
1515 | -} |
1516 | - |
1517 | -static void |
1518 | -stop_virtblk(struct mic_info *mic) |
1519 | -{ |
1520 | - int vr_size, ret; |
1521 | - |
1522 | - vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES, |
1523 | - MIC_VIRTIO_RING_ALIGN) + |
1524 | - sizeof(struct _mic_vring_info)); |
1525 | - ret = munmap(mic->mic_virtblk.block_dp, |
1526 | - MIC_DEVICE_PAGE_END + vr_size * virtblk_dev_page.dd.num_vq); |
1527 | - if (ret < 0) |
1528 | - mpsslog("%s munmap errno %d\n", mic->name, errno); |
1529 | - close(mic->mic_virtblk.virtio_block_fd); |
1530 | -} |
1531 | - |
1532 | -static __u8 |
1533 | -header_error_check(struct vring_desc *desc) |
1534 | -{ |
1535 | - if (le32toh(desc->len) != sizeof(struct virtio_blk_outhdr)) { |
1536 | - mpsslog("%s() %d: length is not sizeof(virtio_blk_outhd)\n", |
1537 | - __func__, __LINE__); |
1538 | - return -EIO; |
1539 | - } |
1540 | - if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT)) { |
1541 | - mpsslog("%s() %d: alone\n", |
1542 | - __func__, __LINE__); |
1543 | - return -EIO; |
1544 | - } |
1545 | - if (le16toh(desc->flags) & VRING_DESC_F_WRITE) { |
1546 | - mpsslog("%s() %d: not read\n", |
1547 | - __func__, __LINE__); |
1548 | - return -EIO; |
1549 | - } |
1550 | - return 0; |
1551 | -} |
1552 | - |
1553 | -static int |
1554 | -read_header(int fd, struct virtio_blk_outhdr *hdr, __u32 desc_idx) |
1555 | -{ |
1556 | - struct iovec iovec; |
1557 | - struct mic_copy_desc copy; |
1558 | - |
1559 | - iovec.iov_len = sizeof(*hdr); |
1560 | - iovec.iov_base = hdr; |
1561 | - copy.iov = &iovec; |
1562 | - copy.iovcnt = 1; |
1563 | - copy.vr_idx = 0; /* only one vring on virtio_block */ |
1564 | - copy.update_used = false; /* do not update used index */ |
1565 | - return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
1566 | -} |
1567 | - |
1568 | -static int |
1569 | -transfer_blocks(int fd, struct iovec *iovec, __u32 iovcnt) |
1570 | -{ |
1571 | - struct mic_copy_desc copy; |
1572 | - |
1573 | - copy.iov = iovec; |
1574 | - copy.iovcnt = iovcnt; |
1575 | - copy.vr_idx = 0; /* only one vring on virtio_block */ |
1576 | - copy.update_used = false; /* do not update used index */ |
1577 | - return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
1578 | -} |
1579 | - |
1580 | -static __u8 |
1581 | -status_error_check(struct vring_desc *desc) |
1582 | -{ |
1583 | - if (le32toh(desc->len) != sizeof(__u8)) { |
1584 | - mpsslog("%s() %d: length is not sizeof(status)\n", |
1585 | - __func__, __LINE__); |
1586 | - return -EIO; |
1587 | - } |
1588 | - return 0; |
1589 | -} |
1590 | - |
1591 | -static int |
1592 | -write_status(int fd, __u8 *status) |
1593 | -{ |
1594 | - struct iovec iovec; |
1595 | - struct mic_copy_desc copy; |
1596 | - |
1597 | - iovec.iov_base = status; |
1598 | - iovec.iov_len = sizeof(*status); |
1599 | - copy.iov = &iovec; |
1600 | - copy.iovcnt = 1; |
1601 | - copy.vr_idx = 0; /* only one vring on virtio_block */ |
1602 | - copy.update_used = true; /* Update used index */ |
1603 | - return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
1604 | -} |
1605 | - |
1606 | -#ifndef VIRTIO_BLK_T_GET_ID |
1607 | -#define VIRTIO_BLK_T_GET_ID 8 |
1608 | -#endif |
1609 | - |
1610 | -static void * |
1611 | -virtio_block(void *arg) |
1612 | -{ |
1613 | - struct mic_info *mic = (struct mic_info *)arg; |
1614 | - int ret; |
1615 | - struct pollfd block_poll; |
1616 | - struct mic_vring vring; |
1617 | - __u16 avail_idx; |
1618 | - __u32 desc_idx; |
1619 | - struct vring_desc *desc; |
1620 | - struct iovec *iovec, *piov; |
1621 | - __u8 status; |
1622 | - __u32 buffer_desc_idx; |
1623 | - struct virtio_blk_outhdr hdr; |
1624 | - void *fos; |
1625 | - |
1626 | - for (;;) { /* forever */ |
1627 | - if (!open_backend(mic)) { /* No virtblk */ |
1628 | - for (mic->mic_virtblk.signaled = 0; |
1629 | - !mic->mic_virtblk.signaled;) |
1630 | - sleep(1); |
1631 | - continue; |
1632 | - } |
1633 | - |
1634 | - /* backend file is specified. */ |
1635 | - if (!start_virtblk(mic, &vring)) |
1636 | - goto _close_backend; |
1637 | - iovec = malloc(sizeof(*iovec) * |
1638 | - le32toh(virtblk_dev_page.blk_config.seg_max)); |
1639 | - if (!iovec) { |
1640 | - mpsslog("%s: can't alloc iovec: %s\n", |
1641 | - mic->name, strerror(ENOMEM)); |
1642 | - goto _stop_virtblk; |
1643 | - } |
1644 | - |
1645 | - block_poll.fd = mic->mic_virtblk.virtio_block_fd; |
1646 | - block_poll.events = POLLIN; |
1647 | - for (mic->mic_virtblk.signaled = 0; |
1648 | - !mic->mic_virtblk.signaled;) { |
1649 | - block_poll.revents = 0; |
1650 | - /* timeout in 1 sec to see signaled */ |
1651 | - ret = poll(&block_poll, 1, 1000); |
1652 | - if (ret < 0) { |
1653 | - mpsslog("%s %d: poll failed: %s\n", |
1654 | - __func__, __LINE__, |
1655 | - strerror(errno)); |
1656 | - continue; |
1657 | - } |
1658 | - |
1659 | - if (!(block_poll.revents & POLLIN)) { |
1660 | -#ifdef DEBUG |
1661 | - mpsslog("%s %d: block_poll.revents=0x%x\n", |
1662 | - __func__, __LINE__, block_poll.revents); |
1663 | -#endif |
1664 | - continue; |
1665 | - } |
1666 | - |
1667 | - /* POLLIN */ |
1668 | - while (vring.info->avail_idx != |
1669 | - le16toh(vring.vr.avail->idx)) { |
1670 | - /* read header element */ |
1671 | - avail_idx = |
1672 | - vring.info->avail_idx & |
1673 | - (vring.vr.num - 1); |
1674 | - desc_idx = le16toh( |
1675 | - vring.vr.avail->ring[avail_idx]); |
1676 | - desc = &vring.vr.desc[desc_idx]; |
1677 | -#ifdef DEBUG |
1678 | - mpsslog("%s() %d: avail_idx=%d ", |
1679 | - __func__, __LINE__, |
1680 | - vring.info->avail_idx); |
1681 | - mpsslog("vring.vr.num=%d desc=%p\n", |
1682 | - vring.vr.num, desc); |
1683 | -#endif |
1684 | - status = header_error_check(desc); |
1685 | - ret = read_header( |
1686 | - mic->mic_virtblk.virtio_block_fd, |
1687 | - &hdr, desc_idx); |
1688 | - if (ret < 0) { |
1689 | - mpsslog("%s() %d %s: ret=%d %s\n", |
1690 | - __func__, __LINE__, |
1691 | - mic->name, ret, |
1692 | - strerror(errno)); |
1693 | - break; |
1694 | - } |
1695 | - /* buffer element */ |
1696 | - piov = iovec; |
1697 | - status = 0; |
1698 | - fos = mic->mic_virtblk.backend_addr + |
1699 | - (hdr.sector * SECTOR_SIZE); |
1700 | - buffer_desc_idx = next_desc(desc); |
1701 | - desc_idx = buffer_desc_idx; |
1702 | - for (desc = &vring.vr.desc[buffer_desc_idx]; |
1703 | - desc->flags & VRING_DESC_F_NEXT; |
1704 | - desc_idx = next_desc(desc), |
1705 | - desc = &vring.vr.desc[desc_idx]) { |
1706 | - piov->iov_len = desc->len; |
1707 | - piov->iov_base = fos; |
1708 | - piov++; |
1709 | - fos += desc->len; |
1710 | - } |
1711 | - /* Returning NULLs for VIRTIO_BLK_T_GET_ID. */ |
1712 | - if (hdr.type & ~(VIRTIO_BLK_T_OUT | |
1713 | - VIRTIO_BLK_T_GET_ID)) { |
1714 | - /* |
1715 | - VIRTIO_BLK_T_IN - does not do |
1716 | - anything. Probably for documenting. |
1717 | - VIRTIO_BLK_T_SCSI_CMD - for |
1718 | - virtio_scsi. |
1719 | - VIRTIO_BLK_T_FLUSH - turned off in |
1720 | - config space. |
1721 | - VIRTIO_BLK_T_BARRIER - defined but not |
1722 | - used in anywhere. |
1723 | - */ |
1724 | - mpsslog("%s() %d: type %x ", |
1725 | - __func__, __LINE__, |
1726 | - hdr.type); |
1727 | - mpsslog("is not supported\n"); |
1728 | - status = -ENOTSUP; |
1729 | - |
1730 | - } else { |
1731 | - ret = transfer_blocks( |
1732 | - mic->mic_virtblk.virtio_block_fd, |
1733 | - iovec, |
1734 | - piov - iovec); |
1735 | - if (ret < 0 && |
1736 | - status != 0) |
1737 | - status = ret; |
1738 | - } |
1739 | - /* write status and update used pointer */ |
1740 | - if (status != 0) |
1741 | - status = status_error_check(desc); |
1742 | - ret = write_status( |
1743 | - mic->mic_virtblk.virtio_block_fd, |
1744 | - &status); |
1745 | -#ifdef DEBUG |
1746 | - mpsslog("%s() %d: write status=%d on desc=%p\n", |
1747 | - __func__, __LINE__, |
1748 | - status, desc); |
1749 | -#endif |
1750 | - } |
1751 | - } |
1752 | - free(iovec); |
1753 | -_stop_virtblk: |
1754 | - stop_virtblk(mic); |
1755 | -_close_backend: |
1756 | - close_backend(mic); |
1757 | - } /* forever */ |
1758 | - |
1759 | - pthread_exit(NULL); |
1760 | -} |
1761 | - |
1762 | -static void |
1763 | -reset(struct mic_info *mic) |
1764 | -{ |
1765 | -#define RESET_TIMEOUT 120 |
1766 | - int i = RESET_TIMEOUT; |
1767 | - setsysfs(mic->name, "state", "reset"); |
1768 | - while (i) { |
1769 | - char *state; |
1770 | - state = readsysfs(mic->name, "state"); |
1771 | - if (!state) |
1772 | - goto retry; |
1773 | - mpsslog("%s: %s %d state %s\n", |
1774 | - mic->name, __func__, __LINE__, state); |
1775 | - |
1776 | - if (!strcmp(state, "ready")) { |
1777 | - free(state); |
1778 | - break; |
1779 | - } |
1780 | - free(state); |
1781 | -retry: |
1782 | - sleep(1); |
1783 | - i--; |
1784 | - } |
1785 | -} |
1786 | - |
1787 | -static int |
1788 | -get_mic_shutdown_status(struct mic_info *mic, char *shutdown_status) |
1789 | -{ |
1790 | - if (!strcmp(shutdown_status, "nop")) |
1791 | - return MIC_NOP; |
1792 | - if (!strcmp(shutdown_status, "crashed")) |
1793 | - return MIC_CRASHED; |
1794 | - if (!strcmp(shutdown_status, "halted")) |
1795 | - return MIC_HALTED; |
1796 | - if (!strcmp(shutdown_status, "poweroff")) |
1797 | - return MIC_POWER_OFF; |
1798 | - if (!strcmp(shutdown_status, "restart")) |
1799 | - return MIC_RESTART; |
1800 | - mpsslog("%s: BUG invalid status %s\n", mic->name, shutdown_status); |
1801 | - /* Invalid state */ |
1802 | - assert(0); |
1803 | -}; |
1804 | - |
1805 | -static int get_mic_state(struct mic_info *mic) |
1806 | -{ |
1807 | - char *state = NULL; |
1808 | - enum mic_states mic_state; |
1809 | - |
1810 | - while (!state) { |
1811 | - state = readsysfs(mic->name, "state"); |
1812 | - sleep(1); |
1813 | - } |
1814 | - mpsslog("%s: %s %d state %s\n", |
1815 | - mic->name, __func__, __LINE__, state); |
1816 | - |
1817 | - if (!strcmp(state, "ready")) { |
1818 | - mic_state = MIC_READY; |
1819 | - } else if (!strcmp(state, "booting")) { |
1820 | - mic_state = MIC_BOOTING; |
1821 | - } else if (!strcmp(state, "online")) { |
1822 | - mic_state = MIC_ONLINE; |
1823 | - } else if (!strcmp(state, "shutting_down")) { |
1824 | - mic_state = MIC_SHUTTING_DOWN; |
1825 | - } else if (!strcmp(state, "reset_failed")) { |
1826 | - mic_state = MIC_RESET_FAILED; |
1827 | - } else if (!strcmp(state, "resetting")) { |
1828 | - mic_state = MIC_RESETTING; |
1829 | - } else { |
1830 | - mpsslog("%s: BUG invalid state %s\n", mic->name, state); |
1831 | - assert(0); |
1832 | - } |
1833 | - |
1834 | - free(state); |
1835 | - return mic_state; |
1836 | -}; |
1837 | - |
1838 | -static void mic_handle_shutdown(struct mic_info *mic) |
1839 | -{ |
1840 | -#define SHUTDOWN_TIMEOUT 60 |
1841 | - int i = SHUTDOWN_TIMEOUT; |
1842 | - char *shutdown_status; |
1843 | - while (i) { |
1844 | - shutdown_status = readsysfs(mic->name, "shutdown_status"); |
1845 | - if (!shutdown_status) { |
1846 | - sleep(1); |
1847 | - continue; |
1848 | - } |
1849 | - mpsslog("%s: %s %d shutdown_status %s\n", |
1850 | - mic->name, __func__, __LINE__, shutdown_status); |
1851 | - switch (get_mic_shutdown_status(mic, shutdown_status)) { |
1852 | - case MIC_RESTART: |
1853 | - mic->restart = 1; |
1854 | - case MIC_HALTED: |
1855 | - case MIC_POWER_OFF: |
1856 | - case MIC_CRASHED: |
1857 | - free(shutdown_status); |
1858 | - goto reset; |
1859 | - default: |
1860 | - break; |
1861 | - } |
1862 | - free(shutdown_status); |
1863 | - sleep(1); |
1864 | - i--; |
1865 | - } |
1866 | -reset: |
1867 | - if (!i) |
1868 | - mpsslog("%s: %s %d timing out waiting for shutdown_status %s\n", |
1869 | - mic->name, __func__, __LINE__, shutdown_status); |
1870 | - reset(mic); |
1871 | -} |
1872 | - |
1873 | -static int open_state_fd(struct mic_info *mic) |
1874 | -{ |
1875 | - char pathname[PATH_MAX]; |
1876 | - int fd; |
1877 | - |
1878 | - snprintf(pathname, PATH_MAX - 1, "%s/%s/%s", |
1879 | - MICSYSFSDIR, mic->name, "state"); |
1880 | - |
1881 | - fd = open(pathname, O_RDONLY); |
1882 | - if (fd < 0) |
1883 | - mpsslog("%s: opening file %s failed %s\n", |
1884 | - mic->name, pathname, strerror(errno)); |
1885 | - return fd; |
1886 | -} |
1887 | - |
1888 | -static int block_till_state_change(int fd, struct mic_info *mic) |
1889 | -{ |
1890 | - struct pollfd ufds[1]; |
1891 | - char value[PAGE_SIZE]; |
1892 | - int ret; |
1893 | - |
1894 | - ufds[0].fd = fd; |
1895 | - ufds[0].events = POLLERR | POLLPRI; |
1896 | - ret = poll(ufds, 1, -1); |
1897 | - if (ret < 0) { |
1898 | - mpsslog("%s: %s %d poll failed %s\n", |
1899 | - mic->name, __func__, __LINE__, strerror(errno)); |
1900 | - return ret; |
1901 | - } |
1902 | - |
1903 | - ret = lseek(fd, 0, SEEK_SET); |
1904 | - if (ret < 0) { |
1905 | - mpsslog("%s: %s %d Failed to seek to 0: %s\n", |
1906 | - mic->name, __func__, __LINE__, strerror(errno)); |
1907 | - return ret; |
1908 | - } |
1909 | - |
1910 | - ret = read(fd, value, sizeof(value)); |
1911 | - if (ret < 0) { |
1912 | - mpsslog("%s: %s %d Failed to read sysfs entry: %s\n", |
1913 | - mic->name, __func__, __LINE__, strerror(errno)); |
1914 | - return ret; |
1915 | - } |
1916 | - |
1917 | - return 0; |
1918 | -} |
1919 | - |
1920 | -static void * |
1921 | -mic_config(void *arg) |
1922 | -{ |
1923 | - struct mic_info *mic = (struct mic_info *)arg; |
1924 | - int fd, ret, stat = 0; |
1925 | - |
1926 | - fd = open_state_fd(mic); |
1927 | - if (fd < 0) { |
1928 | - mpsslog("%s: %s %d open state fd failed %s\n", |
1929 | - mic->name, __func__, __LINE__, strerror(errno)); |
1930 | - goto exit; |
1931 | - } |
1932 | - |
1933 | - do { |
1934 | - ret = block_till_state_change(fd, mic); |
1935 | - if (ret < 0) { |
1936 | - mpsslog("%s: %s %d block_till_state_change error %s\n", |
1937 | - mic->name, __func__, __LINE__, strerror(errno)); |
1938 | - goto close_exit; |
1939 | - } |
1940 | - |
1941 | - switch (get_mic_state(mic)) { |
1942 | - case MIC_SHUTTING_DOWN: |
1943 | - mic_handle_shutdown(mic); |
1944 | - break; |
1945 | - case MIC_READY: |
1946 | - case MIC_RESET_FAILED: |
1947 | - ret = kill(mic->pid, SIGTERM); |
1948 | - mpsslog("%s: %s %d kill pid %d ret %d\n", |
1949 | - mic->name, __func__, __LINE__, |
1950 | - mic->pid, ret); |
1951 | - if (!ret) { |
1952 | - ret = waitpid(mic->pid, &stat, |
1953 | - WIFSIGNALED(stat)); |
1954 | - mpsslog("%s: %s %d waitpid ret %d pid %d\n", |
1955 | - mic->name, __func__, __LINE__, |
1956 | - ret, mic->pid); |
1957 | - } |
1958 | - if (mic->boot_on_resume) { |
1959 | - setsysfs(mic->name, "state", "boot"); |
1960 | - mic->boot_on_resume = 0; |
1961 | - } |
1962 | - goto close_exit; |
1963 | - default: |
1964 | - break; |
1965 | - } |
1966 | - } while (1); |
1967 | - |
1968 | -close_exit: |
1969 | - close(fd); |
1970 | -exit: |
1971 | - init_mic(mic); |
1972 | - pthread_exit(NULL); |
1973 | -} |
1974 | - |
1975 | -static void |
1976 | -set_cmdline(struct mic_info *mic) |
1977 | -{ |
1978 | - char buffer[PATH_MAX]; |
1979 | - int len; |
1980 | - |
1981 | - len = snprintf(buffer, PATH_MAX, |
1982 | - "clocksource=tsc highres=off nohz=off "); |
1983 | - len += snprintf(buffer + len, PATH_MAX - len, |
1984 | - "cpufreq_on;corec6_off;pc3_off;pc6_off "); |
1985 | - len += snprintf(buffer + len, PATH_MAX - len, |
1986 | - "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0", |
1987 | - mic->id + 1); |
1988 | - |
1989 | - setsysfs(mic->name, "cmdline", buffer); |
1990 | - mpsslog("%s: Command line: \"%s\"\n", mic->name, buffer); |
1991 | - snprintf(buffer, PATH_MAX, "172.31.%d.1", mic->id + 1); |
1992 | - mpsslog("%s: IPADDR: \"%s\"\n", mic->name, buffer); |
1993 | -} |
1994 | - |
1995 | -static void |
1996 | -set_log_buf_info(struct mic_info *mic) |
1997 | -{ |
1998 | - int fd; |
1999 | - off_t len; |
2000 | - char system_map[] = "/lib/firmware/mic/System.map"; |
2001 | - char *map, *temp, log_buf[17] = {'\0'}; |
2002 | - |
2003 | - fd = open(system_map, O_RDONLY); |
2004 | - if (fd < 0) { |
2005 | - mpsslog("%s: Opening System.map failed: %d\n", |
2006 | - mic->name, errno); |
2007 | - return; |
2008 | - } |
2009 | - len = lseek(fd, 0, SEEK_END); |
2010 | - if (len < 0) { |
2011 | - mpsslog("%s: Reading System.map size failed: %d\n", |
2012 | - mic->name, errno); |
2013 | - close(fd); |
2014 | - return; |
2015 | - } |
2016 | - map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); |
2017 | - if (map == MAP_FAILED) { |
2018 | - mpsslog("%s: mmap of System.map failed: %d\n", |
2019 | - mic->name, errno); |
2020 | - close(fd); |
2021 | - return; |
2022 | - } |
2023 | - temp = strstr(map, "__log_buf"); |
2024 | - if (!temp) { |
2025 | - mpsslog("%s: __log_buf not found: %d\n", mic->name, errno); |
2026 | - munmap(map, len); |
2027 | - close(fd); |
2028 | - return; |
2029 | - } |
2030 | - strncpy(log_buf, temp - 19, 16); |
2031 | - setsysfs(mic->name, "log_buf_addr", log_buf); |
2032 | - mpsslog("%s: log_buf_addr: %s\n", mic->name, log_buf); |
2033 | - temp = strstr(map, "log_buf_len"); |
2034 | - if (!temp) { |
2035 | - mpsslog("%s: log_buf_len not found: %d\n", mic->name, errno); |
2036 | - munmap(map, len); |
2037 | - close(fd); |
2038 | - return; |
2039 | - } |
2040 | - strncpy(log_buf, temp - 19, 16); |
2041 | - setsysfs(mic->name, "log_buf_len", log_buf); |
2042 | - mpsslog("%s: log_buf_len: %s\n", mic->name, log_buf); |
2043 | - munmap(map, len); |
2044 | - close(fd); |
2045 | -} |
2046 | - |
2047 | -static void |
2048 | -change_virtblk_backend(int x, siginfo_t *siginfo, void *p) |
2049 | -{ |
2050 | - struct mic_info *mic; |
2051 | - |
2052 | - for (mic = mic_list.next; mic != NULL; mic = mic->next) |
2053 | - mic->mic_virtblk.signaled = 1/* true */; |
2054 | -} |
2055 | - |
2056 | -static void |
2057 | -set_mic_boot_params(struct mic_info *mic) |
2058 | -{ |
2059 | - set_log_buf_info(mic); |
2060 | - set_cmdline(mic); |
2061 | -} |
2062 | - |
2063 | -static void * |
2064 | -init_mic(void *arg) |
2065 | -{ |
2066 | - struct mic_info *mic = (struct mic_info *)arg; |
2067 | - struct sigaction ignore = { |
2068 | - .sa_flags = 0, |
2069 | - .sa_handler = SIG_IGN |
2070 | - }; |
2071 | - struct sigaction act = { |
2072 | - .sa_flags = SA_SIGINFO, |
2073 | - .sa_sigaction = change_virtblk_backend, |
2074 | - }; |
2075 | - char buffer[PATH_MAX]; |
2076 | - int err, fd; |
2077 | - |
2078 | - /* |
2079 | - * Currently, one virtio block device is supported for each MIC card |
2080 | - * at a time. Any user (or test) can send a SIGUSR1 to the MIC daemon. |
2081 | - * The signal informs the virtio block backend about a change in the |
2082 | - * configuration file which specifies the virtio backend file name on |
2083 | - * the host. Virtio block backend then re-reads the configuration file |
2084 | - * and switches to the new block device. This signalling mechanism may |
2085 | - * not be required once multiple virtio block devices are supported by |
2086 | - * the MIC daemon. |
2087 | - */ |
2088 | - sigaction(SIGUSR1, &ignore, NULL); |
2089 | -retry: |
2090 | - fd = open_state_fd(mic); |
2091 | - if (fd < 0) { |
2092 | - mpsslog("%s: %s %d open state fd failed %s\n", |
2093 | - mic->name, __func__, __LINE__, strerror(errno)); |
2094 | - sleep(2); |
2095 | - goto retry; |
2096 | - } |
2097 | - |
2098 | - if (mic->restart) { |
2099 | - snprintf(buffer, PATH_MAX, "boot"); |
2100 | - setsysfs(mic->name, "state", buffer); |
2101 | - mpsslog("%s restarting mic %d\n", |
2102 | - mic->name, mic->restart); |
2103 | - mic->restart = 0; |
2104 | - } |
2105 | - |
2106 | - while (1) { |
2107 | - while (block_till_state_change(fd, mic)) { |
2108 | - mpsslog("%s: %s %d block_till_state_change error %s\n", |
2109 | - mic->name, __func__, __LINE__, strerror(errno)); |
2110 | - sleep(2); |
2111 | - continue; |
2112 | - } |
2113 | - |
2114 | - if (get_mic_state(mic) == MIC_BOOTING) |
2115 | - break; |
2116 | - } |
2117 | - |
2118 | - mic->pid = fork(); |
2119 | - switch (mic->pid) { |
2120 | - case 0: |
2121 | - add_virtio_device(mic, &virtcons_dev_page.dd); |
2122 | - add_virtio_device(mic, &virtnet_dev_page.dd); |
2123 | - err = pthread_create(&mic->mic_console.console_thread, NULL, |
2124 | - virtio_console, mic); |
2125 | - if (err) |
2126 | - mpsslog("%s virtcons pthread_create failed %s\n", |
2127 | - mic->name, strerror(err)); |
2128 | - err = pthread_create(&mic->mic_net.net_thread, NULL, |
2129 | - virtio_net, mic); |
2130 | - if (err) |
2131 | - mpsslog("%s virtnet pthread_create failed %s\n", |
2132 | - mic->name, strerror(err)); |
2133 | - err = pthread_create(&mic->mic_virtblk.block_thread, NULL, |
2134 | - virtio_block, mic); |
2135 | - if (err) |
2136 | - mpsslog("%s virtblk pthread_create failed %s\n", |
2137 | - mic->name, strerror(err)); |
2138 | - sigemptyset(&act.sa_mask); |
2139 | - err = sigaction(SIGUSR1, &act, NULL); |
2140 | - if (err) |
2141 | - mpsslog("%s sigaction SIGUSR1 failed %s\n", |
2142 | - mic->name, strerror(errno)); |
2143 | - while (1) |
2144 | - sleep(60); |
2145 | - case -1: |
2146 | - mpsslog("fork failed MIC name %s id %d errno %d\n", |
2147 | - mic->name, mic->id, errno); |
2148 | - break; |
2149 | - default: |
2150 | - err = pthread_create(&mic->config_thread, NULL, |
2151 | - mic_config, mic); |
2152 | - if (err) |
2153 | - mpsslog("%s mic_config pthread_create failed %s\n", |
2154 | - mic->name, strerror(err)); |
2155 | - } |
2156 | - |
2157 | - return NULL; |
2158 | -} |
2159 | - |
2160 | -static void |
2161 | -start_daemon(void) |
2162 | -{ |
2163 | - struct mic_info *mic; |
2164 | - int err; |
2165 | - |
2166 | - for (mic = mic_list.next; mic; mic = mic->next) { |
2167 | - set_mic_boot_params(mic); |
2168 | - err = pthread_create(&mic->init_thread, NULL, init_mic, mic); |
2169 | - if (err) |
2170 | - mpsslog("%s init_mic pthread_create failed %s\n", |
2171 | - mic->name, strerror(err)); |
2172 | - } |
2173 | - |
2174 | - while (1) |
2175 | - sleep(60); |
2176 | -} |
2177 | - |
2178 | -static int |
2179 | -init_mic_list(void) |
2180 | -{ |
2181 | - struct mic_info *mic = &mic_list; |
2182 | - struct dirent *file; |
2183 | - DIR *dp; |
2184 | - int cnt = 0; |
2185 | - |
2186 | - dp = opendir(MICSYSFSDIR); |
2187 | - if (!dp) |
2188 | - return 0; |
2189 | - |
2190 | - while ((file = readdir(dp)) != NULL) { |
2191 | - if (!strncmp(file->d_name, "mic", 3)) { |
2192 | - mic->next = calloc(1, sizeof(struct mic_info)); |
2193 | - if (mic->next) { |
2194 | - mic = mic->next; |
2195 | - mic->id = atoi(&file->d_name[3]); |
2196 | - mic->name = malloc(strlen(file->d_name) + 16); |
2197 | - if (mic->name) |
2198 | - strcpy(mic->name, file->d_name); |
2199 | - mpsslog("MIC name %s id %d\n", mic->name, |
2200 | - mic->id); |
2201 | - cnt++; |
2202 | - } |
2203 | - } |
2204 | - } |
2205 | - |
2206 | - closedir(dp); |
2207 | - return cnt; |
2208 | -} |
2209 | - |
2210 | -void |
2211 | -mpsslog(char *format, ...) |
2212 | -{ |
2213 | - va_list args; |
2214 | - char buffer[4096]; |
2215 | - char ts[52], *ts1; |
2216 | - time_t t; |
2217 | - |
2218 | - if (logfp == NULL) |
2219 | - return; |
2220 | - |
2221 | - va_start(args, format); |
2222 | - vsprintf(buffer, format, args); |
2223 | - va_end(args); |
2224 | - |
2225 | - time(&t); |
2226 | - ts1 = ctime_r(&t, ts); |
2227 | - ts1[strlen(ts1) - 1] = '\0'; |
2228 | - fprintf(logfp, "%s: %s", ts1, buffer); |
2229 | - |
2230 | - fflush(logfp); |
2231 | -} |
2232 | - |
2233 | -int |
2234 | -main(int argc, char *argv[]) |
2235 | -{ |
2236 | - int cnt; |
2237 | - pid_t pid; |
2238 | - |
2239 | - myname = argv[0]; |
2240 | - |
2241 | - logfp = fopen(LOGFILE_NAME, "a+"); |
2242 | - if (!logfp) { |
2243 | - fprintf(stderr, "cannot open logfile '%s'\n", LOGFILE_NAME); |
2244 | - exit(1); |
2245 | - } |
2246 | - pid = fork(); |
2247 | - switch (pid) { |
2248 | - case 0: |
2249 | - break; |
2250 | - case -1: |
2251 | - exit(2); |
2252 | - default: |
2253 | - exit(0); |
2254 | - } |
2255 | - |
2256 | - mpsslog("MIC Daemon start\n"); |
2257 | - |
2258 | - cnt = init_mic_list(); |
2259 | - if (cnt == 0) { |
2260 | - mpsslog("MIC module not loaded\n"); |
2261 | - exit(3); |
2262 | - } |
2263 | - mpsslog("MIC found %d devices\n", cnt); |
2264 | - |
2265 | - start_daemon(); |
2266 | - |
2267 | - exit(0); |
2268 | -} |
2269 | diff --git a/Documentation/mic/mpssd/mpssd.h b/Documentation/mic/mpssd/mpssd.h |
2270 | deleted file mode 100644 |
2271 | index 8bd64944aacc..000000000000 |
2272 | --- a/Documentation/mic/mpssd/mpssd.h |
2273 | +++ /dev/null |
2274 | @@ -1,103 +0,0 @@ |
2275 | -/* |
2276 | - * Intel MIC Platform Software Stack (MPSS) |
2277 | - * |
2278 | - * Copyright(c) 2013 Intel Corporation. |
2279 | - * |
2280 | - * This program is free software; you can redistribute it and/or modify |
2281 | - * it under the terms of the GNU General Public License, version 2, as |
2282 | - * published by the Free Software Foundation. |
2283 | - * |
2284 | - * This program is distributed in the hope that it will be useful, but |
2285 | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
2286 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2287 | - * General Public License for more details. |
2288 | - * |
2289 | - * The full GNU General Public License is included in this distribution in |
2290 | - * the file called "COPYING". |
2291 | - * |
2292 | - * Intel MIC User Space Tools. |
2293 | - */ |
2294 | -#ifndef _MPSSD_H_ |
2295 | -#define _MPSSD_H_ |
2296 | - |
2297 | -#include <stdio.h> |
2298 | -#include <stdlib.h> |
2299 | -#include <string.h> |
2300 | -#include <fcntl.h> |
2301 | -#include <unistd.h> |
2302 | -#include <dirent.h> |
2303 | -#include <libgen.h> |
2304 | -#include <pthread.h> |
2305 | -#include <stdarg.h> |
2306 | -#include <time.h> |
2307 | -#include <errno.h> |
2308 | -#include <sys/dir.h> |
2309 | -#include <sys/ioctl.h> |
2310 | -#include <sys/poll.h> |
2311 | -#include <sys/types.h> |
2312 | -#include <sys/socket.h> |
2313 | -#include <sys/stat.h> |
2314 | -#include <sys/types.h> |
2315 | -#include <sys/mman.h> |
2316 | -#include <sys/utsname.h> |
2317 | -#include <sys/wait.h> |
2318 | -#include <netinet/in.h> |
2319 | -#include <arpa/inet.h> |
2320 | -#include <netdb.h> |
2321 | -#include <pthread.h> |
2322 | -#include <signal.h> |
2323 | -#include <limits.h> |
2324 | -#include <syslog.h> |
2325 | -#include <getopt.h> |
2326 | -#include <net/if.h> |
2327 | -#include <linux/if_tun.h> |
2328 | -#include <linux/if_tun.h> |
2329 | -#include <linux/virtio_ids.h> |
2330 | - |
2331 | -#define MICSYSFSDIR "/sys/class/mic" |
2332 | -#define LOGFILE_NAME "/var/log/mpssd" |
2333 | -#define PAGE_SIZE 4096 |
2334 | - |
2335 | -struct mic_console_info { |
2336 | - pthread_t console_thread; |
2337 | - int virtio_console_fd; |
2338 | - void *console_dp; |
2339 | -}; |
2340 | - |
2341 | -struct mic_net_info { |
2342 | - pthread_t net_thread; |
2343 | - int virtio_net_fd; |
2344 | - int tap_fd; |
2345 | - void *net_dp; |
2346 | -}; |
2347 | - |
2348 | -struct mic_virtblk_info { |
2349 | - pthread_t block_thread; |
2350 | - int virtio_block_fd; |
2351 | - void *block_dp; |
2352 | - volatile sig_atomic_t signaled; |
2353 | - char *backend_file; |
2354 | - int backend; |
2355 | - void *backend_addr; |
2356 | - long backend_size; |
2357 | -}; |
2358 | - |
2359 | -struct mic_info { |
2360 | - int id; |
2361 | - char *name; |
2362 | - pthread_t config_thread; |
2363 | - pthread_t init_thread; |
2364 | - pid_t pid; |
2365 | - struct mic_console_info mic_console; |
2366 | - struct mic_net_info mic_net; |
2367 | - struct mic_virtblk_info mic_virtblk; |
2368 | - int restart; |
2369 | - int boot_on_resume; |
2370 | - struct mic_info *next; |
2371 | -}; |
2372 | - |
2373 | -__attribute__((format(printf, 1, 2))) |
2374 | -void mpsslog(char *format, ...); |
2375 | -char *readsysfs(char *dir, char *entry); |
2376 | -int setsysfs(char *dir, char *entry, char *value); |
2377 | -#endif |
2378 | diff --git a/Documentation/mic/mpssd/sysfs.c b/Documentation/mic/mpssd/sysfs.c |
2379 | deleted file mode 100644 |
2380 | index 8dd326936083..000000000000 |
2381 | --- a/Documentation/mic/mpssd/sysfs.c |
2382 | +++ /dev/null |
2383 | @@ -1,102 +0,0 @@ |
2384 | -/* |
2385 | - * Intel MIC Platform Software Stack (MPSS) |
2386 | - * |
2387 | - * Copyright(c) 2013 Intel Corporation. |
2388 | - * |
2389 | - * This program is free software; you can redistribute it and/or modify |
2390 | - * it under the terms of the GNU General Public License, version 2, as |
2391 | - * published by the Free Software Foundation. |
2392 | - * |
2393 | - * This program is distributed in the hope that it will be useful, but |
2394 | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
2395 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2396 | - * General Public License for more details. |
2397 | - * |
2398 | - * The full GNU General Public License is included in this distribution in |
2399 | - * the file called "COPYING". |
2400 | - * |
2401 | - * Intel MIC User Space Tools. |
2402 | - */ |
2403 | - |
2404 | -#include "mpssd.h" |
2405 | - |
2406 | -#define PAGE_SIZE 4096 |
2407 | - |
2408 | -char * |
2409 | -readsysfs(char *dir, char *entry) |
2410 | -{ |
2411 | - char filename[PATH_MAX]; |
2412 | - char value[PAGE_SIZE]; |
2413 | - char *string = NULL; |
2414 | - int fd; |
2415 | - int len; |
2416 | - |
2417 | - if (dir == NULL) |
2418 | - snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry); |
2419 | - else |
2420 | - snprintf(filename, PATH_MAX, |
2421 | - "%s/%s/%s", MICSYSFSDIR, dir, entry); |
2422 | - |
2423 | - fd = open(filename, O_RDONLY); |
2424 | - if (fd < 0) { |
2425 | - mpsslog("Failed to open sysfs entry '%s': %s\n", |
2426 | - filename, strerror(errno)); |
2427 | - return NULL; |
2428 | - } |
2429 | - |
2430 | - len = read(fd, value, sizeof(value)); |
2431 | - if (len < 0) { |
2432 | - mpsslog("Failed to read sysfs entry '%s': %s\n", |
2433 | - filename, strerror(errno)); |
2434 | - goto readsys_ret; |
2435 | - } |
2436 | - if (len == 0) |
2437 | - goto readsys_ret; |
2438 | - |
2439 | - value[len - 1] = '\0'; |
2440 | - |
2441 | - string = malloc(strlen(value) + 1); |
2442 | - if (string) |
2443 | - strcpy(string, value); |
2444 | - |
2445 | -readsys_ret: |
2446 | - close(fd); |
2447 | - return string; |
2448 | -} |
2449 | - |
2450 | -int |
2451 | -setsysfs(char *dir, char *entry, char *value) |
2452 | -{ |
2453 | - char filename[PATH_MAX]; |
2454 | - char *oldvalue; |
2455 | - int fd, ret = 0; |
2456 | - |
2457 | - if (dir == NULL) |
2458 | - snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry); |
2459 | - else |
2460 | - snprintf(filename, PATH_MAX, "%s/%s/%s", |
2461 | - MICSYSFSDIR, dir, entry); |
2462 | - |
2463 | - oldvalue = readsysfs(dir, entry); |
2464 | - |
2465 | - fd = open(filename, O_RDWR); |
2466 | - if (fd < 0) { |
2467 | - ret = errno; |
2468 | - mpsslog("Failed to open sysfs entry '%s': %s\n", |
2469 | - filename, strerror(errno)); |
2470 | - goto done; |
2471 | - } |
2472 | - |
2473 | - if (!oldvalue || strcmp(value, oldvalue)) { |
2474 | - if (write(fd, value, strlen(value)) < 0) { |
2475 | - ret = errno; |
2476 | - mpsslog("Failed to write new sysfs entry '%s': %s\n", |
2477 | - filename, strerror(errno)); |
2478 | - } |
2479 | - } |
2480 | - close(fd); |
2481 | -done: |
2482 | - if (oldvalue) |
2483 | - free(oldvalue); |
2484 | - return ret; |
2485 | -} |
2486 | diff --git a/Makefile b/Makefile |
2487 | index 671e183bd507..10aec937e9e4 100644 |
2488 | --- a/Makefile |
2489 | +++ b/Makefile |
2490 | @@ -1,6 +1,6 @@ |
2491 | VERSION = 4 |
2492 | PATCHLEVEL = 4 |
2493 | -SUBLEVEL = 52 |
2494 | +SUBLEVEL = 53 |
2495 | EXTRAVERSION = |
2496 | NAME = Blurry Fish Butt |
2497 | |
2498 | diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts |
2499 | index e74df327cdd3..20618a897c99 100644 |
2500 | --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts |
2501 | +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts |
2502 | @@ -122,6 +122,8 @@ |
2503 | uart1: serial@f8020000 { |
2504 | pinctrl-names = "default"; |
2505 | pinctrl-0 = <&pinctrl_uart1_default>; |
2506 | + atmel,use-dma-rx; |
2507 | + atmel,use-dma-tx; |
2508 | status = "okay"; |
2509 | }; |
2510 | |
2511 | diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts b/arch/arm/boot/dts/at91-sama5d4_xplained.dts |
2512 | index da84e65b56ef..e27024cdf48b 100644 |
2513 | --- a/arch/arm/boot/dts/at91-sama5d4_xplained.dts |
2514 | +++ b/arch/arm/boot/dts/at91-sama5d4_xplained.dts |
2515 | @@ -110,6 +110,8 @@ |
2516 | }; |
2517 | |
2518 | usart3: serial@fc00c000 { |
2519 | + atmel,use-dma-rx; |
2520 | + atmel,use-dma-tx; |
2521 | status = "okay"; |
2522 | }; |
2523 | |
2524 | diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h |
2525 | index 405aa1883307..23d5cad56ddc 100644 |
2526 | --- a/arch/arm/include/asm/kvm_mmu.h |
2527 | +++ b/arch/arm/include/asm/kvm_mmu.h |
2528 | @@ -204,18 +204,12 @@ static inline void __coherent_cache_guest_page(struct kvm_vcpu *vcpu, pfn_t pfn, |
2529 | * and iterate over the range. |
2530 | */ |
2531 | |
2532 | - bool need_flush = !vcpu_has_cache_enabled(vcpu) || ipa_uncached; |
2533 | - |
2534 | VM_BUG_ON(size & ~PAGE_MASK); |
2535 | |
2536 | - if (!need_flush && !icache_is_pipt()) |
2537 | - goto vipt_cache; |
2538 | - |
2539 | while (size) { |
2540 | void *va = kmap_atomic_pfn(pfn); |
2541 | |
2542 | - if (need_flush) |
2543 | - kvm_flush_dcache_to_poc(va, PAGE_SIZE); |
2544 | + kvm_flush_dcache_to_poc(va, PAGE_SIZE); |
2545 | |
2546 | if (icache_is_pipt()) |
2547 | __cpuc_coherent_user_range((unsigned long)va, |
2548 | @@ -227,7 +221,6 @@ static inline void __coherent_cache_guest_page(struct kvm_vcpu *vcpu, pfn_t pfn, |
2549 | kunmap_atomic(va); |
2550 | } |
2551 | |
2552 | -vipt_cache: |
2553 | if (!icache_is_pipt() && !icache_is_vivt_asid_tagged()) { |
2554 | /* any kind of VIPT cache */ |
2555 | __flush_icache_all(); |
2556 | diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h |
2557 | index 61505676d085..819b21a9851c 100644 |
2558 | --- a/arch/arm64/include/asm/kvm_mmu.h |
2559 | +++ b/arch/arm64/include/asm/kvm_mmu.h |
2560 | @@ -236,8 +236,7 @@ static inline void __coherent_cache_guest_page(struct kvm_vcpu *vcpu, pfn_t pfn, |
2561 | { |
2562 | void *va = page_address(pfn_to_page(pfn)); |
2563 | |
2564 | - if (!vcpu_has_cache_enabled(vcpu) || ipa_uncached) |
2565 | - kvm_flush_dcache_to_poc(va, size); |
2566 | + kvm_flush_dcache_to_poc(va, size); |
2567 | |
2568 | if (!icache_is_aliasing()) { /* PIPT */ |
2569 | flush_icache_range((unsigned long)va, |
2570 | diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c |
2571 | index 52caa75bfe4e..e2f50d690624 100644 |
2572 | --- a/arch/mips/bcm47xx/buttons.c |
2573 | +++ b/arch/mips/bcm47xx/buttons.c |
2574 | @@ -17,6 +17,12 @@ |
2575 | .active_low = 1, \ |
2576 | } |
2577 | |
2578 | +#define BCM47XX_GPIO_KEY_H(_gpio, _code) \ |
2579 | + { \ |
2580 | + .code = _code, \ |
2581 | + .gpio = _gpio, \ |
2582 | + } |
2583 | + |
2584 | /* Asus */ |
2585 | |
2586 | static const struct gpio_keys_button |
2587 | @@ -79,8 +85,8 @@ bcm47xx_buttons_asus_wl500gpv2[] __initconst = { |
2588 | |
2589 | static const struct gpio_keys_button |
2590 | bcm47xx_buttons_asus_wl500w[] __initconst = { |
2591 | - BCM47XX_GPIO_KEY(6, KEY_RESTART), |
2592 | - BCM47XX_GPIO_KEY(7, KEY_WPS_BUTTON), |
2593 | + BCM47XX_GPIO_KEY_H(6, KEY_RESTART), |
2594 | + BCM47XX_GPIO_KEY_H(7, KEY_WPS_BUTTON), |
2595 | }; |
2596 | |
2597 | static const struct gpio_keys_button |
2598 | diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S |
2599 | index 64e08df51d65..8b7004132491 100644 |
2600 | --- a/arch/mips/cavium-octeon/octeon-memcpy.S |
2601 | +++ b/arch/mips/cavium-octeon/octeon-memcpy.S |
2602 | @@ -208,18 +208,18 @@ EXC( STORE t2, UNIT(6)(dst), s_exc_p10u) |
2603 | ADD src, src, 16*NBYTES |
2604 | EXC( STORE t3, UNIT(7)(dst), s_exc_p9u) |
2605 | ADD dst, dst, 16*NBYTES |
2606 | -EXC( LOAD t0, UNIT(-8)(src), l_exc_copy) |
2607 | -EXC( LOAD t1, UNIT(-7)(src), l_exc_copy) |
2608 | -EXC( LOAD t2, UNIT(-6)(src), l_exc_copy) |
2609 | -EXC( LOAD t3, UNIT(-5)(src), l_exc_copy) |
2610 | +EXC( LOAD t0, UNIT(-8)(src), l_exc_copy_rewind16) |
2611 | +EXC( LOAD t1, UNIT(-7)(src), l_exc_copy_rewind16) |
2612 | +EXC( LOAD t2, UNIT(-6)(src), l_exc_copy_rewind16) |
2613 | +EXC( LOAD t3, UNIT(-5)(src), l_exc_copy_rewind16) |
2614 | EXC( STORE t0, UNIT(-8)(dst), s_exc_p8u) |
2615 | EXC( STORE t1, UNIT(-7)(dst), s_exc_p7u) |
2616 | EXC( STORE t2, UNIT(-6)(dst), s_exc_p6u) |
2617 | EXC( STORE t3, UNIT(-5)(dst), s_exc_p5u) |
2618 | -EXC( LOAD t0, UNIT(-4)(src), l_exc_copy) |
2619 | -EXC( LOAD t1, UNIT(-3)(src), l_exc_copy) |
2620 | -EXC( LOAD t2, UNIT(-2)(src), l_exc_copy) |
2621 | -EXC( LOAD t3, UNIT(-1)(src), l_exc_copy) |
2622 | +EXC( LOAD t0, UNIT(-4)(src), l_exc_copy_rewind16) |
2623 | +EXC( LOAD t1, UNIT(-3)(src), l_exc_copy_rewind16) |
2624 | +EXC( LOAD t2, UNIT(-2)(src), l_exc_copy_rewind16) |
2625 | +EXC( LOAD t3, UNIT(-1)(src), l_exc_copy_rewind16) |
2626 | EXC( STORE t0, UNIT(-4)(dst), s_exc_p4u) |
2627 | EXC( STORE t1, UNIT(-3)(dst), s_exc_p3u) |
2628 | EXC( STORE t2, UNIT(-2)(dst), s_exc_p2u) |
2629 | @@ -383,6 +383,10 @@ done: |
2630 | nop |
2631 | END(memcpy) |
2632 | |
2633 | +l_exc_copy_rewind16: |
2634 | + /* Rewind src and dst by 16*NBYTES for l_exc_copy */ |
2635 | + SUB src, src, 16*NBYTES |
2636 | + SUB dst, dst, 16*NBYTES |
2637 | l_exc_copy: |
2638 | /* |
2639 | * Copy bytes from src until faulting load address (or until a |
2640 | diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h |
2641 | index 3ceacde5eb6e..17f89f9670b2 100644 |
2642 | --- a/arch/mips/include/asm/checksum.h |
2643 | +++ b/arch/mips/include/asm/checksum.h |
2644 | @@ -186,7 +186,9 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, |
2645 | " daddu %0, %4 \n" |
2646 | " dsll32 $1, %0, 0 \n" |
2647 | " daddu %0, $1 \n" |
2648 | + " sltu $1, %0, $1 \n" |
2649 | " dsra32 %0, %0, 0 \n" |
2650 | + " addu %0, $1 \n" |
2651 | #endif |
2652 | " .set pop" |
2653 | : "=r" (sum) |
2654 | diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c |
2655 | index 44a6f25e902e..fc537d1b649d 100644 |
2656 | --- a/arch/mips/kernel/process.c |
2657 | +++ b/arch/mips/kernel/process.c |
2658 | @@ -191,11 +191,9 @@ struct mips_frame_info { |
2659 | #define J_TARGET(pc,target) \ |
2660 | (((unsigned long)(pc) & 0xf0000000) | ((target) << 2)) |
2661 | |
2662 | -static inline int is_ra_save_ins(union mips_instruction *ip) |
2663 | +static inline int is_ra_save_ins(union mips_instruction *ip, int *poff) |
2664 | { |
2665 | #ifdef CONFIG_CPU_MICROMIPS |
2666 | - union mips_instruction mmi; |
2667 | - |
2668 | /* |
2669 | * swsp ra,offset |
2670 | * swm16 reglist,offset(sp) |
2671 | @@ -205,29 +203,71 @@ static inline int is_ra_save_ins(union mips_instruction *ip) |
2672 | * |
2673 | * microMIPS is way more fun... |
2674 | */ |
2675 | - if (mm_insn_16bit(ip->halfword[0])) { |
2676 | - mmi.word = (ip->halfword[0] << 16); |
2677 | - return (mmi.mm16_r5_format.opcode == mm_swsp16_op && |
2678 | - mmi.mm16_r5_format.rt == 31) || |
2679 | - (mmi.mm16_m_format.opcode == mm_pool16c_op && |
2680 | - mmi.mm16_m_format.func == mm_swm16_op); |
2681 | + if (mm_insn_16bit(ip->halfword[1])) { |
2682 | + switch (ip->mm16_r5_format.opcode) { |
2683 | + case mm_swsp16_op: |
2684 | + if (ip->mm16_r5_format.rt != 31) |
2685 | + return 0; |
2686 | + |
2687 | + *poff = ip->mm16_r5_format.simmediate; |
2688 | + *poff = (*poff << 2) / sizeof(ulong); |
2689 | + return 1; |
2690 | + |
2691 | + case mm_pool16c_op: |
2692 | + switch (ip->mm16_m_format.func) { |
2693 | + case mm_swm16_op: |
2694 | + *poff = ip->mm16_m_format.imm; |
2695 | + *poff += 1 + ip->mm16_m_format.rlist; |
2696 | + *poff = (*poff << 2) / sizeof(ulong); |
2697 | + return 1; |
2698 | + |
2699 | + default: |
2700 | + return 0; |
2701 | + } |
2702 | + |
2703 | + default: |
2704 | + return 0; |
2705 | + } |
2706 | } |
2707 | - else { |
2708 | - mmi.halfword[0] = ip->halfword[1]; |
2709 | - mmi.halfword[1] = ip->halfword[0]; |
2710 | - return (mmi.mm_m_format.opcode == mm_pool32b_op && |
2711 | - mmi.mm_m_format.rd > 9 && |
2712 | - mmi.mm_m_format.base == 29 && |
2713 | - mmi.mm_m_format.func == mm_swm32_func) || |
2714 | - (mmi.i_format.opcode == mm_sw32_op && |
2715 | - mmi.i_format.rs == 29 && |
2716 | - mmi.i_format.rt == 31); |
2717 | + |
2718 | + switch (ip->i_format.opcode) { |
2719 | + case mm_sw32_op: |
2720 | + if (ip->i_format.rs != 29) |
2721 | + return 0; |
2722 | + if (ip->i_format.rt != 31) |
2723 | + return 0; |
2724 | + |
2725 | + *poff = ip->i_format.simmediate / sizeof(ulong); |
2726 | + return 1; |
2727 | + |
2728 | + case mm_pool32b_op: |
2729 | + switch (ip->mm_m_format.func) { |
2730 | + case mm_swm32_func: |
2731 | + if (ip->mm_m_format.rd < 0x10) |
2732 | + return 0; |
2733 | + if (ip->mm_m_format.base != 29) |
2734 | + return 0; |
2735 | + |
2736 | + *poff = ip->mm_m_format.simmediate; |
2737 | + *poff += (ip->mm_m_format.rd & 0xf) * sizeof(u32); |
2738 | + *poff /= sizeof(ulong); |
2739 | + return 1; |
2740 | + default: |
2741 | + return 0; |
2742 | + } |
2743 | + |
2744 | + default: |
2745 | + return 0; |
2746 | } |
2747 | #else |
2748 | /* sw / sd $ra, offset($sp) */ |
2749 | - return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) && |
2750 | - ip->i_format.rs == 29 && |
2751 | - ip->i_format.rt == 31; |
2752 | + if ((ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) && |
2753 | + ip->i_format.rs == 29 && ip->i_format.rt == 31) { |
2754 | + *poff = ip->i_format.simmediate / sizeof(ulong); |
2755 | + return 1; |
2756 | + } |
2757 | + |
2758 | + return 0; |
2759 | #endif |
2760 | } |
2761 | |
2762 | @@ -242,13 +282,16 @@ static inline int is_jump_ins(union mips_instruction *ip) |
2763 | * |
2764 | * microMIPS is kind of more fun... |
2765 | */ |
2766 | - union mips_instruction mmi; |
2767 | - |
2768 | - mmi.word = (ip->halfword[0] << 16); |
2769 | + if (mm_insn_16bit(ip->halfword[1])) { |
2770 | + if ((ip->mm16_r5_format.opcode == mm_pool16c_op && |
2771 | + (ip->mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op)) |
2772 | + return 1; |
2773 | + return 0; |
2774 | + } |
2775 | |
2776 | - if ((mmi.mm16_r5_format.opcode == mm_pool16c_op && |
2777 | - (mmi.mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op) || |
2778 | - ip->j_format.opcode == mm_jal32_op) |
2779 | + if (ip->j_format.opcode == mm_j32_op) |
2780 | + return 1; |
2781 | + if (ip->j_format.opcode == mm_jal32_op) |
2782 | return 1; |
2783 | if (ip->r_format.opcode != mm_pool32a_op || |
2784 | ip->r_format.func != mm_pool32axf_op) |
2785 | @@ -276,15 +319,13 @@ static inline int is_sp_move_ins(union mips_instruction *ip) |
2786 | * |
2787 | * microMIPS is not more fun... |
2788 | */ |
2789 | - if (mm_insn_16bit(ip->halfword[0])) { |
2790 | - union mips_instruction mmi; |
2791 | - |
2792 | - mmi.word = (ip->halfword[0] << 16); |
2793 | - return (mmi.mm16_r3_format.opcode == mm_pool16d_op && |
2794 | - mmi.mm16_r3_format.simmediate && mm_addiusp_func) || |
2795 | - (mmi.mm16_r5_format.opcode == mm_pool16d_op && |
2796 | - mmi.mm16_r5_format.rt == 29); |
2797 | + if (mm_insn_16bit(ip->halfword[1])) { |
2798 | + return (ip->mm16_r3_format.opcode == mm_pool16d_op && |
2799 | + ip->mm16_r3_format.simmediate && mm_addiusp_func) || |
2800 | + (ip->mm16_r5_format.opcode == mm_pool16d_op && |
2801 | + ip->mm16_r5_format.rt == 29); |
2802 | } |
2803 | + |
2804 | return ip->mm_i_format.opcode == mm_addiu32_op && |
2805 | ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29; |
2806 | #else |
2807 | @@ -299,30 +340,36 @@ static inline int is_sp_move_ins(union mips_instruction *ip) |
2808 | |
2809 | static int get_frame_info(struct mips_frame_info *info) |
2810 | { |
2811 | -#ifdef CONFIG_CPU_MICROMIPS |
2812 | - union mips_instruction *ip = (void *) (((char *) info->func) - 1); |
2813 | -#else |
2814 | - union mips_instruction *ip = info->func; |
2815 | -#endif |
2816 | - unsigned max_insns = info->func_size / sizeof(union mips_instruction); |
2817 | - unsigned i; |
2818 | + bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS); |
2819 | + union mips_instruction insn, *ip, *ip_end; |
2820 | + const unsigned int max_insns = 128; |
2821 | + unsigned int i; |
2822 | |
2823 | info->pc_offset = -1; |
2824 | info->frame_size = 0; |
2825 | |
2826 | + ip = (void *)msk_isa16_mode((ulong)info->func); |
2827 | if (!ip) |
2828 | goto err; |
2829 | |
2830 | - if (max_insns == 0) |
2831 | - max_insns = 128U; /* unknown function size */ |
2832 | - max_insns = min(128U, max_insns); |
2833 | + ip_end = (void *)ip + info->func_size; |
2834 | |
2835 | - for (i = 0; i < max_insns; i++, ip++) { |
2836 | + for (i = 0; i < max_insns && ip < ip_end; i++, ip++) { |
2837 | + if (is_mmips && mm_insn_16bit(ip->halfword[0])) { |
2838 | + insn.halfword[0] = 0; |
2839 | + insn.halfword[1] = ip->halfword[0]; |
2840 | + } else if (is_mmips) { |
2841 | + insn.halfword[0] = ip->halfword[1]; |
2842 | + insn.halfword[1] = ip->halfword[0]; |
2843 | + } else { |
2844 | + insn.word = ip->word; |
2845 | + } |
2846 | |
2847 | - if (is_jump_ins(ip)) |
2848 | + if (is_jump_ins(&insn)) |
2849 | break; |
2850 | + |
2851 | if (!info->frame_size) { |
2852 | - if (is_sp_move_ins(ip)) |
2853 | + if (is_sp_move_ins(&insn)) |
2854 | { |
2855 | #ifdef CONFIG_CPU_MICROMIPS |
2856 | if (mm_insn_16bit(ip->halfword[0])) |
2857 | @@ -345,11 +392,9 @@ static int get_frame_info(struct mips_frame_info *info) |
2858 | } |
2859 | continue; |
2860 | } |
2861 | - if (info->pc_offset == -1 && is_ra_save_ins(ip)) { |
2862 | - info->pc_offset = |
2863 | - ip->i_format.simmediate / sizeof(long); |
2864 | + if (info->pc_offset == -1 && |
2865 | + is_ra_save_ins(&insn, &info->pc_offset)) |
2866 | break; |
2867 | - } |
2868 | } |
2869 | if (info->frame_size && info->pc_offset >= 0) /* nested */ |
2870 | return 0; |
2871 | diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c |
2872 | index 80554e8f6037..3e390a4e3897 100644 |
2873 | --- a/arch/mips/lantiq/xway/sysctrl.c |
2874 | +++ b/arch/mips/lantiq/xway/sysctrl.c |
2875 | @@ -545,7 +545,7 @@ void __init ltq_soc_init(void) |
2876 | clkdev_add_pmu("1a800000.pcie", "msi", 1, 1, PMU1_PCIE2_MSI); |
2877 | clkdev_add_pmu("1a800000.pcie", "pdi", 1, 1, PMU1_PCIE2_PDI); |
2878 | clkdev_add_pmu("1a800000.pcie", "ctl", 1, 1, PMU1_PCIE2_CTL); |
2879 | - clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | PMU_PPE_DP); |
2880 | + clkdev_add_pmu("1e108000.eth", NULL, 0, 0, PMU_SWITCH | PMU_PPE_DP); |
2881 | clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); |
2882 | clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); |
2883 | } else if (of_machine_is_compatible("lantiq,ar10")) { |
2884 | @@ -553,7 +553,7 @@ void __init ltq_soc_init(void) |
2885 | ltq_ar10_fpi_hz(), ltq_ar10_pp32_hz()); |
2886 | clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0); |
2887 | clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1); |
2888 | - clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | |
2889 | + clkdev_add_pmu("1e108000.eth", NULL, 0, 0, PMU_SWITCH | |
2890 | PMU_PPE_DP | PMU_PPE_TC); |
2891 | clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); |
2892 | clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY); |
2893 | @@ -575,11 +575,11 @@ void __init ltq_soc_init(void) |
2894 | clkdev_add_pmu(NULL, "ahb", 1, 0, PMU_AHBM | PMU_AHBS); |
2895 | |
2896 | clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF); |
2897 | - clkdev_add_pmu("1e108000.eth", NULL, 1, 0, |
2898 | + clkdev_add_pmu("1e108000.eth", NULL, 0, 0, |
2899 | PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM | |
2900 | PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 | |
2901 | PMU_PPE_QSB | PMU_PPE_TOP); |
2902 | - clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY); |
2903 | + clkdev_add_pmu("1f203000.rcu", "gphy", 0, 0, PMU_GPHY); |
2904 | clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); |
2905 | clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); |
2906 | clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); |
2907 | diff --git a/arch/mips/mm/sc-ip22.c b/arch/mips/mm/sc-ip22.c |
2908 | index dc7c5a5214a9..efaf364fe581 100644 |
2909 | --- a/arch/mips/mm/sc-ip22.c |
2910 | +++ b/arch/mips/mm/sc-ip22.c |
2911 | @@ -31,26 +31,40 @@ static inline void indy_sc_wipe(unsigned long first, unsigned long last) |
2912 | unsigned long tmp; |
2913 | |
2914 | __asm__ __volatile__( |
2915 | - ".set\tpush\t\t\t# indy_sc_wipe\n\t" |
2916 | - ".set\tnoreorder\n\t" |
2917 | - ".set\tmips3\n\t" |
2918 | - ".set\tnoat\n\t" |
2919 | - "mfc0\t%2, $12\n\t" |
2920 | - "li\t$1, 0x80\t\t\t# Go 64 bit\n\t" |
2921 | - "mtc0\t$1, $12\n\t" |
2922 | - |
2923 | - "dli\t$1, 0x9000000080000000\n\t" |
2924 | - "or\t%0, $1\t\t\t# first line to flush\n\t" |
2925 | - "or\t%1, $1\t\t\t# last line to flush\n\t" |
2926 | - ".set\tat\n\t" |
2927 | - |
2928 | - "1:\tsw\t$0, 0(%0)\n\t" |
2929 | - "bne\t%0, %1, 1b\n\t" |
2930 | - " daddu\t%0, 32\n\t" |
2931 | - |
2932 | - "mtc0\t%2, $12\t\t\t# Back to 32 bit\n\t" |
2933 | - "nop; nop; nop; nop;\n\t" |
2934 | - ".set\tpop" |
2935 | + " .set push # indy_sc_wipe \n" |
2936 | + " .set noreorder \n" |
2937 | + " .set mips3 \n" |
2938 | + " .set noat \n" |
2939 | + " mfc0 %2, $12 \n" |
2940 | + " li $1, 0x80 # Go 64 bit \n" |
2941 | + " mtc0 $1, $12 \n" |
2942 | + " \n" |
2943 | + " # \n" |
2944 | + " # Open code a dli $1, 0x9000000080000000 \n" |
2945 | + " # \n" |
2946 | + " # Required because binutils 2.25 will happily accept \n" |
2947 | + " # 64 bit instructions in .set mips3 mode but puke on \n" |
2948 | + " # 64 bit constants when generating 32 bit ELF \n" |
2949 | + " # \n" |
2950 | + " lui $1,0x9000 \n" |
2951 | + " dsll $1,$1,0x10 \n" |
2952 | + " ori $1,$1,0x8000 \n" |
2953 | + " dsll $1,$1,0x10 \n" |
2954 | + " \n" |
2955 | + " or %0, $1 # first line to flush \n" |
2956 | + " or %1, $1 # last line to flush \n" |
2957 | + " .set at \n" |
2958 | + " \n" |
2959 | + "1: sw $0, 0(%0) \n" |
2960 | + " bne %0, %1, 1b \n" |
2961 | + " daddu %0, 32 \n" |
2962 | + " \n" |
2963 | + " mtc0 %2, $12 # Back to 32 bit \n" |
2964 | + " nop # pipeline hazard \n" |
2965 | + " nop \n" |
2966 | + " nop \n" |
2967 | + " nop \n" |
2968 | + " .set pop \n" |
2969 | : "=r" (first), "=r" (last), "=&r" (tmp) |
2970 | : "0" (first), "1" (last)); |
2971 | } |
2972 | diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c |
2973 | index 05e804cdecaa..fdf48785d3e9 100644 |
2974 | --- a/arch/powerpc/kernel/hw_breakpoint.c |
2975 | +++ b/arch/powerpc/kernel/hw_breakpoint.c |
2976 | @@ -227,8 +227,10 @@ int __kprobes hw_breakpoint_handler(struct die_args *args) |
2977 | rcu_read_lock(); |
2978 | |
2979 | bp = __this_cpu_read(bp_per_reg); |
2980 | - if (!bp) |
2981 | + if (!bp) { |
2982 | + rc = NOTIFY_DONE; |
2983 | goto out; |
2984 | + } |
2985 | info = counter_arch_bp(bp); |
2986 | |
2987 | /* |
2988 | diff --git a/crypto/testmgr.h b/crypto/testmgr.h |
2989 | index da0a8fd765f4..0e02c60a57b6 100644 |
2990 | --- a/crypto/testmgr.h |
2991 | +++ b/crypto/testmgr.h |
2992 | @@ -21778,7 +21778,7 @@ static struct aead_testvec aes_ccm_enc_tv_template[] = { |
2993 | "\x09\x75\x9a\x9b\x3c\x9b\x27\x39", |
2994 | .klen = 32, |
2995 | .iv = "\x03\xf9\xd9\x4e\x63\xb5\x3d\x9d" |
2996 | - "\x43\xf6\x1e\x50", |
2997 | + "\x43\xf6\x1e\x50\0\0\0\0", |
2998 | .assoc = "\x57\xf5\x6b\x8b\x57\x5c\x3d\x3b" |
2999 | "\x13\x02\x01\x0c\x83\x4c\x96\x35" |
3000 | "\x8e\xd6\x39\xcf\x7d\x14\x9b\x94" |
3001 | diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c |
3002 | index 59d8d0d14824..327f9e374b44 100644 |
3003 | --- a/drivers/bcma/main.c |
3004 | +++ b/drivers/bcma/main.c |
3005 | @@ -640,8 +640,11 @@ static int bcma_device_probe(struct device *dev) |
3006 | drv); |
3007 | int err = 0; |
3008 | |
3009 | + get_device(dev); |
3010 | if (adrv->probe) |
3011 | err = adrv->probe(core); |
3012 | + if (err) |
3013 | + put_device(dev); |
3014 | |
3015 | return err; |
3016 | } |
3017 | @@ -654,6 +657,7 @@ static int bcma_device_remove(struct device *dev) |
3018 | |
3019 | if (adrv->remove) |
3020 | adrv->remove(core); |
3021 | + put_device(dev); |
3022 | |
3023 | return 0; |
3024 | } |
3025 | diff --git a/drivers/block/loop.c b/drivers/block/loop.c |
3026 | index ab0b2dd3f629..cec36d5c24f5 100644 |
3027 | --- a/drivers/block/loop.c |
3028 | +++ b/drivers/block/loop.c |
3029 | @@ -1108,9 +1108,12 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) |
3030 | if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE) |
3031 | return -EINVAL; |
3032 | |
3033 | + /* I/O need to be drained during transfer transition */ |
3034 | + blk_mq_freeze_queue(lo->lo_queue); |
3035 | + |
3036 | err = loop_release_xfer(lo); |
3037 | if (err) |
3038 | - return err; |
3039 | + goto exit; |
3040 | |
3041 | if (info->lo_encrypt_type) { |
3042 | unsigned int type = info->lo_encrypt_type; |
3043 | @@ -1125,12 +1128,14 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) |
3044 | |
3045 | err = loop_init_xfer(lo, xfer, info); |
3046 | if (err) |
3047 | - return err; |
3048 | + goto exit; |
3049 | |
3050 | if (lo->lo_offset != info->lo_offset || |
3051 | lo->lo_sizelimit != info->lo_sizelimit) |
3052 | - if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) |
3053 | - return -EFBIG; |
3054 | + if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) { |
3055 | + err = -EFBIG; |
3056 | + goto exit; |
3057 | + } |
3058 | |
3059 | loop_config_discard(lo); |
3060 | |
3061 | @@ -1148,13 +1153,6 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) |
3062 | (info->lo_flags & LO_FLAGS_AUTOCLEAR)) |
3063 | lo->lo_flags ^= LO_FLAGS_AUTOCLEAR; |
3064 | |
3065 | - if ((info->lo_flags & LO_FLAGS_PARTSCAN) && |
3066 | - !(lo->lo_flags & LO_FLAGS_PARTSCAN)) { |
3067 | - lo->lo_flags |= LO_FLAGS_PARTSCAN; |
3068 | - lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN; |
3069 | - loop_reread_partitions(lo, lo->lo_device); |
3070 | - } |
3071 | - |
3072 | lo->lo_encrypt_key_size = info->lo_encrypt_key_size; |
3073 | lo->lo_init[0] = info->lo_init[0]; |
3074 | lo->lo_init[1] = info->lo_init[1]; |
3075 | @@ -1167,7 +1165,17 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) |
3076 | /* update dio if lo_offset or transfer is changed */ |
3077 | __loop_update_dio(lo, lo->use_dio); |
3078 | |
3079 | - return 0; |
3080 | + exit: |
3081 | + blk_mq_unfreeze_queue(lo->lo_queue); |
3082 | + |
3083 | + if (!err && (info->lo_flags & LO_FLAGS_PARTSCAN) && |
3084 | + !(lo->lo_flags & LO_FLAGS_PARTSCAN)) { |
3085 | + lo->lo_flags |= LO_FLAGS_PARTSCAN; |
3086 | + lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN; |
3087 | + loop_reread_partitions(lo, lo->lo_device); |
3088 | + } |
3089 | + |
3090 | + return err; |
3091 | } |
3092 | |
3093 | static int |
3094 | diff --git a/drivers/dma/ipu/ipu_irq.c b/drivers/dma/ipu/ipu_irq.c |
3095 | index dd184b50e5b4..284627806b88 100644 |
3096 | --- a/drivers/dma/ipu/ipu_irq.c |
3097 | +++ b/drivers/dma/ipu/ipu_irq.c |
3098 | @@ -272,7 +272,7 @@ static void ipu_irq_handler(struct irq_desc *desc) |
3099 | u32 status; |
3100 | int i, line; |
3101 | |
3102 | - for (i = IPU_IRQ_NR_FN_BANKS; i < IPU_IRQ_NR_BANKS; i++) { |
3103 | + for (i = 0; i < IPU_IRQ_NR_BANKS; i++) { |
3104 | struct ipu_irq_bank *bank = irq_bank + i; |
3105 | |
3106 | raw_spin_lock(&bank_lock); |
3107 | diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c |
3108 | index 63194a9a7189..89fd0113aa5c 100644 |
3109 | --- a/drivers/hv/hv.c |
3110 | +++ b/drivers/hv/hv.c |
3111 | @@ -422,7 +422,7 @@ int hv_synic_alloc(void) |
3112 | goto err; |
3113 | } |
3114 | |
3115 | - for_each_online_cpu(cpu) { |
3116 | + for_each_present_cpu(cpu) { |
3117 | hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC); |
3118 | if (hv_context.event_dpc[cpu] == NULL) { |
3119 | pr_err("Unable to allocate event dpc\n"); |
3120 | @@ -461,6 +461,8 @@ int hv_synic_alloc(void) |
3121 | pr_err("Unable to allocate post msg page\n"); |
3122 | goto err; |
3123 | } |
3124 | + |
3125 | + INIT_LIST_HEAD(&hv_context.percpu_list[cpu]); |
3126 | } |
3127 | |
3128 | return 0; |
3129 | @@ -485,7 +487,7 @@ void hv_synic_free(void) |
3130 | int cpu; |
3131 | |
3132 | kfree(hv_context.hv_numa_map); |
3133 | - for_each_online_cpu(cpu) |
3134 | + for_each_present_cpu(cpu) |
3135 | hv_synic_free_cpu(cpu); |
3136 | } |
3137 | |
3138 | @@ -555,8 +557,6 @@ void hv_synic_init(void *arg) |
3139 | rdmsrl(HV_X64_MSR_VP_INDEX, vp_index); |
3140 | hv_context.vp_index[cpu] = (u32)vp_index; |
3141 | |
3142 | - INIT_LIST_HEAD(&hv_context.percpu_list[cpu]); |
3143 | - |
3144 | /* |
3145 | * Register the per-cpu clockevent source. |
3146 | */ |
3147 | diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c |
3148 | index c37a71e13de0..1fb02dcbc500 100644 |
3149 | --- a/drivers/hv/hv_fcopy.c |
3150 | +++ b/drivers/hv/hv_fcopy.c |
3151 | @@ -61,6 +61,7 @@ static DECLARE_WORK(fcopy_send_work, fcopy_send_data); |
3152 | static const char fcopy_devname[] = "vmbus/hv_fcopy"; |
3153 | static u8 *recv_buffer; |
3154 | static struct hvutil_transport *hvt; |
3155 | +static struct completion release_event; |
3156 | /* |
3157 | * This state maintains the version number registered by the daemon. |
3158 | */ |
3159 | @@ -312,12 +313,14 @@ static void fcopy_on_reset(void) |
3160 | |
3161 | if (cancel_delayed_work_sync(&fcopy_timeout_work)) |
3162 | fcopy_respond_to_host(HV_E_FAIL); |
3163 | + complete(&release_event); |
3164 | } |
3165 | |
3166 | int hv_fcopy_init(struct hv_util_service *srv) |
3167 | { |
3168 | recv_buffer = srv->recv_buffer; |
3169 | |
3170 | + init_completion(&release_event); |
3171 | /* |
3172 | * When this driver loads, the user level daemon that |
3173 | * processes the host requests may not yet be running. |
3174 | @@ -339,4 +342,5 @@ void hv_fcopy_deinit(void) |
3175 | fcopy_transaction.state = HVUTIL_DEVICE_DYING; |
3176 | cancel_delayed_work_sync(&fcopy_timeout_work); |
3177 | hvutil_transport_destroy(hvt); |
3178 | + wait_for_completion(&release_event); |
3179 | } |
3180 | diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c |
3181 | index 2a3420c4ca59..ce4d3a935491 100644 |
3182 | --- a/drivers/hv/hv_kvp.c |
3183 | +++ b/drivers/hv/hv_kvp.c |
3184 | @@ -86,6 +86,7 @@ static DECLARE_WORK(kvp_sendkey_work, kvp_send_key); |
3185 | static const char kvp_devname[] = "vmbus/hv_kvp"; |
3186 | static u8 *recv_buffer; |
3187 | static struct hvutil_transport *hvt; |
3188 | +static struct completion release_event; |
3189 | /* |
3190 | * Register the kernel component with the user-level daemon. |
3191 | * As part of this registration, pass the LIC version number. |
3192 | @@ -682,6 +683,7 @@ static void kvp_on_reset(void) |
3193 | if (cancel_delayed_work_sync(&kvp_timeout_work)) |
3194 | kvp_respond_to_host(NULL, HV_E_FAIL); |
3195 | kvp_transaction.state = HVUTIL_DEVICE_INIT; |
3196 | + complete(&release_event); |
3197 | } |
3198 | |
3199 | int |
3200 | @@ -689,6 +691,7 @@ hv_kvp_init(struct hv_util_service *srv) |
3201 | { |
3202 | recv_buffer = srv->recv_buffer; |
3203 | |
3204 | + init_completion(&release_event); |
3205 | /* |
3206 | * When this driver loads, the user level daemon that |
3207 | * processes the host requests may not yet be running. |
3208 | @@ -711,4 +714,5 @@ void hv_kvp_deinit(void) |
3209 | cancel_delayed_work_sync(&kvp_timeout_work); |
3210 | cancel_work_sync(&kvp_sendkey_work); |
3211 | hvutil_transport_destroy(hvt); |
3212 | + wait_for_completion(&release_event); |
3213 | } |
3214 | diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c |
3215 | index 81882d4848bd..faad79ae318a 100644 |
3216 | --- a/drivers/hv/hv_snapshot.c |
3217 | +++ b/drivers/hv/hv_snapshot.c |
3218 | @@ -66,6 +66,7 @@ static int dm_reg_value; |
3219 | static const char vss_devname[] = "vmbus/hv_vss"; |
3220 | static __u8 *recv_buffer; |
3221 | static struct hvutil_transport *hvt; |
3222 | +static struct completion release_event; |
3223 | |
3224 | static void vss_send_op(struct work_struct *dummy); |
3225 | static void vss_timeout_func(struct work_struct *dummy); |
3226 | @@ -326,11 +327,13 @@ static void vss_on_reset(void) |
3227 | if (cancel_delayed_work_sync(&vss_timeout_work)) |
3228 | vss_respond_to_host(HV_E_FAIL); |
3229 | vss_transaction.state = HVUTIL_DEVICE_INIT; |
3230 | + complete(&release_event); |
3231 | } |
3232 | |
3233 | int |
3234 | hv_vss_init(struct hv_util_service *srv) |
3235 | { |
3236 | + init_completion(&release_event); |
3237 | if (vmbus_proto_version < VERSION_WIN8_1) { |
3238 | pr_warn("Integration service 'Backup (volume snapshot)'" |
3239 | " not supported on this host version.\n"); |
3240 | @@ -360,4 +363,5 @@ void hv_vss_deinit(void) |
3241 | cancel_delayed_work_sync(&vss_timeout_work); |
3242 | cancel_work_sync(&vss_send_op_work); |
3243 | hvutil_transport_destroy(hvt); |
3244 | + wait_for_completion(&release_event); |
3245 | } |
3246 | diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c |
3247 | index a0d7deeac62f..3f90985d545e 100644 |
3248 | --- a/drivers/iio/pressure/mpl115.c |
3249 | +++ b/drivers/iio/pressure/mpl115.c |
3250 | @@ -136,6 +136,7 @@ static const struct iio_chan_spec mpl115_channels[] = { |
3251 | { |
3252 | .type = IIO_TEMP, |
3253 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), |
3254 | + .info_mask_shared_by_type = |
3255 | BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), |
3256 | }, |
3257 | }; |
3258 | diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c |
3259 | index 01b2e0b18878..0f5b8767ec2e 100644 |
3260 | --- a/drivers/iio/pressure/mpl3115.c |
3261 | +++ b/drivers/iio/pressure/mpl3115.c |
3262 | @@ -182,7 +182,7 @@ static const struct iio_chan_spec mpl3115_channels[] = { |
3263 | { |
3264 | .type = IIO_PRESSURE, |
3265 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), |
3266 | - BIT(IIO_CHAN_INFO_SCALE), |
3267 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), |
3268 | .scan_index = 0, |
3269 | .scan_type = { |
3270 | .sign = 'u', |
3271 | @@ -195,7 +195,7 @@ static const struct iio_chan_spec mpl3115_channels[] = { |
3272 | { |
3273 | .type = IIO_TEMP, |
3274 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), |
3275 | - BIT(IIO_CHAN_INFO_SCALE), |
3276 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), |
3277 | .scan_index = 1, |
3278 | .scan_type = { |
3279 | .sign = 's', |
3280 | diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c |
3281 | index c9dcad6a53bf..3f5741a3e728 100644 |
3282 | --- a/drivers/infiniband/core/cma.c |
3283 | +++ b/drivers/infiniband/core/cma.c |
3284 | @@ -3349,6 +3349,9 @@ static int cma_accept_iw(struct rdma_id_private *id_priv, |
3285 | struct iw_cm_conn_param iw_param; |
3286 | int ret; |
3287 | |
3288 | + if (!conn_param) |
3289 | + return -EINVAL; |
3290 | + |
3291 | ret = cma_modify_qp_rtr(id_priv, conn_param); |
3292 | if (ret) |
3293 | return ret; |
3294 | diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c |
3295 | index 9413b0726237..f0fc6f7b5d98 100644 |
3296 | --- a/drivers/iommu/intel-iommu.c |
3297 | +++ b/drivers/iommu/intel-iommu.c |
3298 | @@ -3238,13 +3238,14 @@ static int __init init_dmars(void) |
3299 | iommu_identity_mapping |= IDENTMAP_GFX; |
3300 | #endif |
3301 | |
3302 | + check_tylersburg_isoch(); |
3303 | + |
3304 | if (iommu_identity_mapping) { |
3305 | ret = si_domain_init(hw_pass_through); |
3306 | if (ret) |
3307 | goto free_iommu; |
3308 | } |
3309 | |
3310 | - check_tylersburg_isoch(); |
3311 | |
3312 | /* |
3313 | * If we copied translations from a previous kernel in the kdump |
3314 | diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c |
3315 | index 515f83e7d9ab..b59615ddf6ba 100644 |
3316 | --- a/drivers/md/dm-cache-target.c |
3317 | +++ b/drivers/md/dm-cache-target.c |
3318 | @@ -251,7 +251,7 @@ struct cache { |
3319 | /* |
3320 | * Fields for converting from sectors to blocks. |
3321 | */ |
3322 | - uint32_t sectors_per_block; |
3323 | + sector_t sectors_per_block; |
3324 | int sectors_per_block_shift; |
3325 | |
3326 | spinlock_t lock; |
3327 | @@ -3547,11 +3547,11 @@ static void cache_status(struct dm_target *ti, status_type_t type, |
3328 | |
3329 | residency = policy_residency(cache->policy); |
3330 | |
3331 | - DMEMIT("%u %llu/%llu %u %llu/%llu %u %u %u %u %u %u %lu ", |
3332 | + DMEMIT("%u %llu/%llu %llu %llu/%llu %u %u %u %u %u %u %lu ", |
3333 | (unsigned)DM_CACHE_METADATA_BLOCK_SIZE, |
3334 | (unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata), |
3335 | (unsigned long long)nr_blocks_metadata, |
3336 | - cache->sectors_per_block, |
3337 | + (unsigned long long)cache->sectors_per_block, |
3338 | (unsigned long long) from_cblock(residency), |
3339 | (unsigned long long) from_cblock(cache->cache_size), |
3340 | (unsigned) atomic_read(&cache->stats.read_hit), |
3341 | diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c |
3342 | index 8289804ccd99..d5ea9f28ae70 100644 |
3343 | --- a/drivers/md/dm-stats.c |
3344 | +++ b/drivers/md/dm-stats.c |
3345 | @@ -175,6 +175,7 @@ static void dm_stat_free(struct rcu_head *head) |
3346 | int cpu; |
3347 | struct dm_stat *s = container_of(head, struct dm_stat, rcu_head); |
3348 | |
3349 | + kfree(s->histogram_boundaries); |
3350 | kfree(s->program_id); |
3351 | kfree(s->aux_data); |
3352 | for_each_possible_cpu(cpu) { |
3353 | diff --git a/drivers/md/linear.c b/drivers/md/linear.c |
3354 | index b7fe7e9fc777..6ba3227e29b2 100644 |
3355 | --- a/drivers/md/linear.c |
3356 | +++ b/drivers/md/linear.c |
3357 | @@ -52,18 +52,26 @@ static inline struct dev_info *which_dev(struct mddev *mddev, sector_t sector) |
3358 | return conf->disks + lo; |
3359 | } |
3360 | |
3361 | +/* |
3362 | + * In linear_congested() conf->raid_disks is used as a copy of |
3363 | + * mddev->raid_disks to iterate conf->disks[], because conf->raid_disks |
3364 | + * and conf->disks[] are created in linear_conf(), they are always |
3365 | + * consitent with each other, but mddev->raid_disks does not. |
3366 | + */ |
3367 | static int linear_congested(struct mddev *mddev, int bits) |
3368 | { |
3369 | struct linear_conf *conf; |
3370 | int i, ret = 0; |
3371 | |
3372 | - conf = mddev->private; |
3373 | + rcu_read_lock(); |
3374 | + conf = rcu_dereference(mddev->private); |
3375 | |
3376 | - for (i = 0; i < mddev->raid_disks && !ret ; i++) { |
3377 | + for (i = 0; i < conf->raid_disks && !ret ; i++) { |
3378 | struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev); |
3379 | ret |= bdi_congested(&q->backing_dev_info, bits); |
3380 | } |
3381 | |
3382 | + rcu_read_unlock(); |
3383 | return ret; |
3384 | } |
3385 | |
3386 | @@ -143,6 +151,19 @@ static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks) |
3387 | conf->disks[i-1].end_sector + |
3388 | conf->disks[i].rdev->sectors; |
3389 | |
3390 | + /* |
3391 | + * conf->raid_disks is copy of mddev->raid_disks. The reason to |
3392 | + * keep a copy of mddev->raid_disks in struct linear_conf is, |
3393 | + * mddev->raid_disks may not be consistent with pointers number of |
3394 | + * conf->disks[] when it is updated in linear_add() and used to |
3395 | + * iterate old conf->disks[] earray in linear_congested(). |
3396 | + * Here conf->raid_disks is always consitent with number of |
3397 | + * pointers in conf->disks[] array, and mddev->private is updated |
3398 | + * with rcu_assign_pointer() in linear_addr(), such race can be |
3399 | + * avoided. |
3400 | + */ |
3401 | + conf->raid_disks = raid_disks; |
3402 | + |
3403 | return conf; |
3404 | |
3405 | out: |
3406 | @@ -195,15 +216,23 @@ static int linear_add(struct mddev *mddev, struct md_rdev *rdev) |
3407 | if (!newconf) |
3408 | return -ENOMEM; |
3409 | |
3410 | + /* newconf->raid_disks already keeps a copy of * the increased |
3411 | + * value of mddev->raid_disks, WARN_ONCE() is just used to make |
3412 | + * sure of this. It is possible that oldconf is still referenced |
3413 | + * in linear_congested(), therefore kfree_rcu() is used to free |
3414 | + * oldconf until no one uses it anymore. |
3415 | + */ |
3416 | mddev_suspend(mddev); |
3417 | - oldconf = mddev->private; |
3418 | + oldconf = rcu_dereference(mddev->private); |
3419 | mddev->raid_disks++; |
3420 | - mddev->private = newconf; |
3421 | + WARN_ONCE(mddev->raid_disks != newconf->raid_disks, |
3422 | + "copied raid_disks doesn't match mddev->raid_disks"); |
3423 | + rcu_assign_pointer(mddev->private, newconf); |
3424 | md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); |
3425 | set_capacity(mddev->gendisk, mddev->array_sectors); |
3426 | mddev_resume(mddev); |
3427 | revalidate_disk(mddev->gendisk); |
3428 | - kfree(oldconf); |
3429 | + kfree_rcu(oldconf, rcu); |
3430 | return 0; |
3431 | } |
3432 | |
3433 | diff --git a/drivers/md/linear.h b/drivers/md/linear.h |
3434 | index b685ddd7d7f7..8d392e6098b3 100644 |
3435 | --- a/drivers/md/linear.h |
3436 | +++ b/drivers/md/linear.h |
3437 | @@ -10,6 +10,7 @@ struct linear_conf |
3438 | { |
3439 | struct rcu_head rcu; |
3440 | sector_t array_sectors; |
3441 | + int raid_disks; /* a copy of mddev->raid_disks */ |
3442 | struct dev_info disks[0]; |
3443 | }; |
3444 | #endif |
3445 | diff --git a/drivers/media/pci/dm1105/Kconfig b/drivers/media/pci/dm1105/Kconfig |
3446 | index 173daf0c0847..14fa7e40f2a6 100644 |
3447 | --- a/drivers/media/pci/dm1105/Kconfig |
3448 | +++ b/drivers/media/pci/dm1105/Kconfig |
3449 | @@ -1,6 +1,6 @@ |
3450 | config DVB_DM1105 |
3451 | tristate "SDMC DM1105 based PCI cards" |
3452 | - depends on DVB_CORE && PCI && I2C |
3453 | + depends on DVB_CORE && PCI && I2C && I2C_ALGOBIT |
3454 | select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT |
3455 | select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT |
3456 | select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT |
3457 | diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c |
3458 | index ba780c45f645..572bc043b62d 100644 |
3459 | --- a/drivers/media/platform/am437x/am437x-vpfe.c |
3460 | +++ b/drivers/media/platform/am437x/am437x-vpfe.c |
3461 | @@ -1576,7 +1576,7 @@ static int vpfe_s_fmt(struct file *file, void *priv, |
3462 | return -EBUSY; |
3463 | } |
3464 | |
3465 | - ret = vpfe_try_fmt(file, priv, &format); |
3466 | + ret = __vpfe_get_format(vpfe, &format, &bpp); |
3467 | if (ret) |
3468 | return ret; |
3469 | |
3470 | diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c |
3471 | index cfb868a48b5f..ff6feff21e94 100644 |
3472 | --- a/drivers/media/usb/uvc/uvc_queue.c |
3473 | +++ b/drivers/media/usb/uvc/uvc_queue.c |
3474 | @@ -416,7 +416,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, |
3475 | nextbuf = NULL; |
3476 | spin_unlock_irqrestore(&queue->irqlock, flags); |
3477 | |
3478 | - buf->state = buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE; |
3479 | + buf->state = buf->error ? UVC_BUF_STATE_ERROR : UVC_BUF_STATE_DONE; |
3480 | vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused); |
3481 | vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE); |
3482 | |
3483 | diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c |
3484 | index a731720f1d13..449b2a47f9a8 100644 |
3485 | --- a/drivers/net/can/usb/usb_8dev.c |
3486 | +++ b/drivers/net/can/usb/usb_8dev.c |
3487 | @@ -954,8 +954,8 @@ static int usb_8dev_probe(struct usb_interface *intf, |
3488 | for (i = 0; i < MAX_TX_URBS; i++) |
3489 | priv->tx_contexts[i].echo_index = MAX_TX_URBS; |
3490 | |
3491 | - priv->cmd_msg_buffer = kzalloc(sizeof(struct usb_8dev_cmd_msg), |
3492 | - GFP_KERNEL); |
3493 | + priv->cmd_msg_buffer = devm_kzalloc(&intf->dev, sizeof(struct usb_8dev_cmd_msg), |
3494 | + GFP_KERNEL); |
3495 | if (!priv->cmd_msg_buffer) |
3496 | goto cleanup_candev; |
3497 | |
3498 | @@ -969,7 +969,7 @@ static int usb_8dev_probe(struct usb_interface *intf, |
3499 | if (err) { |
3500 | netdev_err(netdev, |
3501 | "couldn't register CAN device: %d\n", err); |
3502 | - goto cleanup_cmd_msg_buffer; |
3503 | + goto cleanup_candev; |
3504 | } |
3505 | |
3506 | err = usb_8dev_cmd_version(priv, &version); |
3507 | @@ -990,9 +990,6 @@ static int usb_8dev_probe(struct usb_interface *intf, |
3508 | cleanup_unregister_candev: |
3509 | unregister_netdev(priv->netdev); |
3510 | |
3511 | -cleanup_cmd_msg_buffer: |
3512 | - kfree(priv->cmd_msg_buffer); |
3513 | - |
3514 | cleanup_candev: |
3515 | free_candev(netdev); |
3516 | |
3517 | diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c |
3518 | index dc44cfef7517..16e052d02c94 100644 |
3519 | --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c |
3520 | +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c |
3521 | @@ -502,8 +502,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
3522 | break; |
3523 | return -EOPNOTSUPP; |
3524 | default: |
3525 | - WARN_ON(1); |
3526 | - return -EINVAL; |
3527 | + return -EOPNOTSUPP; |
3528 | } |
3529 | |
3530 | mutex_lock(&ah->lock); |
3531 | diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h |
3532 | index 694ca2e680e5..74670e08e6da 100644 |
3533 | --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h |
3534 | +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h |
3535 | @@ -73,13 +73,13 @@ |
3536 | #define AR9300_OTP_BASE \ |
3537 | ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30000 : 0x14000) |
3538 | #define AR9300_OTP_STATUS \ |
3539 | - ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30018 : 0x15f18) |
3540 | + ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x31018 : 0x15f18) |
3541 | #define AR9300_OTP_STATUS_TYPE 0x7 |
3542 | #define AR9300_OTP_STATUS_VALID 0x4 |
3543 | #define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 |
3544 | #define AR9300_OTP_STATUS_SM_BUSY 0x1 |
3545 | #define AR9300_OTP_READ_DATA \ |
3546 | - ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3001c : 0x15f1c) |
3547 | + ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3101c : 0x15f1c) |
3548 | |
3549 | enum targetPowerHTRates { |
3550 | HT_TARGET_RATE_0_8_16, |
3551 | diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h |
3552 | index b42f4a963ef4..a660e40f2df1 100644 |
3553 | --- a/drivers/net/wireless/ath/ath9k/ath9k.h |
3554 | +++ b/drivers/net/wireless/ath/ath9k/ath9k.h |
3555 | @@ -959,6 +959,7 @@ struct ath_softc { |
3556 | struct survey_info *cur_survey; |
3557 | struct survey_info survey[ATH9K_NUM_CHANNELS]; |
3558 | |
3559 | + spinlock_t intr_lock; |
3560 | struct tasklet_struct intr_tq; |
3561 | struct tasklet_struct bcon_tasklet; |
3562 | struct ath_hw *sc_ah; |
3563 | diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c |
3564 | index bc70ce62bc03..0f5672f5c9ba 100644 |
3565 | --- a/drivers/net/wireless/ath/ath9k/init.c |
3566 | +++ b/drivers/net/wireless/ath/ath9k/init.c |
3567 | @@ -619,6 +619,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, |
3568 | common->bt_ant_diversity = 1; |
3569 | |
3570 | spin_lock_init(&common->cc_lock); |
3571 | + spin_lock_init(&sc->intr_lock); |
3572 | spin_lock_init(&sc->sc_serial_rw); |
3573 | spin_lock_init(&sc->sc_pm_lock); |
3574 | spin_lock_init(&sc->chan_lock); |
3575 | diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c |
3576 | index bba85d1a6cd1..d937c39b3a0b 100644 |
3577 | --- a/drivers/net/wireless/ath/ath9k/mac.c |
3578 | +++ b/drivers/net/wireless/ath/ath9k/mac.c |
3579 | @@ -805,21 +805,12 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah) |
3580 | } |
3581 | EXPORT_SYMBOL(ath9k_hw_disable_interrupts); |
3582 | |
3583 | -void ath9k_hw_enable_interrupts(struct ath_hw *ah) |
3584 | +static void __ath9k_hw_enable_interrupts(struct ath_hw *ah) |
3585 | { |
3586 | struct ath_common *common = ath9k_hw_common(ah); |
3587 | u32 sync_default = AR_INTR_SYNC_DEFAULT; |
3588 | u32 async_mask; |
3589 | |
3590 | - if (!(ah->imask & ATH9K_INT_GLOBAL)) |
3591 | - return; |
3592 | - |
3593 | - if (!atomic_inc_and_test(&ah->intr_ref_cnt)) { |
3594 | - ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", |
3595 | - atomic_read(&ah->intr_ref_cnt)); |
3596 | - return; |
3597 | - } |
3598 | - |
3599 | if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || |
3600 | AR_SREV_9561(ah)) |
3601 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; |
3602 | @@ -841,6 +832,39 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) |
3603 | ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", |
3604 | REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); |
3605 | } |
3606 | + |
3607 | +void ath9k_hw_resume_interrupts(struct ath_hw *ah) |
3608 | +{ |
3609 | + struct ath_common *common = ath9k_hw_common(ah); |
3610 | + |
3611 | + if (!(ah->imask & ATH9K_INT_GLOBAL)) |
3612 | + return; |
3613 | + |
3614 | + if (atomic_read(&ah->intr_ref_cnt) != 0) { |
3615 | + ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", |
3616 | + atomic_read(&ah->intr_ref_cnt)); |
3617 | + return; |
3618 | + } |
3619 | + |
3620 | + __ath9k_hw_enable_interrupts(ah); |
3621 | +} |
3622 | +EXPORT_SYMBOL(ath9k_hw_resume_interrupts); |
3623 | + |
3624 | +void ath9k_hw_enable_interrupts(struct ath_hw *ah) |
3625 | +{ |
3626 | + struct ath_common *common = ath9k_hw_common(ah); |
3627 | + |
3628 | + if (!(ah->imask & ATH9K_INT_GLOBAL)) |
3629 | + return; |
3630 | + |
3631 | + if (!atomic_inc_and_test(&ah->intr_ref_cnt)) { |
3632 | + ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", |
3633 | + atomic_read(&ah->intr_ref_cnt)); |
3634 | + return; |
3635 | + } |
3636 | + |
3637 | + __ath9k_hw_enable_interrupts(ah); |
3638 | +} |
3639 | EXPORT_SYMBOL(ath9k_hw_enable_interrupts); |
3640 | |
3641 | void ath9k_hw_set_interrupts(struct ath_hw *ah) |
3642 | diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h |
3643 | index 7fbf7f965f61..1b63d26f30ce 100644 |
3644 | --- a/drivers/net/wireless/ath/ath9k/mac.h |
3645 | +++ b/drivers/net/wireless/ath/ath9k/mac.h |
3646 | @@ -748,6 +748,7 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah); |
3647 | void ath9k_hw_enable_interrupts(struct ath_hw *ah); |
3648 | void ath9k_hw_disable_interrupts(struct ath_hw *ah); |
3649 | void ath9k_hw_kill_interrupts(struct ath_hw *ah); |
3650 | +void ath9k_hw_resume_interrupts(struct ath_hw *ah); |
3651 | |
3652 | void ar9002_hw_attach_mac_ops(struct ath_hw *ah); |
3653 | |
3654 | diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c |
3655 | index 8c5d2cf9c979..b114e57a823f 100644 |
3656 | --- a/drivers/net/wireless/ath/ath9k/main.c |
3657 | +++ b/drivers/net/wireless/ath/ath9k/main.c |
3658 | @@ -373,21 +373,20 @@ void ath9k_tasklet(unsigned long data) |
3659 | struct ath_common *common = ath9k_hw_common(ah); |
3660 | enum ath_reset_type type; |
3661 | unsigned long flags; |
3662 | - u32 status = sc->intrstatus; |
3663 | + u32 status; |
3664 | u32 rxmask; |
3665 | |
3666 | + spin_lock_irqsave(&sc->intr_lock, flags); |
3667 | + status = sc->intrstatus; |
3668 | + sc->intrstatus = 0; |
3669 | + spin_unlock_irqrestore(&sc->intr_lock, flags); |
3670 | + |
3671 | ath9k_ps_wakeup(sc); |
3672 | spin_lock(&sc->sc_pcu_lock); |
3673 | |
3674 | if (status & ATH9K_INT_FATAL) { |
3675 | type = RESET_TYPE_FATAL_INT; |
3676 | ath9k_queue_reset(sc, type); |
3677 | - |
3678 | - /* |
3679 | - * Increment the ref. counter here so that |
3680 | - * interrupts are enabled in the reset routine. |
3681 | - */ |
3682 | - atomic_inc(&ah->intr_ref_cnt); |
3683 | ath_dbg(common, RESET, "FATAL: Skipping interrupts\n"); |
3684 | goto out; |
3685 | } |
3686 | @@ -403,11 +402,6 @@ void ath9k_tasklet(unsigned long data) |
3687 | type = RESET_TYPE_BB_WATCHDOG; |
3688 | ath9k_queue_reset(sc, type); |
3689 | |
3690 | - /* |
3691 | - * Increment the ref. counter here so that |
3692 | - * interrupts are enabled in the reset routine. |
3693 | - */ |
3694 | - atomic_inc(&ah->intr_ref_cnt); |
3695 | ath_dbg(common, RESET, |
3696 | "BB_WATCHDOG: Skipping interrupts\n"); |
3697 | goto out; |
3698 | @@ -420,7 +414,6 @@ void ath9k_tasklet(unsigned long data) |
3699 | if ((sc->gtt_cnt >= MAX_GTT_CNT) && !ath9k_hw_check_alive(ah)) { |
3700 | type = RESET_TYPE_TX_GTT; |
3701 | ath9k_queue_reset(sc, type); |
3702 | - atomic_inc(&ah->intr_ref_cnt); |
3703 | ath_dbg(common, RESET, |
3704 | "GTT: Skipping interrupts\n"); |
3705 | goto out; |
3706 | @@ -477,7 +470,7 @@ void ath9k_tasklet(unsigned long data) |
3707 | ath9k_btcoex_handle_interrupt(sc, status); |
3708 | |
3709 | /* re-enable hardware interrupt */ |
3710 | - ath9k_hw_enable_interrupts(ah); |
3711 | + ath9k_hw_resume_interrupts(ah); |
3712 | out: |
3713 | spin_unlock(&sc->sc_pcu_lock); |
3714 | ath9k_ps_restore(sc); |
3715 | @@ -541,7 +534,9 @@ irqreturn_t ath_isr(int irq, void *dev) |
3716 | return IRQ_NONE; |
3717 | |
3718 | /* Cache the status */ |
3719 | - sc->intrstatus = status; |
3720 | + spin_lock(&sc->intr_lock); |
3721 | + sc->intrstatus |= status; |
3722 | + spin_unlock(&sc->intr_lock); |
3723 | |
3724 | if (status & SCHED_INTR) |
3725 | sched = true; |
3726 | @@ -587,7 +582,7 @@ chip_reset: |
3727 | |
3728 | if (sched) { |
3729 | /* turn off every interrupt */ |
3730 | - ath9k_hw_disable_interrupts(ah); |
3731 | + ath9k_hw_kill_interrupts(ah); |
3732 | tasklet_schedule(&sc->intr_tq); |
3733 | } |
3734 | |
3735 | diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.h b/drivers/net/wireless/realtek/rtlwifi/pci.h |
3736 | index 5da6703942d9..672f81ea02d0 100644 |
3737 | --- a/drivers/net/wireless/realtek/rtlwifi/pci.h |
3738 | +++ b/drivers/net/wireless/realtek/rtlwifi/pci.h |
3739 | @@ -275,10 +275,10 @@ struct mp_adapter { |
3740 | }; |
3741 | |
3742 | struct rtl_pci_priv { |
3743 | + struct bt_coexist_info bt_coexist; |
3744 | + struct rtl_led_ctl ledctl; |
3745 | struct rtl_pci dev; |
3746 | struct mp_adapter ndis_adapter; |
3747 | - struct rtl_led_ctl ledctl; |
3748 | - struct bt_coexist_info bt_coexist; |
3749 | }; |
3750 | |
3751 | #define rtl_pcipriv(hw) (((struct rtl_pci_priv *)(rtl_priv(hw))->priv)) |
3752 | diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c |
3753 | index 5f14308e8eb3..b1601441991d 100644 |
3754 | --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c |
3755 | +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c |
3756 | @@ -1003,7 +1003,7 @@ static void _rtl92ee_hw_configure(struct ieee80211_hw *hw) |
3757 | rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x100a); |
3758 | |
3759 | /* Note Data sheet don't define */ |
3760 | - rtl_write_word(rtlpriv, 0x4C7, 0x80); |
3761 | + rtl_write_byte(rtlpriv, 0x4C7, 0x80); |
3762 | |
3763 | rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20); |
3764 | |
3765 | diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c |
3766 | index bbb789f8990b..c2103e7a8132 100644 |
3767 | --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c |
3768 | +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c |
3769 | @@ -1127,7 +1127,7 @@ static u8 _rtl8821ae_dbi_read(struct rtl_priv *rtlpriv, u16 addr) |
3770 | } |
3771 | if (0 == tmp) { |
3772 | read_addr = REG_DBI_RDATA + addr % 4; |
3773 | - ret = rtl_read_word(rtlpriv, read_addr); |
3774 | + ret = rtl_read_byte(rtlpriv, read_addr); |
3775 | } |
3776 | return ret; |
3777 | } |
3778 | diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.h b/drivers/net/wireless/realtek/rtlwifi/usb.h |
3779 | index 685273ca9561..441c4412130c 100644 |
3780 | --- a/drivers/net/wireless/realtek/rtlwifi/usb.h |
3781 | +++ b/drivers/net/wireless/realtek/rtlwifi/usb.h |
3782 | @@ -150,8 +150,9 @@ struct rtl_usb { |
3783 | }; |
3784 | |
3785 | struct rtl_usb_priv { |
3786 | - struct rtl_usb dev; |
3787 | + struct bt_coexist_info bt_coexist; |
3788 | struct rtl_led_ctl ledctl; |
3789 | + struct rtl_usb dev; |
3790 | }; |
3791 | |
3792 | #define rtl_usbpriv(hw) (((struct rtl_usb_priv *)(rtl_priv(hw))->priv)) |
3793 | diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c |
3794 | index 732ac71b82cd..88dbbeb8569b 100644 |
3795 | --- a/drivers/regulator/core.c |
3796 | +++ b/drivers/regulator/core.c |
3797 | @@ -4273,12 +4273,13 @@ static void regulator_summary_show_subtree(struct seq_file *s, |
3798 | seq_puts(s, "\n"); |
3799 | |
3800 | list_for_each_entry(consumer, &rdev->consumer_list, list) { |
3801 | - if (consumer->dev->class == ®ulator_class) |
3802 | + if (consumer->dev && consumer->dev->class == ®ulator_class) |
3803 | continue; |
3804 | |
3805 | seq_printf(s, "%*s%-*s ", |
3806 | (level + 1) * 3 + 1, "", |
3807 | - 30 - (level + 1) * 3, dev_name(consumer->dev)); |
3808 | + 30 - (level + 1) * 3, |
3809 | + consumer->dev ? dev_name(consumer->dev) : "deviceless"); |
3810 | |
3811 | switch (rdev->desc->type) { |
3812 | case REGULATOR_VOLTAGE: |
3813 | diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c |
3814 | index c169a2cd4727..e29cc9fca0bf 100644 |
3815 | --- a/drivers/rtc/rtc-sun6i.c |
3816 | +++ b/drivers/rtc/rtc-sun6i.c |
3817 | @@ -37,9 +37,11 @@ |
3818 | |
3819 | /* Control register */ |
3820 | #define SUN6I_LOSC_CTRL 0x0000 |
3821 | +#define SUN6I_LOSC_CTRL_KEY (0x16aa << 16) |
3822 | #define SUN6I_LOSC_CTRL_ALM_DHMS_ACC BIT(9) |
3823 | #define SUN6I_LOSC_CTRL_RTC_HMS_ACC BIT(8) |
3824 | #define SUN6I_LOSC_CTRL_RTC_YMD_ACC BIT(7) |
3825 | +#define SUN6I_LOSC_CTRL_EXT_OSC BIT(0) |
3826 | #define SUN6I_LOSC_CTRL_ACC_MASK GENMASK(9, 7) |
3827 | |
3828 | /* RTC */ |
3829 | @@ -114,13 +116,17 @@ struct sun6i_rtc_dev { |
3830 | void __iomem *base; |
3831 | int irq; |
3832 | unsigned long alarm; |
3833 | + |
3834 | + spinlock_t lock; |
3835 | }; |
3836 | |
3837 | static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) |
3838 | { |
3839 | struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id; |
3840 | + irqreturn_t ret = IRQ_NONE; |
3841 | u32 val; |
3842 | |
3843 | + spin_lock(&chip->lock); |
3844 | val = readl(chip->base + SUN6I_ALRM_IRQ_STA); |
3845 | |
3846 | if (val & SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND) { |
3847 | @@ -129,10 +135,11 @@ static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) |
3848 | |
3849 | rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF); |
3850 | |
3851 | - return IRQ_HANDLED; |
3852 | + ret = IRQ_HANDLED; |
3853 | } |
3854 | + spin_unlock(&chip->lock); |
3855 | |
3856 | - return IRQ_NONE; |
3857 | + return ret; |
3858 | } |
3859 | |
3860 | static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) |
3861 | @@ -140,6 +147,7 @@ static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) |
3862 | u32 alrm_val = 0; |
3863 | u32 alrm_irq_val = 0; |
3864 | u32 alrm_wake_val = 0; |
3865 | + unsigned long flags; |
3866 | |
3867 | if (to) { |
3868 | alrm_val = SUN6I_ALRM_EN_CNT_EN; |
3869 | @@ -150,9 +158,11 @@ static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) |
3870 | chip->base + SUN6I_ALRM_IRQ_STA); |
3871 | } |
3872 | |
3873 | + spin_lock_irqsave(&chip->lock, flags); |
3874 | writel(alrm_val, chip->base + SUN6I_ALRM_EN); |
3875 | writel(alrm_irq_val, chip->base + SUN6I_ALRM_IRQ_EN); |
3876 | writel(alrm_wake_val, chip->base + SUN6I_ALARM_CONFIG); |
3877 | + spin_unlock_irqrestore(&chip->lock, flags); |
3878 | } |
3879 | |
3880 | static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) |
3881 | @@ -191,11 +201,15 @@ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) |
3882 | static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) |
3883 | { |
3884 | struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); |
3885 | + unsigned long flags; |
3886 | u32 alrm_st; |
3887 | u32 alrm_en; |
3888 | |
3889 | + spin_lock_irqsave(&chip->lock, flags); |
3890 | alrm_en = readl(chip->base + SUN6I_ALRM_IRQ_EN); |
3891 | alrm_st = readl(chip->base + SUN6I_ALRM_IRQ_STA); |
3892 | + spin_unlock_irqrestore(&chip->lock, flags); |
3893 | + |
3894 | wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN); |
3895 | wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN); |
3896 | rtc_time_to_tm(chip->alarm, &wkalrm->time); |
3897 | @@ -356,6 +370,7 @@ static int sun6i_rtc_probe(struct platform_device *pdev) |
3898 | chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); |
3899 | if (!chip) |
3900 | return -ENOMEM; |
3901 | + spin_lock_init(&chip->lock); |
3902 | |
3903 | platform_set_drvdata(pdev, chip); |
3904 | chip->dev = &pdev->dev; |
3905 | @@ -404,6 +419,10 @@ static int sun6i_rtc_probe(struct platform_device *pdev) |
3906 | /* disable alarm wakeup */ |
3907 | writel(0, chip->base + SUN6I_ALARM_CONFIG); |
3908 | |
3909 | + /* switch to the external, more precise, oscillator */ |
3910 | + writel(SUN6I_LOSC_CTRL_KEY | SUN6I_LOSC_CTRL_EXT_OSC, |
3911 | + chip->base + SUN6I_LOSC_CTRL); |
3912 | + |
3913 | chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, |
3914 | &sun6i_rtc_ops, THIS_MODULE); |
3915 | if (IS_ERR(chip->rtc)) { |
3916 | diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c |
3917 | index bc0203f3d243..e415e1c58eb5 100644 |
3918 | --- a/drivers/scsi/aacraid/src.c |
3919 | +++ b/drivers/scsi/aacraid/src.c |
3920 | @@ -413,16 +413,23 @@ static int aac_src_check_health(struct aac_dev *dev) |
3921 | u32 status = src_readl(dev, MUnit.OMR); |
3922 | |
3923 | /* |
3924 | + * Check to see if the board panic'd. |
3925 | + */ |
3926 | + if (unlikely(status & KERNEL_PANIC)) |
3927 | + goto err_blink; |
3928 | + |
3929 | + /* |
3930 | * Check to see if the board failed any self tests. |
3931 | */ |
3932 | if (unlikely(status & SELF_TEST_FAILED)) |
3933 | - return -1; |
3934 | + goto err_out; |
3935 | |
3936 | /* |
3937 | - * Check to see if the board panic'd. |
3938 | + * Check to see if the board failed any self tests. |
3939 | */ |
3940 | - if (unlikely(status & KERNEL_PANIC)) |
3941 | - return (status >> 16) & 0xFF; |
3942 | + if (unlikely(status & MONITOR_PANIC)) |
3943 | + goto err_out; |
3944 | + |
3945 | /* |
3946 | * Wait for the adapter to be up and running. |
3947 | */ |
3948 | @@ -432,6 +439,12 @@ static int aac_src_check_health(struct aac_dev *dev) |
3949 | * Everything is OK |
3950 | */ |
3951 | return 0; |
3952 | + |
3953 | +err_out: |
3954 | + return -1; |
3955 | + |
3956 | +err_blink: |
3957 | + return (status > 16) & 0xFF; |
3958 | } |
3959 | |
3960 | /** |
3961 | diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h |
3962 | index 33ec4fa39ccb..f224cdb2fce4 100644 |
3963 | --- a/drivers/scsi/lpfc/lpfc_hw4.h |
3964 | +++ b/drivers/scsi/lpfc/lpfc_hw4.h |
3965 | @@ -1182,6 +1182,7 @@ struct lpfc_mbx_wq_create { |
3966 | #define lpfc_mbx_wq_create_page_size_SHIFT 0 |
3967 | #define lpfc_mbx_wq_create_page_size_MASK 0x000000FF |
3968 | #define lpfc_mbx_wq_create_page_size_WORD word1 |
3969 | +#define LPFC_WQ_PAGE_SIZE_4096 0x1 |
3970 | #define lpfc_mbx_wq_create_wqe_size_SHIFT 8 |
3971 | #define lpfc_mbx_wq_create_wqe_size_MASK 0x0000000F |
3972 | #define lpfc_mbx_wq_create_wqe_size_WORD word1 |
3973 | @@ -1253,6 +1254,7 @@ struct rq_context { |
3974 | #define lpfc_rq_context_page_size_SHIFT 0 /* Version 1 Only */ |
3975 | #define lpfc_rq_context_page_size_MASK 0x000000FF |
3976 | #define lpfc_rq_context_page_size_WORD word0 |
3977 | +#define LPFC_RQ_PAGE_SIZE_4096 0x1 |
3978 | uint32_t reserved1; |
3979 | uint32_t word2; |
3980 | #define lpfc_rq_context_cq_id_SHIFT 16 |
3981 | diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c |
3982 | index 92dfd6a5178c..f5aeda8f014f 100644 |
3983 | --- a/drivers/scsi/lpfc/lpfc_sli.c |
3984 | +++ b/drivers/scsi/lpfc/lpfc_sli.c |
3985 | @@ -13475,7 +13475,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, |
3986 | LPFC_WQ_WQE_SIZE_128); |
3987 | bf_set(lpfc_mbx_wq_create_page_size, |
3988 | &wq_create->u.request_1, |
3989 | - (PAGE_SIZE/SLI4_PAGE_SIZE)); |
3990 | + LPFC_WQ_PAGE_SIZE_4096); |
3991 | page = wq_create->u.request_1.page; |
3992 | break; |
3993 | } |
3994 | @@ -13501,8 +13501,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, |
3995 | LPFC_WQ_WQE_SIZE_128); |
3996 | break; |
3997 | } |
3998 | - bf_set(lpfc_mbx_wq_create_page_size, &wq_create->u.request_1, |
3999 | - (PAGE_SIZE/SLI4_PAGE_SIZE)); |
4000 | + bf_set(lpfc_mbx_wq_create_page_size, |
4001 | + &wq_create->u.request_1, |
4002 | + LPFC_WQ_PAGE_SIZE_4096); |
4003 | page = wq_create->u.request_1.page; |
4004 | break; |
4005 | default: |
4006 | @@ -13688,7 +13689,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, |
4007 | LPFC_RQE_SIZE_8); |
4008 | bf_set(lpfc_rq_context_page_size, |
4009 | &rq_create->u.request.context, |
4010 | - (PAGE_SIZE/SLI4_PAGE_SIZE)); |
4011 | + LPFC_RQ_PAGE_SIZE_4096); |
4012 | } else { |
4013 | switch (hrq->entry_count) { |
4014 | default: |
4015 | diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c |
4016 | index e7649ed3f667..4d655b568269 100644 |
4017 | --- a/drivers/scsi/scsi_dh.c |
4018 | +++ b/drivers/scsi/scsi_dh.c |
4019 | @@ -289,20 +289,6 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) |
4020 | } |
4021 | EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); |
4022 | |
4023 | -static struct scsi_device *get_sdev_from_queue(struct request_queue *q) |
4024 | -{ |
4025 | - struct scsi_device *sdev; |
4026 | - unsigned long flags; |
4027 | - |
4028 | - spin_lock_irqsave(q->queue_lock, flags); |
4029 | - sdev = q->queuedata; |
4030 | - if (!sdev || !get_device(&sdev->sdev_gendev)) |
4031 | - sdev = NULL; |
4032 | - spin_unlock_irqrestore(q->queue_lock, flags); |
4033 | - |
4034 | - return sdev; |
4035 | -} |
4036 | - |
4037 | /* |
4038 | * scsi_dh_activate - activate the path associated with the scsi_device |
4039 | * corresponding to the given request queue. |
4040 | @@ -321,7 +307,7 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) |
4041 | struct scsi_device *sdev; |
4042 | int err = SCSI_DH_NOSYS; |
4043 | |
4044 | - sdev = get_sdev_from_queue(q); |
4045 | + sdev = scsi_device_from_queue(q); |
4046 | if (!sdev) { |
4047 | if (fn) |
4048 | fn(data, err); |
4049 | @@ -368,7 +354,7 @@ int scsi_dh_set_params(struct request_queue *q, const char *params) |
4050 | struct scsi_device *sdev; |
4051 | int err = -SCSI_DH_NOSYS; |
4052 | |
4053 | - sdev = get_sdev_from_queue(q); |
4054 | + sdev = scsi_device_from_queue(q); |
4055 | if (!sdev) |
4056 | return err; |
4057 | |
4058 | @@ -391,7 +377,7 @@ int scsi_dh_attach(struct request_queue *q, const char *name) |
4059 | struct scsi_device_handler *scsi_dh; |
4060 | int err = 0; |
4061 | |
4062 | - sdev = get_sdev_from_queue(q); |
4063 | + sdev = scsi_device_from_queue(q); |
4064 | if (!sdev) |
4065 | return -ENODEV; |
4066 | |
4067 | @@ -429,7 +415,7 @@ const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp) |
4068 | struct scsi_device *sdev; |
4069 | const char *handler_name = NULL; |
4070 | |
4071 | - sdev = get_sdev_from_queue(q); |
4072 | + sdev = scsi_device_from_queue(q); |
4073 | if (!sdev) |
4074 | return NULL; |
4075 | |
4076 | diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c |
4077 | index 8558e3886960..887045ae5d10 100644 |
4078 | --- a/drivers/scsi/scsi_lib.c |
4079 | +++ b/drivers/scsi/scsi_lib.c |
4080 | @@ -2215,6 +2215,29 @@ void scsi_mq_destroy_tags(struct Scsi_Host *shost) |
4081 | blk_mq_free_tag_set(&shost->tag_set); |
4082 | } |
4083 | |
4084 | +/** |
4085 | + * scsi_device_from_queue - return sdev associated with a request_queue |
4086 | + * @q: The request queue to return the sdev from |
4087 | + * |
4088 | + * Return the sdev associated with a request queue or NULL if the |
4089 | + * request_queue does not reference a SCSI device. |
4090 | + */ |
4091 | +struct scsi_device *scsi_device_from_queue(struct request_queue *q) |
4092 | +{ |
4093 | + struct scsi_device *sdev = NULL; |
4094 | + |
4095 | + if (q->mq_ops) { |
4096 | + if (q->mq_ops == &scsi_mq_ops) |
4097 | + sdev = q->queuedata; |
4098 | + } else if (q->request_fn == scsi_request_fn) |
4099 | + sdev = q->queuedata; |
4100 | + if (!sdev || !get_device(&sdev->sdev_gendev)) |
4101 | + sdev = NULL; |
4102 | + |
4103 | + return sdev; |
4104 | +} |
4105 | +EXPORT_SYMBOL_GPL(scsi_device_from_queue); |
4106 | + |
4107 | /* |
4108 | * Function: scsi_block_requests() |
4109 | * |
4110 | diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c |
4111 | index 6ee50742f6a5..78430ef28ea4 100644 |
4112 | --- a/drivers/scsi/sd.c |
4113 | +++ b/drivers/scsi/sd.c |
4114 | @@ -1398,11 +1398,15 @@ static int media_not_present(struct scsi_disk *sdkp, |
4115 | **/ |
4116 | static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing) |
4117 | { |
4118 | - struct scsi_disk *sdkp = scsi_disk(disk); |
4119 | - struct scsi_device *sdp = sdkp->device; |
4120 | + struct scsi_disk *sdkp = scsi_disk_get(disk); |
4121 | + struct scsi_device *sdp; |
4122 | struct scsi_sense_hdr *sshdr = NULL; |
4123 | int retval; |
4124 | |
4125 | + if (!sdkp) |
4126 | + return 0; |
4127 | + |
4128 | + sdp = sdkp->device; |
4129 | SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_check_events\n")); |
4130 | |
4131 | /* |
4132 | @@ -1459,6 +1463,7 @@ out: |
4133 | kfree(sshdr); |
4134 | retval = sdp->changed ? DISK_EVENT_MEDIA_CHANGE : 0; |
4135 | sdp->changed = 0; |
4136 | + scsi_disk_put(sdkp); |
4137 | return retval; |
4138 | } |
4139 | |
4140 | diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c |
4141 | index 0f636cc4c809..cd5c1c060481 100644 |
4142 | --- a/drivers/scsi/storvsc_drv.c |
4143 | +++ b/drivers/scsi/storvsc_drv.c |
4144 | @@ -135,6 +135,8 @@ struct hv_fc_wwn_packet { |
4145 | #define SRB_FLAGS_PORT_DRIVER_RESERVED 0x0F000000 |
4146 | #define SRB_FLAGS_CLASS_DRIVER_RESERVED 0xF0000000 |
4147 | |
4148 | +#define SP_UNTAGGED ((unsigned char) ~0) |
4149 | +#define SRB_SIMPLE_TAG_REQUEST 0x20 |
4150 | |
4151 | /* |
4152 | * Platform neutral description of a scsi request - |
4153 | @@ -354,6 +356,7 @@ enum storvsc_request_type { |
4154 | #define SRB_STATUS_SUCCESS 0x01 |
4155 | #define SRB_STATUS_ABORTED 0x02 |
4156 | #define SRB_STATUS_ERROR 0x04 |
4157 | +#define SRB_STATUS_DATA_OVERRUN 0x12 |
4158 | |
4159 | #define SRB_STATUS(status) \ |
4160 | (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN)) |
4161 | @@ -864,6 +867,13 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, |
4162 | switch (SRB_STATUS(vm_srb->srb_status)) { |
4163 | case SRB_STATUS_ERROR: |
4164 | /* |
4165 | + * Let upper layer deal with error when |
4166 | + * sense message is present. |
4167 | + */ |
4168 | + |
4169 | + if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) |
4170 | + break; |
4171 | + /* |
4172 | * If there is an error; offline the device since all |
4173 | * error recovery strategies would have already been |
4174 | * deployed on the host side. However, if the command |
4175 | @@ -927,6 +937,7 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) |
4176 | struct hv_host_device *host_dev = shost_priv(scmnd->device->host); |
4177 | struct scsi_sense_hdr sense_hdr; |
4178 | struct vmscsi_request *vm_srb; |
4179 | + u32 data_transfer_length; |
4180 | struct Scsi_Host *host; |
4181 | struct storvsc_device *stor_dev; |
4182 | struct hv_device *dev = host_dev->dev; |
4183 | @@ -937,6 +948,7 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) |
4184 | host = stor_dev->host; |
4185 | |
4186 | vm_srb = &cmd_request->vstor_packet.vm_srb; |
4187 | + data_transfer_length = vm_srb->data_transfer_length; |
4188 | |
4189 | scmnd->result = vm_srb->scsi_status; |
4190 | |
4191 | @@ -947,13 +959,20 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) |
4192 | &sense_hdr); |
4193 | } |
4194 | |
4195 | - if (vm_srb->srb_status != SRB_STATUS_SUCCESS) |
4196 | + if (vm_srb->srb_status != SRB_STATUS_SUCCESS) { |
4197 | storvsc_handle_error(vm_srb, scmnd, host, sense_hdr.asc, |
4198 | sense_hdr.ascq); |
4199 | + /* |
4200 | + * The Windows driver set data_transfer_length on |
4201 | + * SRB_STATUS_DATA_OVERRUN. On other errors, this value |
4202 | + * is untouched. In these cases we set it to 0. |
4203 | + */ |
4204 | + if (vm_srb->srb_status != SRB_STATUS_DATA_OVERRUN) |
4205 | + data_transfer_length = 0; |
4206 | + } |
4207 | |
4208 | scsi_set_resid(scmnd, |
4209 | - cmd_request->payload->range.len - |
4210 | - vm_srb->data_transfer_length); |
4211 | + cmd_request->payload->range.len - data_transfer_length); |
4212 | |
4213 | scmnd->scsi_done(scmnd); |
4214 | |
4215 | @@ -1409,6 +1428,13 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) |
4216 | vm_srb->win8_extension.srb_flags |= |
4217 | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; |
4218 | |
4219 | + if (scmnd->device->tagged_supported) { |
4220 | + vm_srb->win8_extension.srb_flags |= |
4221 | + (SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE); |
4222 | + vm_srb->win8_extension.queue_tag = SP_UNTAGGED; |
4223 | + vm_srb->win8_extension.queue_action = SRB_SIMPLE_TAG_REQUEST; |
4224 | + } |
4225 | + |
4226 | /* Build the SRB */ |
4227 | switch (scmnd->sc_data_direction) { |
4228 | case DMA_TO_DEVICE: |
4229 | diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c |
4230 | index 110b8c0b6cd7..0f2fe34e14c2 100644 |
4231 | --- a/drivers/staging/rtl8188eu/core/rtw_recv.c |
4232 | +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c |
4233 | @@ -1405,6 +1405,9 @@ static int wlanhdr_to_ethhdr(struct recv_frame *precvframe) |
4234 | ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0))); |
4235 | } |
4236 | |
4237 | + if (!ptr) |
4238 | + return _FAIL; |
4239 | + |
4240 | memcpy(ptr, pattrib->dst, ETH_ALEN); |
4241 | memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN); |
4242 | |
4243 | diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c |
4244 | index 4ff530155187..04ac23cc47a8 100644 |
4245 | --- a/drivers/staging/rtl8712/rtl871x_recv.c |
4246 | +++ b/drivers/staging/rtl8712/rtl871x_recv.c |
4247 | @@ -641,11 +641,16 @@ sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) |
4248 | /* append rx status for mp test packets */ |
4249 | ptr = recvframe_pull(precvframe, (rmv_len - |
4250 | sizeof(struct ethhdr) + 2) - 24); |
4251 | + if (!ptr) |
4252 | + return _FAIL; |
4253 | memcpy(ptr, get_rxmem(precvframe), 24); |
4254 | ptr += 24; |
4255 | - } else |
4256 | + } else { |
4257 | ptr = recvframe_pull(precvframe, (rmv_len - |
4258 | sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0))); |
4259 | + if (!ptr) |
4260 | + return _FAIL; |
4261 | + } |
4262 | |
4263 | memcpy(ptr, pattrib->dst, ETH_ALEN); |
4264 | memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN); |
4265 | diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c |
4266 | index bd810c109277..6ed80b05d674 100644 |
4267 | --- a/drivers/target/iscsi/iscsi_target.c |
4268 | +++ b/drivers/target/iscsi/iscsi_target.c |
4269 | @@ -3436,7 +3436,7 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd, |
4270 | |
4271 | if ((tpg->tpg_attrib.generate_node_acls == 0) && |
4272 | (tpg->tpg_attrib.demo_mode_discovery == 0) && |
4273 | - (!core_tpg_get_initiator_node_acl(&tpg->tpg_se_tpg, |
4274 | + (!target_tpg_has_node_acl(&tpg->tpg_se_tpg, |
4275 | cmd->conn->sess->sess_ops->InitiatorName))) { |
4276 | continue; |
4277 | } |
4278 | diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c |
4279 | index 5fb9dd7f08bb..028854cda97b 100644 |
4280 | --- a/drivers/target/target_core_tpg.c |
4281 | +++ b/drivers/target/target_core_tpg.c |
4282 | @@ -75,9 +75,21 @@ struct se_node_acl *core_tpg_get_initiator_node_acl( |
4283 | unsigned char *initiatorname) |
4284 | { |
4285 | struct se_node_acl *acl; |
4286 | - |
4287 | + /* |
4288 | + * Obtain se_node_acl->acl_kref using fabric driver provided |
4289 | + * initiatorname[] during node acl endpoint lookup driven by |
4290 | + * new se_session login. |
4291 | + * |
4292 | + * The reference is held until se_session shutdown -> release |
4293 | + * occurs via fabric driver invoked transport_deregister_session() |
4294 | + * or transport_free_session() code. |
4295 | + */ |
4296 | mutex_lock(&tpg->acl_node_mutex); |
4297 | acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); |
4298 | + if (acl) { |
4299 | + if (!kref_get_unless_zero(&acl->acl_kref)) |
4300 | + acl = NULL; |
4301 | + } |
4302 | mutex_unlock(&tpg->acl_node_mutex); |
4303 | |
4304 | return acl; |
4305 | @@ -232,6 +244,25 @@ static void target_add_node_acl(struct se_node_acl *acl) |
4306 | acl->initiatorname); |
4307 | } |
4308 | |
4309 | +bool target_tpg_has_node_acl(struct se_portal_group *tpg, |
4310 | + const char *initiatorname) |
4311 | +{ |
4312 | + struct se_node_acl *acl; |
4313 | + bool found = false; |
4314 | + |
4315 | + mutex_lock(&tpg->acl_node_mutex); |
4316 | + list_for_each_entry(acl, &tpg->acl_node_list, acl_list) { |
4317 | + if (!strcmp(acl->initiatorname, initiatorname)) { |
4318 | + found = true; |
4319 | + break; |
4320 | + } |
4321 | + } |
4322 | + mutex_unlock(&tpg->acl_node_mutex); |
4323 | + |
4324 | + return found; |
4325 | +} |
4326 | +EXPORT_SYMBOL(target_tpg_has_node_acl); |
4327 | + |
4328 | struct se_node_acl *core_tpg_check_initiator_node_acl( |
4329 | struct se_portal_group *tpg, |
4330 | unsigned char *initiatorname) |
4331 | @@ -248,6 +279,15 @@ struct se_node_acl *core_tpg_check_initiator_node_acl( |
4332 | acl = target_alloc_node_acl(tpg, initiatorname); |
4333 | if (!acl) |
4334 | return NULL; |
4335 | + /* |
4336 | + * When allocating a dynamically generated node_acl, go ahead |
4337 | + * and take the extra kref now before returning to the fabric |
4338 | + * driver caller. |
4339 | + * |
4340 | + * Note this reference will be released at session shutdown |
4341 | + * time within transport_free_session() code. |
4342 | + */ |
4343 | + kref_get(&acl->acl_kref); |
4344 | acl->dynamic_node_acl = 1; |
4345 | |
4346 | /* |
4347 | diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c |
4348 | index aa517c4fadb9..befe22744802 100644 |
4349 | --- a/drivers/target/target_core_transport.c |
4350 | +++ b/drivers/target/target_core_transport.c |
4351 | @@ -341,7 +341,6 @@ void __transport_register_session( |
4352 | &buf[0], PR_REG_ISID_LEN); |
4353 | se_sess->sess_bin_isid = get_unaligned_be64(&buf[0]); |
4354 | } |
4355 | - kref_get(&se_nacl->acl_kref); |
4356 | |
4357 | spin_lock_irq(&se_nacl->nacl_sess_lock); |
4358 | /* |
4359 | @@ -424,14 +423,27 @@ static void target_complete_nacl(struct kref *kref) |
4360 | { |
4361 | struct se_node_acl *nacl = container_of(kref, |
4362 | struct se_node_acl, acl_kref); |
4363 | + struct se_portal_group *se_tpg = nacl->se_tpg; |
4364 | |
4365 | - complete(&nacl->acl_free_comp); |
4366 | + if (!nacl->dynamic_stop) { |
4367 | + complete(&nacl->acl_free_comp); |
4368 | + return; |
4369 | + } |
4370 | + |
4371 | + mutex_lock(&se_tpg->acl_node_mutex); |
4372 | + list_del(&nacl->acl_list); |
4373 | + mutex_unlock(&se_tpg->acl_node_mutex); |
4374 | + |
4375 | + core_tpg_wait_for_nacl_pr_ref(nacl); |
4376 | + core_free_device_list_for_node(nacl, se_tpg); |
4377 | + kfree(nacl); |
4378 | } |
4379 | |
4380 | void target_put_nacl(struct se_node_acl *nacl) |
4381 | { |
4382 | kref_put(&nacl->acl_kref, target_complete_nacl); |
4383 | } |
4384 | +EXPORT_SYMBOL(target_put_nacl); |
4385 | |
4386 | void transport_deregister_session_configfs(struct se_session *se_sess) |
4387 | { |
4388 | @@ -464,6 +476,42 @@ EXPORT_SYMBOL(transport_deregister_session_configfs); |
4389 | |
4390 | void transport_free_session(struct se_session *se_sess) |
4391 | { |
4392 | + struct se_node_acl *se_nacl = se_sess->se_node_acl; |
4393 | + |
4394 | + /* |
4395 | + * Drop the se_node_acl->nacl_kref obtained from within |
4396 | + * core_tpg_get_initiator_node_acl(). |
4397 | + */ |
4398 | + if (se_nacl) { |
4399 | + struct se_portal_group *se_tpg = se_nacl->se_tpg; |
4400 | + const struct target_core_fabric_ops *se_tfo = se_tpg->se_tpg_tfo; |
4401 | + unsigned long flags; |
4402 | + |
4403 | + se_sess->se_node_acl = NULL; |
4404 | + |
4405 | + /* |
4406 | + * Also determine if we need to drop the extra ->cmd_kref if |
4407 | + * it had been previously dynamically generated, and |
4408 | + * the endpoint is not caching dynamic ACLs. |
4409 | + */ |
4410 | + mutex_lock(&se_tpg->acl_node_mutex); |
4411 | + if (se_nacl->dynamic_node_acl && |
4412 | + !se_tfo->tpg_check_demo_mode_cache(se_tpg)) { |
4413 | + spin_lock_irqsave(&se_nacl->nacl_sess_lock, flags); |
4414 | + if (list_empty(&se_nacl->acl_sess_list)) |
4415 | + se_nacl->dynamic_stop = true; |
4416 | + spin_unlock_irqrestore(&se_nacl->nacl_sess_lock, flags); |
4417 | + |
4418 | + if (se_nacl->dynamic_stop) |
4419 | + list_del(&se_nacl->acl_list); |
4420 | + } |
4421 | + mutex_unlock(&se_tpg->acl_node_mutex); |
4422 | + |
4423 | + if (se_nacl->dynamic_stop) |
4424 | + target_put_nacl(se_nacl); |
4425 | + |
4426 | + target_put_nacl(se_nacl); |
4427 | + } |
4428 | if (se_sess->sess_cmd_map) { |
4429 | percpu_ida_destroy(&se_sess->sess_tag_pool); |
4430 | kvfree(se_sess->sess_cmd_map); |
4431 | @@ -475,16 +523,12 @@ EXPORT_SYMBOL(transport_free_session); |
4432 | void transport_deregister_session(struct se_session *se_sess) |
4433 | { |
4434 | struct se_portal_group *se_tpg = se_sess->se_tpg; |
4435 | - const struct target_core_fabric_ops *se_tfo; |
4436 | - struct se_node_acl *se_nacl; |
4437 | unsigned long flags; |
4438 | - bool comp_nacl = true, drop_nacl = false; |
4439 | |
4440 | if (!se_tpg) { |
4441 | transport_free_session(se_sess); |
4442 | return; |
4443 | } |
4444 | - se_tfo = se_tpg->se_tpg_tfo; |
4445 | |
4446 | spin_lock_irqsave(&se_tpg->session_lock, flags); |
4447 | list_del(&se_sess->sess_list); |
4448 | @@ -492,37 +536,16 @@ void transport_deregister_session(struct se_session *se_sess) |
4449 | se_sess->fabric_sess_ptr = NULL; |
4450 | spin_unlock_irqrestore(&se_tpg->session_lock, flags); |
4451 | |
4452 | - /* |
4453 | - * Determine if we need to do extra work for this initiator node's |
4454 | - * struct se_node_acl if it had been previously dynamically generated. |
4455 | - */ |
4456 | - se_nacl = se_sess->se_node_acl; |
4457 | - |
4458 | - mutex_lock(&se_tpg->acl_node_mutex); |
4459 | - if (se_nacl && se_nacl->dynamic_node_acl) { |
4460 | - if (!se_tfo->tpg_check_demo_mode_cache(se_tpg)) { |
4461 | - list_del(&se_nacl->acl_list); |
4462 | - se_tpg->num_node_acls--; |
4463 | - drop_nacl = true; |
4464 | - } |
4465 | - } |
4466 | - mutex_unlock(&se_tpg->acl_node_mutex); |
4467 | - |
4468 | - if (drop_nacl) { |
4469 | - core_tpg_wait_for_nacl_pr_ref(se_nacl); |
4470 | - core_free_device_list_for_node(se_nacl, se_tpg); |
4471 | - kfree(se_nacl); |
4472 | - comp_nacl = false; |
4473 | - } |
4474 | pr_debug("TARGET_CORE[%s]: Deregistered fabric_sess\n", |
4475 | se_tpg->se_tpg_tfo->get_fabric_name()); |
4476 | /* |
4477 | * If last kref is dropping now for an explicit NodeACL, awake sleeping |
4478 | * ->acl_free_comp caller to wakeup configfs se_node_acl->acl_group |
4479 | - * removal context. |
4480 | + * removal context from within transport_free_session() code. |
4481 | + * |
4482 | + * For dynamic ACL, target_put_nacl() uses target_complete_nacl() |
4483 | + * to release all remaining generate_node_acl=1 created ACL resources. |
4484 | */ |
4485 | - if (se_nacl && comp_nacl) |
4486 | - target_put_nacl(se_nacl); |
4487 | |
4488 | transport_free_session(se_sess); |
4489 | } |
4490 | diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c |
4491 | index aab5221d6c2e..aac0ce8aeb0b 100644 |
4492 | --- a/drivers/usb/gadget/udc/fsl_udc_core.c |
4493 | +++ b/drivers/usb/gadget/udc/fsl_udc_core.c |
4494 | @@ -1249,6 +1249,12 @@ static const struct usb_gadget_ops fsl_gadget_ops = { |
4495 | .udc_stop = fsl_udc_stop, |
4496 | }; |
4497 | |
4498 | +/* |
4499 | + * Empty complete function used by this driver to fill in the req->complete |
4500 | + * field when creating a request since the complete field is mandatory. |
4501 | + */ |
4502 | +static void fsl_noop_complete(struct usb_ep *ep, struct usb_request *req) { } |
4503 | + |
4504 | /* Set protocol stall on ep0, protocol stall will automatically be cleared |
4505 | on new transaction */ |
4506 | static void ep0stall(struct fsl_udc *udc) |
4507 | @@ -1283,7 +1289,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) |
4508 | req->req.length = 0; |
4509 | req->req.status = -EINPROGRESS; |
4510 | req->req.actual = 0; |
4511 | - req->req.complete = NULL; |
4512 | + req->req.complete = fsl_noop_complete; |
4513 | req->dtd_count = 0; |
4514 | |
4515 | ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep)); |
4516 | @@ -1366,7 +1372,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, |
4517 | req->req.length = 2; |
4518 | req->req.status = -EINPROGRESS; |
4519 | req->req.actual = 0; |
4520 | - req->req.complete = NULL; |
4521 | + req->req.complete = fsl_noop_complete; |
4522 | req->dtd_count = 0; |
4523 | |
4524 | ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep)); |
4525 | diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c |
4526 | index 4fe7c9b56bc0..19cb32a65161 100644 |
4527 | --- a/drivers/usb/host/xhci-plat.c |
4528 | +++ b/drivers/usb/host/xhci-plat.c |
4529 | @@ -162,9 +162,6 @@ static int xhci_plat_probe(struct platform_device *pdev) |
4530 | (pdata && pdata->usb3_lpm_capable)) |
4531 | xhci->quirks |= XHCI_LPM_SUPPORT; |
4532 | |
4533 | - if (HCC_MAX_PSA(xhci->hcc_params) >= 4) |
4534 | - xhci->shared_hcd->can_do_streams = 1; |
4535 | - |
4536 | hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0); |
4537 | if (IS_ERR(hcd->usb_phy)) { |
4538 | ret = PTR_ERR(hcd->usb_phy); |
4539 | @@ -181,6 +178,9 @@ static int xhci_plat_probe(struct platform_device *pdev) |
4540 | if (ret) |
4541 | goto disable_usb_phy; |
4542 | |
4543 | + if (HCC_MAX_PSA(xhci->hcc_params) >= 4) |
4544 | + xhci->shared_hcd->can_do_streams = 1; |
4545 | + |
4546 | ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); |
4547 | if (ret) |
4548 | goto dealloc_usb2_hcd; |
4549 | diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c |
4550 | index b03d3b867fca..9a9c82a4d35d 100644 |
4551 | --- a/drivers/usb/musb/da8xx.c |
4552 | +++ b/drivers/usb/musb/da8xx.c |
4553 | @@ -458,15 +458,11 @@ static int da8xx_musb_exit(struct musb *musb) |
4554 | } |
4555 | |
4556 | static const struct musb_platform_ops da8xx_ops = { |
4557 | - .quirks = MUSB_DMA_CPPI | MUSB_INDEXED_EP, |
4558 | + .quirks = MUSB_INDEXED_EP, |
4559 | .init = da8xx_musb_init, |
4560 | .exit = da8xx_musb_exit, |
4561 | |
4562 | .fifo_mode = 2, |
4563 | -#ifdef CONFIG_USB_TI_CPPI_DMA |
4564 | - .dma_init = cppi_dma_controller_create, |
4565 | - .dma_exit = cppi_dma_controller_destroy, |
4566 | -#endif |
4567 | .enable = da8xx_musb_enable, |
4568 | .disable = da8xx_musb_disable, |
4569 | |
4570 | diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c |
4571 | index 049a884a756f..59d74d1b47a8 100644 |
4572 | --- a/drivers/w1/masters/ds2490.c |
4573 | +++ b/drivers/w1/masters/ds2490.c |
4574 | @@ -153,6 +153,9 @@ struct ds_device |
4575 | */ |
4576 | u16 spu_bit; |
4577 | |
4578 | + u8 st_buf[ST_SIZE]; |
4579 | + u8 byte_buf; |
4580 | + |
4581 | struct w1_bus_master master; |
4582 | }; |
4583 | |
4584 | @@ -174,7 +177,6 @@ struct ds_status |
4585 | u8 data_in_buffer_status; |
4586 | u8 reserved1; |
4587 | u8 reserved2; |
4588 | - |
4589 | }; |
4590 | |
4591 | static struct usb_device_id ds_id_table [] = { |
4592 | @@ -244,28 +246,6 @@ static int ds_send_control(struct ds_device *dev, u16 value, u16 index) |
4593 | return err; |
4594 | } |
4595 | |
4596 | -static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, |
4597 | - unsigned char *buf, int size) |
4598 | -{ |
4599 | - int count, err; |
4600 | - |
4601 | - memset(st, 0, sizeof(*st)); |
4602 | - |
4603 | - count = 0; |
4604 | - err = usb_interrupt_msg(dev->udev, usb_rcvintpipe(dev->udev, |
4605 | - dev->ep[EP_STATUS]), buf, size, &count, 1000); |
4606 | - if (err < 0) { |
4607 | - pr_err("Failed to read 1-wire data from 0x%x: err=%d.\n", |
4608 | - dev->ep[EP_STATUS], err); |
4609 | - return err; |
4610 | - } |
4611 | - |
4612 | - if (count >= sizeof(*st)) |
4613 | - memcpy(st, buf, sizeof(*st)); |
4614 | - |
4615 | - return count; |
4616 | -} |
4617 | - |
4618 | static inline void ds_print_msg(unsigned char *buf, unsigned char *str, int off) |
4619 | { |
4620 | pr_info("%45s: %8x\n", str, buf[off]); |
4621 | @@ -324,6 +304,35 @@ static void ds_dump_status(struct ds_device *dev, unsigned char *buf, int count) |
4622 | } |
4623 | } |
4624 | |
4625 | +static int ds_recv_status(struct ds_device *dev, struct ds_status *st, |
4626 | + bool dump) |
4627 | +{ |
4628 | + int count, err; |
4629 | + |
4630 | + if (st) |
4631 | + memset(st, 0, sizeof(*st)); |
4632 | + |
4633 | + count = 0; |
4634 | + err = usb_interrupt_msg(dev->udev, |
4635 | + usb_rcvintpipe(dev->udev, |
4636 | + dev->ep[EP_STATUS]), |
4637 | + dev->st_buf, sizeof(dev->st_buf), |
4638 | + &count, 1000); |
4639 | + if (err < 0) { |
4640 | + pr_err("Failed to read 1-wire data from 0x%x: err=%d.\n", |
4641 | + dev->ep[EP_STATUS], err); |
4642 | + return err; |
4643 | + } |
4644 | + |
4645 | + if (dump) |
4646 | + ds_dump_status(dev, dev->st_buf, count); |
4647 | + |
4648 | + if (st && count >= sizeof(*st)) |
4649 | + memcpy(st, dev->st_buf, sizeof(*st)); |
4650 | + |
4651 | + return count; |
4652 | +} |
4653 | + |
4654 | static void ds_reset_device(struct ds_device *dev) |
4655 | { |
4656 | ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); |
4657 | @@ -344,7 +353,6 @@ static void ds_reset_device(struct ds_device *dev) |
4658 | static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) |
4659 | { |
4660 | int count, err; |
4661 | - struct ds_status st; |
4662 | |
4663 | /* Careful on size. If size is less than what is available in |
4664 | * the input buffer, the device fails the bulk transfer and |
4665 | @@ -359,14 +367,9 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) |
4666 | err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), |
4667 | buf, size, &count, 1000); |
4668 | if (err < 0) { |
4669 | - u8 buf[ST_SIZE]; |
4670 | - int count; |
4671 | - |
4672 | pr_info("Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); |
4673 | usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); |
4674 | - |
4675 | - count = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); |
4676 | - ds_dump_status(dev, buf, count); |
4677 | + ds_recv_status(dev, NULL, true); |
4678 | return err; |
4679 | } |
4680 | |
4681 | @@ -404,7 +407,6 @@ int ds_stop_pulse(struct ds_device *dev, int limit) |
4682 | { |
4683 | struct ds_status st; |
4684 | int count = 0, err = 0; |
4685 | - u8 buf[ST_SIZE]; |
4686 | |
4687 | do { |
4688 | err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); |
4689 | @@ -413,7 +415,7 @@ int ds_stop_pulse(struct ds_device *dev, int limit) |
4690 | err = ds_send_control(dev, CTL_RESUME_EXE, 0); |
4691 | if (err) |
4692 | break; |
4693 | - err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); |
4694 | + err = ds_recv_status(dev, &st, false); |
4695 | if (err) |
4696 | break; |
4697 | |
4698 | @@ -456,18 +458,17 @@ int ds_detect(struct ds_device *dev, struct ds_status *st) |
4699 | |
4700 | static int ds_wait_status(struct ds_device *dev, struct ds_status *st) |
4701 | { |
4702 | - u8 buf[ST_SIZE]; |
4703 | int err, count = 0; |
4704 | |
4705 | do { |
4706 | st->status = 0; |
4707 | - err = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); |
4708 | + err = ds_recv_status(dev, st, false); |
4709 | #if 0 |
4710 | if (err >= 0) { |
4711 | int i; |
4712 | printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); |
4713 | for (i=0; i<err; ++i) |
4714 | - printk("%02x ", buf[i]); |
4715 | + printk("%02x ", dev->st_buf[i]); |
4716 | printk("\n"); |
4717 | } |
4718 | #endif |
4719 | @@ -485,7 +486,7 @@ static int ds_wait_status(struct ds_device *dev, struct ds_status *st) |
4720 | * can do something with it). |
4721 | */ |
4722 | if (err > 16 || count >= 100 || err < 0) |
4723 | - ds_dump_status(dev, buf, err); |
4724 | + ds_dump_status(dev, dev->st_buf, err); |
4725 | |
4726 | /* Extended data isn't an error. Well, a short is, but the dump |
4727 | * would have already told the user that and we can't do anything |
4728 | @@ -608,7 +609,6 @@ static int ds_write_byte(struct ds_device *dev, u8 byte) |
4729 | { |
4730 | int err; |
4731 | struct ds_status st; |
4732 | - u8 rbyte; |
4733 | |
4734 | err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte); |
4735 | if (err) |
4736 | @@ -621,11 +621,11 @@ static int ds_write_byte(struct ds_device *dev, u8 byte) |
4737 | if (err) |
4738 | return err; |
4739 | |
4740 | - err = ds_recv_data(dev, &rbyte, sizeof(rbyte)); |
4741 | + err = ds_recv_data(dev, &dev->byte_buf, 1); |
4742 | if (err < 0) |
4743 | return err; |
4744 | |
4745 | - return !(byte == rbyte); |
4746 | + return !(byte == dev->byte_buf); |
4747 | } |
4748 | |
4749 | static int ds_read_byte(struct ds_device *dev, u8 *byte) |
4750 | @@ -712,7 +712,6 @@ static void ds9490r_search(void *data, struct w1_master *master, |
4751 | int err; |
4752 | u16 value, index; |
4753 | struct ds_status st; |
4754 | - u8 st_buf[ST_SIZE]; |
4755 | int search_limit; |
4756 | int found = 0; |
4757 | int i; |
4758 | @@ -724,7 +723,12 @@ static void ds9490r_search(void *data, struct w1_master *master, |
4759 | /* FIFO 128 bytes, bulk packet size 64, read a multiple of the |
4760 | * packet size. |
4761 | */ |
4762 | - u64 buf[2*64/8]; |
4763 | + const size_t bufsize = 2 * 64; |
4764 | + u64 *buf; |
4765 | + |
4766 | + buf = kmalloc(bufsize, GFP_KERNEL); |
4767 | + if (!buf) |
4768 | + return; |
4769 | |
4770 | mutex_lock(&master->bus_mutex); |
4771 | |
4772 | @@ -745,10 +749,9 @@ static void ds9490r_search(void *data, struct w1_master *master, |
4773 | do { |
4774 | schedule_timeout(jtime); |
4775 | |
4776 | - if (ds_recv_status_nodump(dev, &st, st_buf, sizeof(st_buf)) < |
4777 | - sizeof(st)) { |
4778 | + err = ds_recv_status(dev, &st, false); |
4779 | + if (err < 0 || err < sizeof(st)) |
4780 | break; |
4781 | - } |
4782 | |
4783 | if (st.data_in_buffer_status) { |
4784 | /* Bulk in can receive partial ids, but when it does |
4785 | @@ -758,7 +761,7 @@ static void ds9490r_search(void *data, struct w1_master *master, |
4786 | * bulk without first checking if status says there |
4787 | * is data to read. |
4788 | */ |
4789 | - err = ds_recv_data(dev, (u8 *)buf, sizeof(buf)); |
4790 | + err = ds_recv_data(dev, (u8 *)buf, bufsize); |
4791 | if (err < 0) |
4792 | break; |
4793 | for (i = 0; i < err/8; ++i) { |
4794 | @@ -794,9 +797,14 @@ static void ds9490r_search(void *data, struct w1_master *master, |
4795 | } |
4796 | search_out: |
4797 | mutex_unlock(&master->bus_mutex); |
4798 | + kfree(buf); |
4799 | } |
4800 | |
4801 | #if 0 |
4802 | +/* |
4803 | + * FIXME: if this disabled code is ever used in the future all ds_send_data() |
4804 | + * calls must be changed to use a DMAable buffer. |
4805 | + */ |
4806 | static int ds_match_access(struct ds_device *dev, u64 init) |
4807 | { |
4808 | int err; |
4809 | @@ -845,13 +853,12 @@ static int ds_set_path(struct ds_device *dev, u64 init) |
4810 | |
4811 | static u8 ds9490r_touch_bit(void *data, u8 bit) |
4812 | { |
4813 | - u8 ret; |
4814 | struct ds_device *dev = data; |
4815 | |
4816 | - if (ds_touch_bit(dev, bit, &ret)) |
4817 | + if (ds_touch_bit(dev, bit, &dev->byte_buf)) |
4818 | return 0; |
4819 | |
4820 | - return ret; |
4821 | + return dev->byte_buf; |
4822 | } |
4823 | |
4824 | #if 0 |
4825 | @@ -866,13 +873,12 @@ static u8 ds9490r_read_bit(void *data) |
4826 | { |
4827 | struct ds_device *dev = data; |
4828 | int err; |
4829 | - u8 bit = 0; |
4830 | |
4831 | - err = ds_touch_bit(dev, 1, &bit); |
4832 | + err = ds_touch_bit(dev, 1, &dev->byte_buf); |
4833 | if (err) |
4834 | return 0; |
4835 | |
4836 | - return bit & 1; |
4837 | + return dev->byte_buf & 1; |
4838 | } |
4839 | #endif |
4840 | |
4841 | @@ -887,32 +893,52 @@ static u8 ds9490r_read_byte(void *data) |
4842 | { |
4843 | struct ds_device *dev = data; |
4844 | int err; |
4845 | - u8 byte = 0; |
4846 | |
4847 | - err = ds_read_byte(dev, &byte); |
4848 | + err = ds_read_byte(dev, &dev->byte_buf); |
4849 | if (err) |
4850 | return 0; |
4851 | |
4852 | - return byte; |
4853 | + return dev->byte_buf; |
4854 | } |
4855 | |
4856 | static void ds9490r_write_block(void *data, const u8 *buf, int len) |
4857 | { |
4858 | struct ds_device *dev = data; |
4859 | + u8 *tbuf; |
4860 | + |
4861 | + if (len <= 0) |
4862 | + return; |
4863 | + |
4864 | + tbuf = kmalloc(len, GFP_KERNEL); |
4865 | + if (!tbuf) |
4866 | + return; |
4867 | |
4868 | - ds_write_block(dev, (u8 *)buf, len); |
4869 | + memcpy(tbuf, buf, len); |
4870 | + ds_write_block(dev, tbuf, len); |
4871 | + |
4872 | + kfree(tbuf); |
4873 | } |
4874 | |
4875 | static u8 ds9490r_read_block(void *data, u8 *buf, int len) |
4876 | { |
4877 | struct ds_device *dev = data; |
4878 | int err; |
4879 | + u8 *tbuf; |
4880 | |
4881 | - err = ds_read_block(dev, buf, len); |
4882 | - if (err < 0) |
4883 | + if (len <= 0) |
4884 | + return 0; |
4885 | + |
4886 | + tbuf = kmalloc(len, GFP_KERNEL); |
4887 | + if (!tbuf) |
4888 | return 0; |
4889 | |
4890 | - return len; |
4891 | + err = ds_read_block(dev, tbuf, len); |
4892 | + if (err >= 0) |
4893 | + memcpy(buf, tbuf, len); |
4894 | + |
4895 | + kfree(tbuf); |
4896 | + |
4897 | + return err >= 0 ? len : 0; |
4898 | } |
4899 | |
4900 | static u8 ds9490r_reset(void *data) |
4901 | diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c |
4902 | index c9a7ff67d395..39886edfa222 100644 |
4903 | --- a/drivers/w1/w1.c |
4904 | +++ b/drivers/w1/w1.c |
4905 | @@ -763,6 +763,7 @@ int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) |
4906 | dev_err(&dev->dev, "%s: Attaching %s failed.\n", __func__, |
4907 | sl->name); |
4908 | w1_family_put(sl->family); |
4909 | + atomic_dec(&sl->master->refcnt); |
4910 | kfree(sl); |
4911 | return err; |
4912 | } |
4913 | diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c |
4914 | index 9da42ace762a..8a456f9b8a44 100644 |
4915 | --- a/fs/ext4/extents.c |
4916 | +++ b/fs/ext4/extents.c |
4917 | @@ -5362,7 +5362,8 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, |
4918 | ext4_lblk_t stop, *iterator, ex_start, ex_end; |
4919 | |
4920 | /* Let path point to the last extent */ |
4921 | - path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0); |
4922 | + path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, |
4923 | + EXT4_EX_NOCACHE); |
4924 | if (IS_ERR(path)) |
4925 | return PTR_ERR(path); |
4926 | |
4927 | @@ -5371,15 +5372,15 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, |
4928 | if (!extent) |
4929 | goto out; |
4930 | |
4931 | - stop = le32_to_cpu(extent->ee_block) + |
4932 | - ext4_ext_get_actual_len(extent); |
4933 | + stop = le32_to_cpu(extent->ee_block); |
4934 | |
4935 | /* |
4936 | * In case of left shift, Don't start shifting extents until we make |
4937 | * sure the hole is big enough to accommodate the shift. |
4938 | */ |
4939 | if (SHIFT == SHIFT_LEFT) { |
4940 | - path = ext4_find_extent(inode, start - 1, &path, 0); |
4941 | + path = ext4_find_extent(inode, start - 1, &path, |
4942 | + EXT4_EX_NOCACHE); |
4943 | if (IS_ERR(path)) |
4944 | return PTR_ERR(path); |
4945 | depth = path->p_depth; |
4946 | @@ -5411,9 +5412,14 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, |
4947 | else |
4948 | iterator = &stop; |
4949 | |
4950 | - /* Its safe to start updating extents */ |
4951 | - while (start < stop) { |
4952 | - path = ext4_find_extent(inode, *iterator, &path, 0); |
4953 | + /* |
4954 | + * Its safe to start updating extents. Start and stop are unsigned, so |
4955 | + * in case of right shift if extent with 0 block is reached, iterator |
4956 | + * becomes NULL to indicate the end of the loop. |
4957 | + */ |
4958 | + while (iterator && start <= stop) { |
4959 | + path = ext4_find_extent(inode, *iterator, &path, |
4960 | + EXT4_EX_NOCACHE); |
4961 | if (IS_ERR(path)) |
4962 | return PTR_ERR(path); |
4963 | depth = path->p_depth; |
4964 | @@ -5440,8 +5446,11 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, |
4965 | ext4_ext_get_actual_len(extent); |
4966 | } else { |
4967 | extent = EXT_FIRST_EXTENT(path[depth].p_hdr); |
4968 | - *iterator = le32_to_cpu(extent->ee_block) > 0 ? |
4969 | - le32_to_cpu(extent->ee_block) - 1 : 0; |
4970 | + if (le32_to_cpu(extent->ee_block) > 0) |
4971 | + *iterator = le32_to_cpu(extent->ee_block) - 1; |
4972 | + else |
4973 | + /* Beginning is reached, end of the loop */ |
4974 | + iterator = NULL; |
4975 | /* Update path extent in case we need to stop */ |
4976 | while (le32_to_cpu(extent->ee_block) < start) |
4977 | extent++; |
4978 | diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c |
4979 | index 8968a93e2150..d4be4e23bc21 100644 |
4980 | --- a/fs/ext4/inline.c |
4981 | +++ b/fs/ext4/inline.c |
4982 | @@ -933,8 +933,15 @@ int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos, |
4983 | struct page *page) |
4984 | { |
4985 | int i_size_changed = 0; |
4986 | + int ret; |
4987 | |
4988 | - copied = ext4_write_inline_data_end(inode, pos, len, copied, page); |
4989 | + ret = ext4_write_inline_data_end(inode, pos, len, copied, page); |
4990 | + if (ret < 0) { |
4991 | + unlock_page(page); |
4992 | + put_page(page); |
4993 | + return ret; |
4994 | + } |
4995 | + copied = ret; |
4996 | |
4997 | /* |
4998 | * No need to use i_size_read() here, the i_size |
4999 | diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c |
5000 | index 10690e5ba2eb..e0f862146793 100644 |
5001 | --- a/fs/ext4/inode.c |
5002 | +++ b/fs/ext4/inode.c |
5003 | @@ -1165,8 +1165,11 @@ static int ext4_write_end(struct file *file, |
5004 | if (ext4_has_inline_data(inode)) { |
5005 | ret = ext4_write_inline_data_end(inode, pos, len, |
5006 | copied, page); |
5007 | - if (ret < 0) |
5008 | + if (ret < 0) { |
5009 | + unlock_page(page); |
5010 | + put_page(page); |
5011 | goto errout; |
5012 | + } |
5013 | copied = ret; |
5014 | } else |
5015 | copied = block_write_end(file, mapping, pos, |
5016 | @@ -1220,7 +1223,9 @@ errout: |
5017 | * set the buffer to be dirty, since in data=journalled mode we need |
5018 | * to call ext4_handle_dirty_metadata() instead. |
5019 | */ |
5020 | -static void zero_new_buffers(struct page *page, unsigned from, unsigned to) |
5021 | +static void ext4_journalled_zero_new_buffers(handle_t *handle, |
5022 | + struct page *page, |
5023 | + unsigned from, unsigned to) |
5024 | { |
5025 | unsigned int block_start = 0, block_end; |
5026 | struct buffer_head *head, *bh; |
5027 | @@ -1237,7 +1242,7 @@ static void zero_new_buffers(struct page *page, unsigned from, unsigned to) |
5028 | size = min(to, block_end) - start; |
5029 | |
5030 | zero_user(page, start, size); |
5031 | - set_buffer_uptodate(bh); |
5032 | + write_end_fn(handle, bh); |
5033 | } |
5034 | clear_buffer_new(bh); |
5035 | } |
5036 | @@ -1266,18 +1271,25 @@ static int ext4_journalled_write_end(struct file *file, |
5037 | |
5038 | BUG_ON(!ext4_handle_valid(handle)); |
5039 | |
5040 | - if (ext4_has_inline_data(inode)) |
5041 | - copied = ext4_write_inline_data_end(inode, pos, len, |
5042 | - copied, page); |
5043 | - else { |
5044 | - if (copied < len) { |
5045 | - if (!PageUptodate(page)) |
5046 | - copied = 0; |
5047 | - zero_new_buffers(page, from+copied, to); |
5048 | + if (ext4_has_inline_data(inode)) { |
5049 | + ret = ext4_write_inline_data_end(inode, pos, len, |
5050 | + copied, page); |
5051 | + if (ret < 0) { |
5052 | + unlock_page(page); |
5053 | + put_page(page); |
5054 | + goto errout; |
5055 | } |
5056 | - |
5057 | + copied = ret; |
5058 | + } else if (unlikely(copied < len) && !PageUptodate(page)) { |
5059 | + copied = 0; |
5060 | + ext4_journalled_zero_new_buffers(handle, page, from, to); |
5061 | + } else { |
5062 | + if (unlikely(copied < len)) |
5063 | + ext4_journalled_zero_new_buffers(handle, page, |
5064 | + from + copied, to); |
5065 | ret = ext4_walk_page_buffers(handle, page_buffers(page), from, |
5066 | - to, &partial, write_end_fn); |
5067 | + from + copied, &partial, |
5068 | + write_end_fn); |
5069 | if (!partial) |
5070 | SetPageUptodate(page); |
5071 | } |
5072 | @@ -1303,6 +1315,7 @@ static int ext4_journalled_write_end(struct file *file, |
5073 | */ |
5074 | ext4_orphan_add(handle, inode); |
5075 | |
5076 | +errout: |
5077 | ret2 = ext4_journal_stop(handle); |
5078 | if (!ret) |
5079 | ret = ret2; |
5080 | diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c |
5081 | index b7a3957a9dca..84cd77663e1f 100644 |
5082 | --- a/fs/ext4/mballoc.c |
5083 | +++ b/fs/ext4/mballoc.c |
5084 | @@ -3120,6 +3120,13 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, |
5085 | if (ar->pright && start + size - 1 >= ar->lright) |
5086 | size -= start + size - ar->lright; |
5087 | |
5088 | + /* |
5089 | + * Trim allocation request for filesystems with artificially small |
5090 | + * groups. |
5091 | + */ |
5092 | + if (size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)) |
5093 | + size = EXT4_BLOCKS_PER_GROUP(ac->ac_sb); |
5094 | + |
5095 | end = start + size; |
5096 | |
5097 | /* check we don't cross already preallocated blocks */ |
5098 | diff --git a/fs/ext4/super.c b/fs/ext4/super.c |
5099 | index b405a7b74ce0..6fe8e30eeb99 100644 |
5100 | --- a/fs/ext4/super.c |
5101 | +++ b/fs/ext4/super.c |
5102 | @@ -793,6 +793,7 @@ static void ext4_put_super(struct super_block *sb) |
5103 | { |
5104 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
5105 | struct ext4_super_block *es = sbi->s_es; |
5106 | + int aborted = 0; |
5107 | int i, err; |
5108 | |
5109 | ext4_unregister_li_request(sb); |
5110 | @@ -802,9 +803,10 @@ static void ext4_put_super(struct super_block *sb) |
5111 | destroy_workqueue(sbi->rsv_conversion_wq); |
5112 | |
5113 | if (sbi->s_journal) { |
5114 | + aborted = is_journal_aborted(sbi->s_journal); |
5115 | err = jbd2_journal_destroy(sbi->s_journal); |
5116 | sbi->s_journal = NULL; |
5117 | - if (err < 0) |
5118 | + if ((err < 0) && !aborted) |
5119 | ext4_abort(sb, "Couldn't clean up the journal"); |
5120 | } |
5121 | |
5122 | @@ -816,7 +818,7 @@ static void ext4_put_super(struct super_block *sb) |
5123 | ext4_ext_release(sb); |
5124 | ext4_xattr_put_super(sb); |
5125 | |
5126 | - if (!(sb->s_flags & MS_RDONLY)) { |
5127 | + if (!(sb->s_flags & MS_RDONLY) && !aborted) { |
5128 | ext4_clear_feature_journal_needs_recovery(sb); |
5129 | es->s_state = cpu_to_le16(sbi->s_mount_state); |
5130 | } |
5131 | @@ -3746,7 +3748,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) |
5132 | * root first: it may be modified in the journal! |
5133 | */ |
5134 | if (!test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb)) { |
5135 | - if (ext4_load_journal(sb, es, journal_devnum)) |
5136 | + err = ext4_load_journal(sb, es, journal_devnum); |
5137 | + if (err) |
5138 | goto failed_mount3a; |
5139 | } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) && |
5140 | ext4_has_feature_journal_needs_recovery(sb)) { |
5141 | diff --git a/fs/fuse/file.c b/fs/fuse/file.c |
5142 | index 8821c380a71a..11538a8be9f0 100644 |
5143 | --- a/fs/fuse/file.c |
5144 | +++ b/fs/fuse/file.c |
5145 | @@ -100,6 +100,7 @@ static void fuse_file_put(struct fuse_file *ff, bool sync) |
5146 | iput(req->misc.release.inode); |
5147 | fuse_put_request(ff->fc, req); |
5148 | } else if (sync) { |
5149 | + __set_bit(FR_FORCE, &req->flags); |
5150 | __clear_bit(FR_BACKGROUND, &req->flags); |
5151 | fuse_request_send(ff->fc, req); |
5152 | iput(req->misc.release.inode); |
5153 | diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c |
5154 | index 32e74710b1aa..9cd8c92b953d 100644 |
5155 | --- a/fs/gfs2/glock.c |
5156 | +++ b/fs/gfs2/glock.c |
5157 | @@ -651,9 +651,11 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, |
5158 | struct kmem_cache *cachep; |
5159 | int ret, tries = 0; |
5160 | |
5161 | + rcu_read_lock(); |
5162 | gl = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms); |
5163 | if (gl && !lockref_get_not_dead(&gl->gl_lockref)) |
5164 | gl = NULL; |
5165 | + rcu_read_unlock(); |
5166 | |
5167 | *glp = gl; |
5168 | if (gl) |
5169 | @@ -721,15 +723,18 @@ again: |
5170 | |
5171 | if (ret == -EEXIST) { |
5172 | ret = 0; |
5173 | + rcu_read_lock(); |
5174 | tmp = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms); |
5175 | if (tmp == NULL || !lockref_get_not_dead(&tmp->gl_lockref)) { |
5176 | if (++tries < 100) { |
5177 | + rcu_read_unlock(); |
5178 | cond_resched(); |
5179 | goto again; |
5180 | } |
5181 | tmp = NULL; |
5182 | ret = -ENOMEM; |
5183 | } |
5184 | + rcu_read_unlock(); |
5185 | } else { |
5186 | WARN_ON_ONCE(ret); |
5187 | } |
5188 | diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c |
5189 | index fa1b8e0dcacf..a2e724053919 100644 |
5190 | --- a/fs/jbd2/transaction.c |
5191 | +++ b/fs/jbd2/transaction.c |
5192 | @@ -1876,7 +1876,9 @@ static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh) |
5193 | |
5194 | __blist_del_buffer(list, jh); |
5195 | jh->b_jlist = BJ_None; |
5196 | - if (test_clear_buffer_jbddirty(bh)) |
5197 | + if (transaction && is_journal_aborted(transaction->t_journal)) |
5198 | + clear_buffer_jbddirty(bh); |
5199 | + else if (test_clear_buffer_jbddirty(bh)) |
5200 | mark_buffer_dirty(bh); /* Expose it to the VM */ |
5201 | } |
5202 | |
5203 | diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c |
5204 | index 9a524e763c3e..4e3679b25b9b 100644 |
5205 | --- a/fs/nfs/nfs4proc.c |
5206 | +++ b/fs/nfs/nfs4proc.c |
5207 | @@ -2452,6 +2452,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, |
5208 | ret = PTR_ERR(state); |
5209 | if (IS_ERR(state)) |
5210 | goto out; |
5211 | + ctx->state = state; |
5212 | if (server->caps & NFS_CAP_POSIX_LOCK) |
5213 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); |
5214 | |
5215 | @@ -2474,7 +2475,6 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, |
5216 | if (ret != 0) |
5217 | goto out; |
5218 | |
5219 | - ctx->state = state; |
5220 | if (d_inode(dentry) == state->inode) { |
5221 | nfs_inode_attach_open_context(ctx); |
5222 | if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) |
5223 | @@ -4711,7 +4711,7 @@ out: |
5224 | */ |
5225 | static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) |
5226 | { |
5227 | - struct page *pages[NFS4ACL_MAXPAGES] = {NULL, }; |
5228 | + struct page *pages[NFS4ACL_MAXPAGES + 1] = {NULL, }; |
5229 | struct nfs_getaclargs args = { |
5230 | .fh = NFS_FH(inode), |
5231 | .acl_pages = pages, |
5232 | @@ -4725,13 +4725,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu |
5233 | .rpc_argp = &args, |
5234 | .rpc_resp = &res, |
5235 | }; |
5236 | - unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE); |
5237 | + unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE) + 1; |
5238 | int ret = -ENOMEM, i; |
5239 | |
5240 | - /* As long as we're doing a round trip to the server anyway, |
5241 | - * let's be prepared for a page of acl data. */ |
5242 | - if (npages == 0) |
5243 | - npages = 1; |
5244 | if (npages > ARRAY_SIZE(pages)) |
5245 | return -ERANGE; |
5246 | |
5247 | diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c |
5248 | index 4e4441216804..1cb50bb898b0 100644 |
5249 | --- a/fs/nfs/nfs4xdr.c |
5250 | +++ b/fs/nfs/nfs4xdr.c |
5251 | @@ -2487,7 +2487,7 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, |
5252 | encode_compound_hdr(xdr, req, &hdr); |
5253 | encode_sequence(xdr, &args->seq_args, &hdr); |
5254 | encode_putfh(xdr, args->fh, &hdr); |
5255 | - replen = hdr.replen + op_decode_hdr_maxsz + 1; |
5256 | + replen = hdr.replen + op_decode_hdr_maxsz; |
5257 | encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr); |
5258 | |
5259 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, |
5260 | diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c |
5261 | index 994d66fbb446..91e0c5429b4d 100644 |
5262 | --- a/fs/nfsd/vfs.c |
5263 | +++ b/fs/nfsd/vfs.c |
5264 | @@ -369,7 +369,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, |
5265 | __be32 err; |
5266 | int host_err; |
5267 | bool get_write_count; |
5268 | - int size_change = 0; |
5269 | + bool size_change = (iap->ia_valid & ATTR_SIZE); |
5270 | |
5271 | if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) |
5272 | accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE; |
5273 | @@ -382,11 +382,11 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, |
5274 | /* Get inode */ |
5275 | err = fh_verify(rqstp, fhp, ftype, accmode); |
5276 | if (err) |
5277 | - goto out; |
5278 | + return err; |
5279 | if (get_write_count) { |
5280 | host_err = fh_want_write(fhp); |
5281 | if (host_err) |
5282 | - return nfserrno(host_err); |
5283 | + goto out; |
5284 | } |
5285 | |
5286 | dentry = fhp->fh_dentry; |
5287 | @@ -397,20 +397,28 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, |
5288 | iap->ia_valid &= ~ATTR_MODE; |
5289 | |
5290 | if (!iap->ia_valid) |
5291 | - goto out; |
5292 | + return 0; |
5293 | |
5294 | nfsd_sanitize_attrs(inode, iap); |
5295 | |
5296 | + if (check_guard && guardtime != inode->i_ctime.tv_sec) |
5297 | + return nfserr_notsync; |
5298 | + |
5299 | /* |
5300 | * The size case is special, it changes the file in addition to the |
5301 | - * attributes. |
5302 | + * attributes, and file systems don't expect it to be mixed with |
5303 | + * "random" attribute changes. We thus split out the size change |
5304 | + * into a separate call to ->setattr, and do the rest as a separate |
5305 | + * setattr call. |
5306 | */ |
5307 | - if (iap->ia_valid & ATTR_SIZE) { |
5308 | + if (size_change) { |
5309 | err = nfsd_get_write_access(rqstp, fhp, iap); |
5310 | if (err) |
5311 | - goto out; |
5312 | - size_change = 1; |
5313 | + return err; |
5314 | + } |
5315 | |
5316 | + fh_lock(fhp); |
5317 | + if (size_change) { |
5318 | /* |
5319 | * RFC5661, Section 18.30.4: |
5320 | * Changing the size of a file with SETATTR indirectly |
5321 | @@ -418,29 +426,36 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, |
5322 | * |
5323 | * (and similar for the older RFCs) |
5324 | */ |
5325 | - if (iap->ia_size != i_size_read(inode)) |
5326 | - iap->ia_valid |= ATTR_MTIME; |
5327 | - } |
5328 | + struct iattr size_attr = { |
5329 | + .ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME, |
5330 | + .ia_size = iap->ia_size, |
5331 | + }; |
5332 | |
5333 | - iap->ia_valid |= ATTR_CTIME; |
5334 | + host_err = notify_change(dentry, &size_attr, NULL); |
5335 | + if (host_err) |
5336 | + goto out_unlock; |
5337 | + iap->ia_valid &= ~ATTR_SIZE; |
5338 | |
5339 | - if (check_guard && guardtime != inode->i_ctime.tv_sec) { |
5340 | - err = nfserr_notsync; |
5341 | - goto out_put_write_access; |
5342 | + /* |
5343 | + * Avoid the additional setattr call below if the only other |
5344 | + * attribute that the client sends is the mtime, as we update |
5345 | + * it as part of the size change above. |
5346 | + */ |
5347 | + if ((iap->ia_valid & ~ATTR_MTIME) == 0) |
5348 | + goto out_unlock; |
5349 | } |
5350 | |
5351 | - fh_lock(fhp); |
5352 | + iap->ia_valid |= ATTR_CTIME; |
5353 | host_err = notify_change(dentry, iap, NULL); |
5354 | - fh_unlock(fhp); |
5355 | - err = nfserrno(host_err); |
5356 | |
5357 | -out_put_write_access: |
5358 | +out_unlock: |
5359 | + fh_unlock(fhp); |
5360 | if (size_change) |
5361 | put_write_access(inode); |
5362 | - if (!err) |
5363 | - err = nfserrno(commit_metadata(fhp)); |
5364 | out: |
5365 | - return err; |
5366 | + if (!host_err) |
5367 | + host_err = commit_metadata(fhp); |
5368 | + return nfserrno(host_err); |
5369 | } |
5370 | |
5371 | #if defined(CONFIG_NFSD_V4) |
5372 | diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h |
5373 | index d49e26c6cdc7..23e129ef6726 100644 |
5374 | --- a/include/linux/intel-iommu.h |
5375 | +++ b/include/linux/intel-iommu.h |
5376 | @@ -153,8 +153,8 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) |
5377 | #define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60) |
5378 | #define DMA_TLB_DSI_FLUSH (((u64)2) << 60) |
5379 | #define DMA_TLB_PSI_FLUSH (((u64)3) << 60) |
5380 | -#define DMA_TLB_IIRG(type) ((type >> 60) & 7) |
5381 | -#define DMA_TLB_IAIG(val) (((val) >> 57) & 7) |
5382 | +#define DMA_TLB_IIRG(type) ((type >> 60) & 3) |
5383 | +#define DMA_TLB_IAIG(val) (((val) >> 57) & 3) |
5384 | #define DMA_TLB_READ_DRAIN (((u64)1) << 49) |
5385 | #define DMA_TLB_WRITE_DRAIN (((u64)1) << 48) |
5386 | #define DMA_TLB_DID(id) (((u64)((id) & 0xffff)) << 32) |
5387 | @@ -164,9 +164,9 @@ static inline void dmar_writeq(void __iomem *addr, u64 val) |
5388 | |
5389 | /* INVALID_DESC */ |
5390 | #define DMA_CCMD_INVL_GRANU_OFFSET 61 |
5391 | -#define DMA_ID_TLB_GLOBAL_FLUSH (((u64)1) << 3) |
5392 | -#define DMA_ID_TLB_DSI_FLUSH (((u64)2) << 3) |
5393 | -#define DMA_ID_TLB_PSI_FLUSH (((u64)3) << 3) |
5394 | +#define DMA_ID_TLB_GLOBAL_FLUSH (((u64)1) << 4) |
5395 | +#define DMA_ID_TLB_DSI_FLUSH (((u64)2) << 4) |
5396 | +#define DMA_ID_TLB_PSI_FLUSH (((u64)3) << 4) |
5397 | #define DMA_ID_TLB_READ_DRAIN (((u64)1) << 7) |
5398 | #define DMA_ID_TLB_WRITE_DRAIN (((u64)1) << 6) |
5399 | #define DMA_ID_TLB_DID(id) (((u64)((id & 0xffff) << 16))) |
5400 | @@ -316,8 +316,8 @@ enum { |
5401 | #define QI_DEV_EIOTLB_SIZE (((u64)1) << 11) |
5402 | #define QI_DEV_EIOTLB_GLOB(g) ((u64)g) |
5403 | #define QI_DEV_EIOTLB_PASID(p) (((u64)p) << 32) |
5404 | -#define QI_DEV_EIOTLB_SID(sid) ((u64)((sid) & 0xffff) << 32) |
5405 | -#define QI_DEV_EIOTLB_QDEP(qd) (((qd) & 0x1f) << 16) |
5406 | +#define QI_DEV_EIOTLB_SID(sid) ((u64)((sid) & 0xffff) << 16) |
5407 | +#define QI_DEV_EIOTLB_QDEP(qd) ((u64)((qd) & 0x1f) << 4) |
5408 | #define QI_DEV_EIOTLB_MAX_INVS 32 |
5409 | |
5410 | #define QI_PGRP_IDX(idx) (((u64)(idx)) << 55) |
5411 | diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h |
5412 | index 301969552d0a..b43e64d69734 100644 |
5413 | --- a/include/rdma/ib_sa.h |
5414 | +++ b/include/rdma/ib_sa.h |
5415 | @@ -138,12 +138,12 @@ struct ib_sa_path_rec { |
5416 | union ib_gid sgid; |
5417 | __be16 dlid; |
5418 | __be16 slid; |
5419 | - int raw_traffic; |
5420 | + u8 raw_traffic; |
5421 | /* reserved */ |
5422 | __be32 flow_label; |
5423 | u8 hop_limit; |
5424 | u8 traffic_class; |
5425 | - int reversible; |
5426 | + u8 reversible; |
5427 | u8 numb_path; |
5428 | __be16 pkey; |
5429 | __be16 qos_class; |
5430 | @@ -204,7 +204,7 @@ struct ib_sa_mcmember_rec { |
5431 | u8 hop_limit; |
5432 | u8 scope; |
5433 | u8 join_state; |
5434 | - int proxy_join; |
5435 | + u8 proxy_join; |
5436 | }; |
5437 | |
5438 | /* Service Record Component Mask Sec 15.2.5.14 Ver 1.1 */ |
5439 | diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h |
5440 | index 4f6ba34cdee6..293b9a7f53bc 100644 |
5441 | --- a/include/scsi/scsi_device.h |
5442 | +++ b/include/scsi/scsi_device.h |
5443 | @@ -307,6 +307,7 @@ extern void scsi_remove_device(struct scsi_device *); |
5444 | extern int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh); |
5445 | void scsi_attach_vpd(struct scsi_device *sdev); |
5446 | |
5447 | +extern struct scsi_device *scsi_device_from_queue(struct request_queue *q); |
5448 | extern int scsi_device_get(struct scsi_device *); |
5449 | extern void scsi_device_put(struct scsi_device *); |
5450 | extern struct scsi_device *scsi_device_lookup(struct Scsi_Host *, |
5451 | diff --git a/include/soc/at91/at91sam9_ddrsdr.h b/include/soc/at91/at91sam9_ddrsdr.h |
5452 | index dc10c52e0e91..393362bdb860 100644 |
5453 | --- a/include/soc/at91/at91sam9_ddrsdr.h |
5454 | +++ b/include/soc/at91/at91sam9_ddrsdr.h |
5455 | @@ -81,6 +81,7 @@ |
5456 | #define AT91_DDRSDRC_LPCB_POWER_DOWN 2 |
5457 | #define AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN 3 |
5458 | #define AT91_DDRSDRC_CLKFR (1 << 2) /* Clock Frozen */ |
5459 | +#define AT91_DDRSDRC_LPDDR2_PWOFF (1 << 3) /* LPDDR Power Off */ |
5460 | #define AT91_DDRSDRC_PASR (7 << 4) /* Partial Array Self Refresh */ |
5461 | #define AT91_DDRSDRC_TCSR (3 << 8) /* Temperature Compensated Self Refresh */ |
5462 | #define AT91_DDRSDRC_DS (3 << 10) /* Drive Strength */ |
5463 | @@ -96,7 +97,9 @@ |
5464 | #define AT91_DDRSDRC_MD_SDR 0 |
5465 | #define AT91_DDRSDRC_MD_LOW_POWER_SDR 1 |
5466 | #define AT91_DDRSDRC_MD_LOW_POWER_DDR 3 |
5467 | +#define AT91_DDRSDRC_MD_LPDDR3 5 |
5468 | #define AT91_DDRSDRC_MD_DDR2 6 /* [SAM9 Only] */ |
5469 | +#define AT91_DDRSDRC_MD_LPDDR2 7 |
5470 | #define AT91_DDRSDRC_DBW (1 << 4) /* Data Bus Width */ |
5471 | #define AT91_DDRSDRC_DBW_32BITS (0 << 4) |
5472 | #define AT91_DDRSDRC_DBW_16BITS (1 << 4) |
5473 | diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h |
5474 | index 6afc6f388edf..800fe16cc36f 100644 |
5475 | --- a/include/target/target_core_base.h |
5476 | +++ b/include/target/target_core_base.h |
5477 | @@ -544,6 +544,7 @@ struct se_node_acl { |
5478 | /* Used to signal demo mode created ACL, disabled by default */ |
5479 | bool dynamic_node_acl; |
5480 | bool acl_stop:1; |
5481 | + bool dynamic_stop; |
5482 | u32 queue_depth; |
5483 | u32 acl_index; |
5484 | enum target_prot_type saved_prot_type; |
5485 | diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h |
5486 | index ce9ea736f1d7..97069ecabe49 100644 |
5487 | --- a/include/target/target_core_fabric.h |
5488 | +++ b/include/target/target_core_fabric.h |
5489 | @@ -168,6 +168,8 @@ void core_allocate_nexus_loss_ua(struct se_node_acl *acl); |
5490 | |
5491 | struct se_node_acl *core_tpg_get_initiator_node_acl(struct se_portal_group *tpg, |
5492 | unsigned char *); |
5493 | +bool target_tpg_has_node_acl(struct se_portal_group *tpg, |
5494 | + const char *); |
5495 | struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *, |
5496 | unsigned char *); |
5497 | int core_tpg_set_initiator_node_queue_depth(struct se_portal_group *, |
5498 | diff --git a/ipc/shm.c b/ipc/shm.c |
5499 | index 3174634ca4e5..4982a4e7f009 100644 |
5500 | --- a/ipc/shm.c |
5501 | +++ b/ipc/shm.c |
5502 | @@ -1083,8 +1083,8 @@ out_unlock1: |
5503 | * "raddr" thing points to kernel space, and there has to be a wrapper around |
5504 | * this. |
5505 | */ |
5506 | -long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, |
5507 | - unsigned long shmlba) |
5508 | +long do_shmat(int shmid, char __user *shmaddr, int shmflg, |
5509 | + ulong *raddr, unsigned long shmlba) |
5510 | { |
5511 | struct shmid_kernel *shp; |
5512 | unsigned long addr; |
5513 | @@ -1105,8 +1105,13 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, |
5514 | goto out; |
5515 | else if ((addr = (ulong)shmaddr)) { |
5516 | if (addr & (shmlba - 1)) { |
5517 | - if (shmflg & SHM_RND) |
5518 | - addr &= ~(shmlba - 1); /* round down */ |
5519 | + /* |
5520 | + * Round down to the nearest multiple of shmlba. |
5521 | + * For sane do_mmap_pgoff() parameters, avoid |
5522 | + * round downs that trigger nil-page and MAP_FIXED. |
5523 | + */ |
5524 | + if ((shmflg & SHM_RND) && addr >= shmlba) |
5525 | + addr &= ~(shmlba - 1); |
5526 | else |
5527 | #ifndef __ARCH_FORCE_SHMLBA |
5528 | if (addr & ~PAGE_MASK) |
5529 | diff --git a/kernel/membarrier.c b/kernel/membarrier.c |
5530 | index 536c727a56e9..9f9284f37f8d 100644 |
5531 | --- a/kernel/membarrier.c |
5532 | +++ b/kernel/membarrier.c |
5533 | @@ -16,6 +16,7 @@ |
5534 | |
5535 | #include <linux/syscalls.h> |
5536 | #include <linux/membarrier.h> |
5537 | +#include <linux/tick.h> |
5538 | |
5539 | /* |
5540 | * Bitmask made from a "or" of all commands within enum membarrier_cmd, |
5541 | @@ -51,6 +52,9 @@ |
5542 | */ |
5543 | SYSCALL_DEFINE2(membarrier, int, cmd, int, flags) |
5544 | { |
5545 | + /* MEMBARRIER_CMD_SHARED is not compatible with nohz_full. */ |
5546 | + if (tick_nohz_full_enabled()) |
5547 | + return -ENOSYS; |
5548 | if (unlikely(flags)) |
5549 | return -EINVAL; |
5550 | switch (cmd) { |
5551 | diff --git a/mm/filemap.c b/mm/filemap.c |
5552 | index c33c31d75a2b..69f75c77c098 100644 |
5553 | --- a/mm/filemap.c |
5554 | +++ b/mm/filemap.c |
5555 | @@ -865,9 +865,12 @@ void page_endio(struct page *page, int rw, int err) |
5556 | unlock_page(page); |
5557 | } else { /* rw == WRITE */ |
5558 | if (err) { |
5559 | + struct address_space *mapping; |
5560 | + |
5561 | SetPageError(page); |
5562 | - if (page->mapping) |
5563 | - mapping_set_error(page->mapping, err); |
5564 | + mapping = page_mapping(page); |
5565 | + if (mapping) |
5566 | + mapping_set_error(mapping, err); |
5567 | } |
5568 | end_page_writeback(page); |
5569 | } |
5570 | diff --git a/mm/page_alloc.c b/mm/page_alloc.c |
5571 | index 6a117213feb8..6f9005dcca2e 100644 |
5572 | --- a/mm/page_alloc.c |
5573 | +++ b/mm/page_alloc.c |
5574 | @@ -2467,7 +2467,7 @@ static bool zone_local(struct zone *local_zone, struct zone *zone) |
5575 | |
5576 | static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone) |
5577 | { |
5578 | - return node_distance(zone_to_nid(local_zone), zone_to_nid(zone)) < |
5579 | + return node_distance(zone_to_nid(local_zone), zone_to_nid(zone)) <= |
5580 | RECLAIM_DISTANCE; |
5581 | } |
5582 | #else /* CONFIG_NUMA */ |
5583 | diff --git a/mm/vmpressure.c b/mm/vmpressure.c |
5584 | index c5afd573d7da..3fb15c25af87 100644 |
5585 | --- a/mm/vmpressure.c |
5586 | +++ b/mm/vmpressure.c |
5587 | @@ -112,9 +112,16 @@ static enum vmpressure_levels vmpressure_calc_level(unsigned long scanned, |
5588 | unsigned long reclaimed) |
5589 | { |
5590 | unsigned long scale = scanned + reclaimed; |
5591 | - unsigned long pressure; |
5592 | + unsigned long pressure = 0; |
5593 | |
5594 | /* |
5595 | + * reclaimed can be greater than scanned in cases |
5596 | + * like THP, where the scanned is 1 and reclaimed |
5597 | + * could be 512 |
5598 | + */ |
5599 | + if (reclaimed >= scanned) |
5600 | + goto out; |
5601 | + /* |
5602 | * We calculate the ratio (in percents) of how many pages were |
5603 | * scanned vs. reclaimed in a given time frame (window). Note that |
5604 | * time is in VM reclaimer's "ticks", i.e. number of pages |
5605 | @@ -124,6 +131,7 @@ static enum vmpressure_levels vmpressure_calc_level(unsigned long scanned, |
5606 | pressure = scale - (reclaimed * scale / scanned); |
5607 | pressure = pressure * 100 / scale; |
5608 | |
5609 | +out: |
5610 | pr_debug("%s: %3lu (s: %lu r: %lu)\n", __func__, pressure, |
5611 | scanned, reclaimed); |
5612 | |
5613 | diff --git a/samples/mic/mpssd/.gitignore b/samples/mic/mpssd/.gitignore |
5614 | new file mode 100644 |
5615 | index 000000000000..8b7c72f07c92 |
5616 | --- /dev/null |
5617 | +++ b/samples/mic/mpssd/.gitignore |
5618 | @@ -0,0 +1 @@ |
5619 | +mpssd |
5620 | diff --git a/samples/mic/mpssd/Makefile b/samples/mic/mpssd/Makefile |
5621 | new file mode 100644 |
5622 | index 000000000000..3e3ef91fed6b |
5623 | --- /dev/null |
5624 | +++ b/samples/mic/mpssd/Makefile |
5625 | @@ -0,0 +1,27 @@ |
5626 | +ifndef CROSS_COMPILE |
5627 | +uname_M := $(shell uname -m 2>/dev/null || echo not) |
5628 | +ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) |
5629 | + |
5630 | +ifeq ($(ARCH),x86) |
5631 | + |
5632 | +PROGS := mpssd |
5633 | +CC = $(CROSS_COMPILE)gcc |
5634 | +CFLAGS := -I../../../usr/include -I../../../tools/include |
5635 | + |
5636 | +ifdef DEBUG |
5637 | +CFLAGS += -DDEBUG=$(DEBUG) |
5638 | +endif |
5639 | + |
5640 | +all: $(PROGS) |
5641 | +mpssd: mpssd.c sysfs.c |
5642 | + $(CC) $(CFLAGS) mpssd.c sysfs.c -o mpssd -lpthread |
5643 | + |
5644 | +install: |
5645 | + install mpssd /usr/sbin/mpssd |
5646 | + install micctrl /usr/sbin/micctrl |
5647 | + |
5648 | +clean: |
5649 | + rm -fr $(PROGS) |
5650 | + |
5651 | +endif |
5652 | +endif |
5653 | diff --git a/samples/mic/mpssd/micctrl b/samples/mic/mpssd/micctrl |
5654 | new file mode 100644 |
5655 | index 000000000000..8f2629b41c5f |
5656 | --- /dev/null |
5657 | +++ b/samples/mic/mpssd/micctrl |
5658 | @@ -0,0 +1,173 @@ |
5659 | +#!/bin/bash |
5660 | +# Intel MIC Platform Software Stack (MPSS) |
5661 | +# |
5662 | +# Copyright(c) 2013 Intel Corporation. |
5663 | +# |
5664 | +# This program is free software; you can redistribute it and/or modify |
5665 | +# it under the terms of the GNU General Public License, version 2, as |
5666 | +# published by the Free Software Foundation. |
5667 | +# |
5668 | +# This program is distributed in the hope that it will be useful, but |
5669 | +# WITHOUT ANY WARRANTY; without even the implied warranty of |
5670 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
5671 | +# General Public License for more details. |
5672 | +# |
5673 | +# The full GNU General Public License is included in this distribution in |
5674 | +# the file called "COPYING". |
5675 | +# |
5676 | +# Intel MIC User Space Tools. |
5677 | +# |
5678 | +# micctrl - Controls MIC boot/start/stop. |
5679 | +# |
5680 | +# chkconfig: 2345 95 05 |
5681 | +# description: start MPSS stack processing. |
5682 | +# |
5683 | +### BEGIN INIT INFO |
5684 | +# Provides: micctrl |
5685 | +### END INIT INFO |
5686 | + |
5687 | +# Source function library. |
5688 | +. /etc/init.d/functions |
5689 | + |
5690 | +sysfs="/sys/class/mic" |
5691 | + |
5692 | +_status() |
5693 | +{ |
5694 | + f=$sysfs/$1 |
5695 | + echo -e $1 state: "`cat $f/state`" shutdown_status: "`cat $f/shutdown_status`" |
5696 | +} |
5697 | + |
5698 | +status() |
5699 | +{ |
5700 | + if [ "`echo $1 | head -c3`" == "mic" ]; then |
5701 | + _status $1 |
5702 | + return $? |
5703 | + fi |
5704 | + for f in $sysfs/* |
5705 | + do |
5706 | + _status `basename $f` |
5707 | + RETVAL=$? |
5708 | + [ $RETVAL -ne 0 ] && return $RETVAL |
5709 | + done |
5710 | + return 0 |
5711 | +} |
5712 | + |
5713 | +_reset() |
5714 | +{ |
5715 | + f=$sysfs/$1 |
5716 | + echo reset > $f/state |
5717 | +} |
5718 | + |
5719 | +reset() |
5720 | +{ |
5721 | + if [ "`echo $1 | head -c3`" == "mic" ]; then |
5722 | + _reset $1 |
5723 | + return $? |
5724 | + fi |
5725 | + for f in $sysfs/* |
5726 | + do |
5727 | + _reset `basename $f` |
5728 | + RETVAL=$? |
5729 | + [ $RETVAL -ne 0 ] && return $RETVAL |
5730 | + done |
5731 | + return 0 |
5732 | +} |
5733 | + |
5734 | +_boot() |
5735 | +{ |
5736 | + f=$sysfs/$1 |
5737 | + echo "linux" > $f/bootmode |
5738 | + echo "mic/uos.img" > $f/firmware |
5739 | + echo "mic/$1.image" > $f/ramdisk |
5740 | + echo "boot" > $f/state |
5741 | +} |
5742 | + |
5743 | +boot() |
5744 | +{ |
5745 | + if [ "`echo $1 | head -c3`" == "mic" ]; then |
5746 | + _boot $1 |
5747 | + return $? |
5748 | + fi |
5749 | + for f in $sysfs/* |
5750 | + do |
5751 | + _boot `basename $f` |
5752 | + RETVAL=$? |
5753 | + [ $RETVAL -ne 0 ] && return $RETVAL |
5754 | + done |
5755 | + return 0 |
5756 | +} |
5757 | + |
5758 | +_shutdown() |
5759 | +{ |
5760 | + f=$sysfs/$1 |
5761 | + echo shutdown > $f/state |
5762 | +} |
5763 | + |
5764 | +shutdown() |
5765 | +{ |
5766 | + if [ "`echo $1 | head -c3`" == "mic" ]; then |
5767 | + _shutdown $1 |
5768 | + return $? |
5769 | + fi |
5770 | + for f in $sysfs/* |
5771 | + do |
5772 | + _shutdown `basename $f` |
5773 | + RETVAL=$? |
5774 | + [ $RETVAL -ne 0 ] && return $RETVAL |
5775 | + done |
5776 | + return 0 |
5777 | +} |
5778 | + |
5779 | +_wait() |
5780 | +{ |
5781 | + f=$sysfs/$1 |
5782 | + while [ "`cat $f/state`" != "offline" -a "`cat $f/state`" != "online" ] |
5783 | + do |
5784 | + sleep 1 |
5785 | + echo -e "Waiting for $1 to go offline" |
5786 | + done |
5787 | +} |
5788 | + |
5789 | +wait() |
5790 | +{ |
5791 | + if [ "`echo $1 | head -c3`" == "mic" ]; then |
5792 | + _wait $1 |
5793 | + return $? |
5794 | + fi |
5795 | + # Wait for the cards to go offline |
5796 | + for f in $sysfs/* |
5797 | + do |
5798 | + _wait `basename $f` |
5799 | + RETVAL=$? |
5800 | + [ $RETVAL -ne 0 ] && return $RETVAL |
5801 | + done |
5802 | + return 0 |
5803 | +} |
5804 | + |
5805 | +if [ ! -d "$sysfs" ]; then |
5806 | + echo -e $"Module unloaded " |
5807 | + exit 3 |
5808 | +fi |
5809 | + |
5810 | +case $1 in |
5811 | + -s) |
5812 | + status $2 |
5813 | + ;; |
5814 | + -r) |
5815 | + reset $2 |
5816 | + ;; |
5817 | + -b) |
5818 | + boot $2 |
5819 | + ;; |
5820 | + -S) |
5821 | + shutdown $2 |
5822 | + ;; |
5823 | + -w) |
5824 | + wait $2 |
5825 | + ;; |
5826 | + *) |
5827 | + echo $"Usage: $0 {-s (status) |-r (reset) |-b (boot) |-S (shutdown) |-w (wait)}" |
5828 | + exit 2 |
5829 | +esac |
5830 | + |
5831 | +exit $? |
5832 | diff --git a/samples/mic/mpssd/mpss b/samples/mic/mpssd/mpss |
5833 | new file mode 100644 |
5834 | index 000000000000..09ea90931649 |
5835 | --- /dev/null |
5836 | +++ b/samples/mic/mpssd/mpss |
5837 | @@ -0,0 +1,200 @@ |
5838 | +#!/bin/bash |
5839 | +# Intel MIC Platform Software Stack (MPSS) |
5840 | +# |
5841 | +# Copyright(c) 2013 Intel Corporation. |
5842 | +# |
5843 | +# This program is free software; you can redistribute it and/or modify |
5844 | +# it under the terms of the GNU General Public License, version 2, as |
5845 | +# published by the Free Software Foundation. |
5846 | +# |
5847 | +# This program is distributed in the hope that it will be useful, but |
5848 | +# WITHOUT ANY WARRANTY; without even the implied warranty of |
5849 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
5850 | +# General Public License for more details. |
5851 | +# |
5852 | +# The full GNU General Public License is included in this distribution in |
5853 | +# the file called "COPYING". |
5854 | +# |
5855 | +# Intel MIC User Space Tools. |
5856 | +# |
5857 | +# mpss Start mpssd. |
5858 | +# |
5859 | +# chkconfig: 2345 95 05 |
5860 | +# description: start MPSS stack processing. |
5861 | +# |
5862 | +### BEGIN INIT INFO |
5863 | +# Provides: mpss |
5864 | +# Required-Start: |
5865 | +# Required-Stop: |
5866 | +# Short-Description: MPSS stack control |
5867 | +# Description: MPSS stack control |
5868 | +### END INIT INFO |
5869 | + |
5870 | +# Source function library. |
5871 | +. /etc/init.d/functions |
5872 | + |
5873 | +exec=/usr/sbin/mpssd |
5874 | +sysfs="/sys/class/mic" |
5875 | +mic_modules="mic_host mic_x100_dma scif" |
5876 | + |
5877 | +start() |
5878 | +{ |
5879 | + [ -x $exec ] || exit 5 |
5880 | + |
5881 | + if [ "`ps -e | awk '{print $4}' | grep mpssd | head -1`" = "mpssd" ]; then |
5882 | + echo -e $"MPSSD already running! " |
5883 | + success |
5884 | + echo |
5885 | + return 0 |
5886 | + fi |
5887 | + |
5888 | + echo -e $"Starting MPSS Stack" |
5889 | + echo -e $"Loading MIC drivers:" $mic_modules |
5890 | + |
5891 | + modprobe -a $mic_modules |
5892 | + RETVAL=$? |
5893 | + if [ $RETVAL -ne 0 ]; then |
5894 | + failure |
5895 | + echo |
5896 | + return $RETVAL |
5897 | + fi |
5898 | + |
5899 | + # Start the daemon |
5900 | + echo -n $"Starting MPSSD " |
5901 | + $exec |
5902 | + RETVAL=$? |
5903 | + if [ $RETVAL -ne 0 ]; then |
5904 | + failure |
5905 | + echo |
5906 | + return $RETVAL |
5907 | + fi |
5908 | + success |
5909 | + echo |
5910 | + |
5911 | + sleep 5 |
5912 | + |
5913 | + # Boot the cards |
5914 | + micctrl -b |
5915 | + |
5916 | + # Wait till ping works |
5917 | + for f in $sysfs/* |
5918 | + do |
5919 | + count=100 |
5920 | + ipaddr=`cat $f/cmdline` |
5921 | + ipaddr=${ipaddr#*address,} |
5922 | + ipaddr=`echo $ipaddr | cut -d, -f1 | cut -d\; -f1` |
5923 | + while [ $count -ge 0 ] |
5924 | + do |
5925 | + echo -e "Pinging "`basename $f`" " |
5926 | + ping -c 1 $ipaddr &> /dev/null |
5927 | + RETVAL=$? |
5928 | + if [ $RETVAL -eq 0 ]; then |
5929 | + success |
5930 | + break |
5931 | + fi |
5932 | + sleep 1 |
5933 | + count=`expr $count - 1` |
5934 | + done |
5935 | + [ $RETVAL -ne 0 ] && failure || success |
5936 | + echo |
5937 | + done |
5938 | + return $RETVAL |
5939 | +} |
5940 | + |
5941 | +stop() |
5942 | +{ |
5943 | + echo -e $"Shutting down MPSS Stack: " |
5944 | + |
5945 | + # Bail out if module is unloaded |
5946 | + if [ ! -d "$sysfs" ]; then |
5947 | + echo -n $"Module unloaded " |
5948 | + success |
5949 | + echo |
5950 | + return 0 |
5951 | + fi |
5952 | + |
5953 | + # Shut down the cards. |
5954 | + micctrl -S |
5955 | + |
5956 | + # Wait for the cards to go offline |
5957 | + for f in $sysfs/* |
5958 | + do |
5959 | + while [ "`cat $f/state`" != "ready" ] |
5960 | + do |
5961 | + sleep 1 |
5962 | + echo -e "Waiting for "`basename $f`" to become ready" |
5963 | + done |
5964 | + done |
5965 | + |
5966 | + # Display the status of the cards |
5967 | + micctrl -s |
5968 | + |
5969 | + # Kill MPSSD now |
5970 | + echo -n $"Killing MPSSD" |
5971 | + killall -9 mpssd 2>/dev/null |
5972 | + RETVAL=$? |
5973 | + [ $RETVAL -ne 0 ] && failure || success |
5974 | + echo |
5975 | + return $RETVAL |
5976 | +} |
5977 | + |
5978 | +restart() |
5979 | +{ |
5980 | + stop |
5981 | + sleep 5 |
5982 | + start |
5983 | +} |
5984 | + |
5985 | +status() |
5986 | +{ |
5987 | + micctrl -s |
5988 | + if [ "`ps -e | awk '{print $4}' | grep mpssd | head -n 1`" = "mpssd" ]; then |
5989 | + echo "mpssd is running" |
5990 | + else |
5991 | + echo "mpssd is stopped" |
5992 | + fi |
5993 | + return 0 |
5994 | +} |
5995 | + |
5996 | +unload() |
5997 | +{ |
5998 | + if [ ! -d "$sysfs" ]; then |
5999 | + echo -n $"No MIC_HOST Module: " |
6000 | + success |
6001 | + echo |
6002 | + return |
6003 | + fi |
6004 | + |
6005 | + stop |
6006 | + |
6007 | + sleep 5 |
6008 | + echo -n $"Removing MIC drivers:" $mic_modules |
6009 | + modprobe -r $mic_modules |
6010 | + RETVAL=$? |
6011 | + [ $RETVAL -ne 0 ] && failure || success |
6012 | + echo |
6013 | + return $RETVAL |
6014 | +} |
6015 | + |
6016 | +case $1 in |
6017 | + start) |
6018 | + start |
6019 | + ;; |
6020 | + stop) |
6021 | + stop |
6022 | + ;; |
6023 | + restart) |
6024 | + restart |
6025 | + ;; |
6026 | + status) |
6027 | + status |
6028 | + ;; |
6029 | + unload) |
6030 | + unload |
6031 | + ;; |
6032 | + *) |
6033 | + echo $"Usage: $0 {start|stop|restart|status|unload}" |
6034 | + exit 2 |
6035 | +esac |
6036 | + |
6037 | +exit $? |
6038 | diff --git a/samples/mic/mpssd/mpssd.c b/samples/mic/mpssd/mpssd.c |
6039 | new file mode 100644 |
6040 | index 000000000000..c99a75968c01 |
6041 | --- /dev/null |
6042 | +++ b/samples/mic/mpssd/mpssd.c |
6043 | @@ -0,0 +1,1826 @@ |
6044 | +/* |
6045 | + * Intel MIC Platform Software Stack (MPSS) |
6046 | + * |
6047 | + * Copyright(c) 2013 Intel Corporation. |
6048 | + * |
6049 | + * This program is free software; you can redistribute it and/or modify |
6050 | + * it under the terms of the GNU General Public License, version 2, as |
6051 | + * published by the Free Software Foundation. |
6052 | + * |
6053 | + * This program is distributed in the hope that it will be useful, but |
6054 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
6055 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
6056 | + * General Public License for more details. |
6057 | + * |
6058 | + * The full GNU General Public License is included in this distribution in |
6059 | + * the file called "COPYING". |
6060 | + * |
6061 | + * Intel MIC User Space Tools. |
6062 | + */ |
6063 | + |
6064 | +#define _GNU_SOURCE |
6065 | + |
6066 | +#include <stdlib.h> |
6067 | +#include <fcntl.h> |
6068 | +#include <getopt.h> |
6069 | +#include <assert.h> |
6070 | +#include <unistd.h> |
6071 | +#include <stdbool.h> |
6072 | +#include <signal.h> |
6073 | +#include <poll.h> |
6074 | +#include <features.h> |
6075 | +#include <sys/types.h> |
6076 | +#include <sys/stat.h> |
6077 | +#include <sys/mman.h> |
6078 | +#include <sys/socket.h> |
6079 | +#include <linux/virtio_ring.h> |
6080 | +#include <linux/virtio_net.h> |
6081 | +#include <linux/virtio_console.h> |
6082 | +#include <linux/virtio_blk.h> |
6083 | +#include <linux/version.h> |
6084 | +#include "mpssd.h" |
6085 | +#include <linux/mic_ioctl.h> |
6086 | +#include <linux/mic_common.h> |
6087 | +#include <tools/endian.h> |
6088 | + |
6089 | +static void *init_mic(void *arg); |
6090 | + |
6091 | +static FILE *logfp; |
6092 | +static struct mic_info mic_list; |
6093 | + |
6094 | +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
6095 | + |
6096 | +#define min_t(type, x, y) ({ \ |
6097 | + type __min1 = (x); \ |
6098 | + type __min2 = (y); \ |
6099 | + __min1 < __min2 ? __min1 : __min2; }) |
6100 | + |
6101 | +/* align addr on a size boundary - adjust address up/down if needed */ |
6102 | +#define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1))) |
6103 | +#define _ALIGN_UP(addr, size) _ALIGN_DOWN(addr + size - 1, size) |
6104 | + |
6105 | +/* align addr on a size boundary - adjust address up if needed */ |
6106 | +#define _ALIGN(addr, size) _ALIGN_UP(addr, size) |
6107 | + |
6108 | +/* to align the pointer to the (next) page boundary */ |
6109 | +#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) |
6110 | + |
6111 | +#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) |
6112 | + |
6113 | +#define GSO_ENABLED 1 |
6114 | +#define MAX_GSO_SIZE (64 * 1024) |
6115 | +#define ETH_H_LEN 14 |
6116 | +#define MAX_NET_PKT_SIZE (_ALIGN_UP(MAX_GSO_SIZE + ETH_H_LEN, 64)) |
6117 | +#define MIC_DEVICE_PAGE_END 0x1000 |
6118 | + |
6119 | +#ifndef VIRTIO_NET_HDR_F_DATA_VALID |
6120 | +#define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */ |
6121 | +#endif |
6122 | + |
6123 | +static struct { |
6124 | + struct mic_device_desc dd; |
6125 | + struct mic_vqconfig vqconfig[2]; |
6126 | + __u32 host_features, guest_acknowledgements; |
6127 | + struct virtio_console_config cons_config; |
6128 | +} virtcons_dev_page = { |
6129 | + .dd = { |
6130 | + .type = VIRTIO_ID_CONSOLE, |
6131 | + .num_vq = ARRAY_SIZE(virtcons_dev_page.vqconfig), |
6132 | + .feature_len = sizeof(virtcons_dev_page.host_features), |
6133 | + .config_len = sizeof(virtcons_dev_page.cons_config), |
6134 | + }, |
6135 | + .vqconfig[0] = { |
6136 | + .num = htole16(MIC_VRING_ENTRIES), |
6137 | + }, |
6138 | + .vqconfig[1] = { |
6139 | + .num = htole16(MIC_VRING_ENTRIES), |
6140 | + }, |
6141 | +}; |
6142 | + |
6143 | +static struct { |
6144 | + struct mic_device_desc dd; |
6145 | + struct mic_vqconfig vqconfig[2]; |
6146 | + __u32 host_features, guest_acknowledgements; |
6147 | + struct virtio_net_config net_config; |
6148 | +} virtnet_dev_page = { |
6149 | + .dd = { |
6150 | + .type = VIRTIO_ID_NET, |
6151 | + .num_vq = ARRAY_SIZE(virtnet_dev_page.vqconfig), |
6152 | + .feature_len = sizeof(virtnet_dev_page.host_features), |
6153 | + .config_len = sizeof(virtnet_dev_page.net_config), |
6154 | + }, |
6155 | + .vqconfig[0] = { |
6156 | + .num = htole16(MIC_VRING_ENTRIES), |
6157 | + }, |
6158 | + .vqconfig[1] = { |
6159 | + .num = htole16(MIC_VRING_ENTRIES), |
6160 | + }, |
6161 | +#if GSO_ENABLED |
6162 | + .host_features = htole32( |
6163 | + 1 << VIRTIO_NET_F_CSUM | |
6164 | + 1 << VIRTIO_NET_F_GSO | |
6165 | + 1 << VIRTIO_NET_F_GUEST_TSO4 | |
6166 | + 1 << VIRTIO_NET_F_GUEST_TSO6 | |
6167 | + 1 << VIRTIO_NET_F_GUEST_ECN), |
6168 | +#else |
6169 | + .host_features = 0, |
6170 | +#endif |
6171 | +}; |
6172 | + |
6173 | +static const char *mic_config_dir = "/etc/mpss"; |
6174 | +static const char *virtblk_backend = "VIRTBLK_BACKEND"; |
6175 | +static struct { |
6176 | + struct mic_device_desc dd; |
6177 | + struct mic_vqconfig vqconfig[1]; |
6178 | + __u32 host_features, guest_acknowledgements; |
6179 | + struct virtio_blk_config blk_config; |
6180 | +} virtblk_dev_page = { |
6181 | + .dd = { |
6182 | + .type = VIRTIO_ID_BLOCK, |
6183 | + .num_vq = ARRAY_SIZE(virtblk_dev_page.vqconfig), |
6184 | + .feature_len = sizeof(virtblk_dev_page.host_features), |
6185 | + .config_len = sizeof(virtblk_dev_page.blk_config), |
6186 | + }, |
6187 | + .vqconfig[0] = { |
6188 | + .num = htole16(MIC_VRING_ENTRIES), |
6189 | + }, |
6190 | + .host_features = |
6191 | + htole32(1<<VIRTIO_BLK_F_SEG_MAX), |
6192 | + .blk_config = { |
6193 | + .seg_max = htole32(MIC_VRING_ENTRIES - 2), |
6194 | + .capacity = htole64(0), |
6195 | + } |
6196 | +}; |
6197 | + |
6198 | +static char *myname; |
6199 | + |
6200 | +static int |
6201 | +tap_configure(struct mic_info *mic, char *dev) |
6202 | +{ |
6203 | + pid_t pid; |
6204 | + char *ifargv[7]; |
6205 | + char ipaddr[IFNAMSIZ]; |
6206 | + int ret = 0; |
6207 | + |
6208 | + pid = fork(); |
6209 | + if (pid == 0) { |
6210 | + ifargv[0] = "ip"; |
6211 | + ifargv[1] = "link"; |
6212 | + ifargv[2] = "set"; |
6213 | + ifargv[3] = dev; |
6214 | + ifargv[4] = "up"; |
6215 | + ifargv[5] = NULL; |
6216 | + mpsslog("Configuring %s\n", dev); |
6217 | + ret = execvp("ip", ifargv); |
6218 | + if (ret < 0) { |
6219 | + mpsslog("%s execvp failed errno %s\n", |
6220 | + mic->name, strerror(errno)); |
6221 | + return ret; |
6222 | + } |
6223 | + } |
6224 | + if (pid < 0) { |
6225 | + mpsslog("%s fork failed errno %s\n", |
6226 | + mic->name, strerror(errno)); |
6227 | + return ret; |
6228 | + } |
6229 | + |
6230 | + ret = waitpid(pid, NULL, 0); |
6231 | + if (ret < 0) { |
6232 | + mpsslog("%s waitpid failed errno %s\n", |
6233 | + mic->name, strerror(errno)); |
6234 | + return ret; |
6235 | + } |
6236 | + |
6237 | + snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id + 1); |
6238 | + |
6239 | + pid = fork(); |
6240 | + if (pid == 0) { |
6241 | + ifargv[0] = "ip"; |
6242 | + ifargv[1] = "addr"; |
6243 | + ifargv[2] = "add"; |
6244 | + ifargv[3] = ipaddr; |
6245 | + ifargv[4] = "dev"; |
6246 | + ifargv[5] = dev; |
6247 | + ifargv[6] = NULL; |
6248 | + mpsslog("Configuring %s ipaddr %s\n", dev, ipaddr); |
6249 | + ret = execvp("ip", ifargv); |
6250 | + if (ret < 0) { |
6251 | + mpsslog("%s execvp failed errno %s\n", |
6252 | + mic->name, strerror(errno)); |
6253 | + return ret; |
6254 | + } |
6255 | + } |
6256 | + if (pid < 0) { |
6257 | + mpsslog("%s fork failed errno %s\n", |
6258 | + mic->name, strerror(errno)); |
6259 | + return ret; |
6260 | + } |
6261 | + |
6262 | + ret = waitpid(pid, NULL, 0); |
6263 | + if (ret < 0) { |
6264 | + mpsslog("%s waitpid failed errno %s\n", |
6265 | + mic->name, strerror(errno)); |
6266 | + return ret; |
6267 | + } |
6268 | + mpsslog("MIC name %s %s %d DONE!\n", |
6269 | + mic->name, __func__, __LINE__); |
6270 | + return 0; |
6271 | +} |
6272 | + |
6273 | +static int tun_alloc(struct mic_info *mic, char *dev) |
6274 | +{ |
6275 | + struct ifreq ifr; |
6276 | + int fd, err; |
6277 | +#if GSO_ENABLED |
6278 | + unsigned offload; |
6279 | +#endif |
6280 | + fd = open("/dev/net/tun", O_RDWR); |
6281 | + if (fd < 0) { |
6282 | + mpsslog("Could not open /dev/net/tun %s\n", strerror(errno)); |
6283 | + goto done; |
6284 | + } |
6285 | + |
6286 | + memset(&ifr, 0, sizeof(ifr)); |
6287 | + |
6288 | + ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR; |
6289 | + if (*dev) |
6290 | + strncpy(ifr.ifr_name, dev, IFNAMSIZ); |
6291 | + |
6292 | + err = ioctl(fd, TUNSETIFF, (void *)&ifr); |
6293 | + if (err < 0) { |
6294 | + mpsslog("%s %s %d TUNSETIFF failed %s\n", |
6295 | + mic->name, __func__, __LINE__, strerror(errno)); |
6296 | + close(fd); |
6297 | + return err; |
6298 | + } |
6299 | +#if GSO_ENABLED |
6300 | + offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_TSO_ECN; |
6301 | + |
6302 | + err = ioctl(fd, TUNSETOFFLOAD, offload); |
6303 | + if (err < 0) { |
6304 | + mpsslog("%s %s %d TUNSETOFFLOAD failed %s\n", |
6305 | + mic->name, __func__, __LINE__, strerror(errno)); |
6306 | + close(fd); |
6307 | + return err; |
6308 | + } |
6309 | +#endif |
6310 | + strcpy(dev, ifr.ifr_name); |
6311 | + mpsslog("Created TAP %s\n", dev); |
6312 | +done: |
6313 | + return fd; |
6314 | +} |
6315 | + |
6316 | +#define NET_FD_VIRTIO_NET 0 |
6317 | +#define NET_FD_TUN 1 |
6318 | +#define MAX_NET_FD 2 |
6319 | + |
6320 | +static void set_dp(struct mic_info *mic, int type, void *dp) |
6321 | +{ |
6322 | + switch (type) { |
6323 | + case VIRTIO_ID_CONSOLE: |
6324 | + mic->mic_console.console_dp = dp; |
6325 | + return; |
6326 | + case VIRTIO_ID_NET: |
6327 | + mic->mic_net.net_dp = dp; |
6328 | + return; |
6329 | + case VIRTIO_ID_BLOCK: |
6330 | + mic->mic_virtblk.block_dp = dp; |
6331 | + return; |
6332 | + } |
6333 | + mpsslog("%s %s %d not found\n", mic->name, __func__, type); |
6334 | + assert(0); |
6335 | +} |
6336 | + |
6337 | +static void *get_dp(struct mic_info *mic, int type) |
6338 | +{ |
6339 | + switch (type) { |
6340 | + case VIRTIO_ID_CONSOLE: |
6341 | + return mic->mic_console.console_dp; |
6342 | + case VIRTIO_ID_NET: |
6343 | + return mic->mic_net.net_dp; |
6344 | + case VIRTIO_ID_BLOCK: |
6345 | + return mic->mic_virtblk.block_dp; |
6346 | + } |
6347 | + mpsslog("%s %s %d not found\n", mic->name, __func__, type); |
6348 | + assert(0); |
6349 | + return NULL; |
6350 | +} |
6351 | + |
6352 | +static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type) |
6353 | +{ |
6354 | + struct mic_device_desc *d; |
6355 | + int i; |
6356 | + void *dp = get_dp(mic, type); |
6357 | + |
6358 | + for (i = sizeof(struct mic_bootparam); i < PAGE_SIZE; |
6359 | + i += mic_total_desc_size(d)) { |
6360 | + d = dp + i; |
6361 | + |
6362 | + /* End of list */ |
6363 | + if (d->type == 0) |
6364 | + break; |
6365 | + |
6366 | + if (d->type == -1) |
6367 | + continue; |
6368 | + |
6369 | + mpsslog("%s %s d-> type %d d %p\n", |
6370 | + mic->name, __func__, d->type, d); |
6371 | + |
6372 | + if (d->type == (__u8)type) |
6373 | + return d; |
6374 | + } |
6375 | + mpsslog("%s %s %d not found\n", mic->name, __func__, type); |
6376 | + return NULL; |
6377 | +} |
6378 | + |
6379 | +/* See comments in vhost.c for explanation of next_desc() */ |
6380 | +static unsigned next_desc(struct vring_desc *desc) |
6381 | +{ |
6382 | + unsigned int next; |
6383 | + |
6384 | + if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT)) |
6385 | + return -1U; |
6386 | + next = le16toh(desc->next); |
6387 | + return next; |
6388 | +} |
6389 | + |
6390 | +/* Sum up all the IOVEC length */ |
6391 | +static ssize_t |
6392 | +sum_iovec_len(struct mic_copy_desc *copy) |
6393 | +{ |
6394 | + ssize_t sum = 0; |
6395 | + int i; |
6396 | + |
6397 | + for (i = 0; i < copy->iovcnt; i++) |
6398 | + sum += copy->iov[i].iov_len; |
6399 | + return sum; |
6400 | +} |
6401 | + |
6402 | +static inline void verify_out_len(struct mic_info *mic, |
6403 | + struct mic_copy_desc *copy) |
6404 | +{ |
6405 | + if (copy->out_len != sum_iovec_len(copy)) { |
6406 | + mpsslog("%s %s %d BUG copy->out_len 0x%x len 0x%zx\n", |
6407 | + mic->name, __func__, __LINE__, |
6408 | + copy->out_len, sum_iovec_len(copy)); |
6409 | + assert(copy->out_len == sum_iovec_len(copy)); |
6410 | + } |
6411 | +} |
6412 | + |
6413 | +/* Display an iovec */ |
6414 | +static void |
6415 | +disp_iovec(struct mic_info *mic, struct mic_copy_desc *copy, |
6416 | + const char *s, int line) |
6417 | +{ |
6418 | + int i; |
6419 | + |
6420 | + for (i = 0; i < copy->iovcnt; i++) |
6421 | + mpsslog("%s %s %d copy->iov[%d] addr %p len 0x%zx\n", |
6422 | + mic->name, s, line, i, |
6423 | + copy->iov[i].iov_base, copy->iov[i].iov_len); |
6424 | +} |
6425 | + |
6426 | +static inline __u16 read_avail_idx(struct mic_vring *vr) |
6427 | +{ |
6428 | + return ACCESS_ONCE(vr->info->avail_idx); |
6429 | +} |
6430 | + |
6431 | +static inline void txrx_prepare(int type, bool tx, struct mic_vring *vr, |
6432 | + struct mic_copy_desc *copy, ssize_t len) |
6433 | +{ |
6434 | + copy->vr_idx = tx ? 0 : 1; |
6435 | + copy->update_used = true; |
6436 | + if (type == VIRTIO_ID_NET) |
6437 | + copy->iov[1].iov_len = len - sizeof(struct virtio_net_hdr); |
6438 | + else |
6439 | + copy->iov[0].iov_len = len; |
6440 | +} |
6441 | + |
6442 | +/* Central API which triggers the copies */ |
6443 | +static int |
6444 | +mic_virtio_copy(struct mic_info *mic, int fd, |
6445 | + struct mic_vring *vr, struct mic_copy_desc *copy) |
6446 | +{ |
6447 | + int ret; |
6448 | + |
6449 | + ret = ioctl(fd, MIC_VIRTIO_COPY_DESC, copy); |
6450 | + if (ret) { |
6451 | + mpsslog("%s %s %d errno %s ret %d\n", |
6452 | + mic->name, __func__, __LINE__, |
6453 | + strerror(errno), ret); |
6454 | + } |
6455 | + return ret; |
6456 | +} |
6457 | + |
6458 | +static inline unsigned _vring_size(unsigned int num, unsigned long align) |
6459 | +{ |
6460 | + return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (3 + num) |
6461 | + + align - 1) & ~(align - 1)) |
6462 | + + sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num; |
6463 | +} |
6464 | + |
6465 | +/* |
6466 | + * This initialization routine requires at least one |
6467 | + * vring i.e. vr0. vr1 is optional. |
6468 | + */ |
6469 | +static void * |
6470 | +init_vr(struct mic_info *mic, int fd, int type, |
6471 | + struct mic_vring *vr0, struct mic_vring *vr1, int num_vq) |
6472 | +{ |
6473 | + int vr_size; |
6474 | + char *va; |
6475 | + |
6476 | + vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES, |
6477 | + MIC_VIRTIO_RING_ALIGN) + |
6478 | + sizeof(struct _mic_vring_info)); |
6479 | + va = mmap(NULL, MIC_DEVICE_PAGE_END + vr_size * num_vq, |
6480 | + PROT_READ, MAP_SHARED, fd, 0); |
6481 | + if (MAP_FAILED == va) { |
6482 | + mpsslog("%s %s %d mmap failed errno %s\n", |
6483 | + mic->name, __func__, __LINE__, |
6484 | + strerror(errno)); |
6485 | + goto done; |
6486 | + } |
6487 | + set_dp(mic, type, va); |
6488 | + vr0->va = (struct mic_vring *)&va[MIC_DEVICE_PAGE_END]; |
6489 | + vr0->info = vr0->va + |
6490 | + _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN); |
6491 | + vring_init(&vr0->vr, |
6492 | + MIC_VRING_ENTRIES, vr0->va, MIC_VIRTIO_RING_ALIGN); |
6493 | + mpsslog("%s %s vr0 %p vr0->info %p vr_size 0x%x vring 0x%x ", |
6494 | + __func__, mic->name, vr0->va, vr0->info, vr_size, |
6495 | + _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN)); |
6496 | + mpsslog("magic 0x%x expected 0x%x\n", |
6497 | + le32toh(vr0->info->magic), MIC_MAGIC + type); |
6498 | + assert(le32toh(vr0->info->magic) == MIC_MAGIC + type); |
6499 | + if (vr1) { |
6500 | + vr1->va = (struct mic_vring *) |
6501 | + &va[MIC_DEVICE_PAGE_END + vr_size]; |
6502 | + vr1->info = vr1->va + _vring_size(MIC_VRING_ENTRIES, |
6503 | + MIC_VIRTIO_RING_ALIGN); |
6504 | + vring_init(&vr1->vr, |
6505 | + MIC_VRING_ENTRIES, vr1->va, MIC_VIRTIO_RING_ALIGN); |
6506 | + mpsslog("%s %s vr1 %p vr1->info %p vr_size 0x%x vring 0x%x ", |
6507 | + __func__, mic->name, vr1->va, vr1->info, vr_size, |
6508 | + _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN)); |
6509 | + mpsslog("magic 0x%x expected 0x%x\n", |
6510 | + le32toh(vr1->info->magic), MIC_MAGIC + type + 1); |
6511 | + assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1); |
6512 | + } |
6513 | +done: |
6514 | + return va; |
6515 | +} |
6516 | + |
6517 | +static int |
6518 | +wait_for_card_driver(struct mic_info *mic, int fd, int type) |
6519 | +{ |
6520 | + struct pollfd pollfd; |
6521 | + int err; |
6522 | + struct mic_device_desc *desc = get_device_desc(mic, type); |
6523 | + __u8 prev_status; |
6524 | + |
6525 | + if (!desc) |
6526 | + return -ENODEV; |
6527 | + prev_status = desc->status; |
6528 | + pollfd.fd = fd; |
6529 | + mpsslog("%s %s Waiting .... desc-> type %d status 0x%x\n", |
6530 | + mic->name, __func__, type, desc->status); |
6531 | + |
6532 | + while (1) { |
6533 | + pollfd.events = POLLIN; |
6534 | + pollfd.revents = 0; |
6535 | + err = poll(&pollfd, 1, -1); |
6536 | + if (err < 0) { |
6537 | + mpsslog("%s %s poll failed %s\n", |
6538 | + mic->name, __func__, strerror(errno)); |
6539 | + continue; |
6540 | + } |
6541 | + |
6542 | + if (pollfd.revents) { |
6543 | + if (desc->status != prev_status) { |
6544 | + mpsslog("%s %s Waiting... desc-> type %d " |
6545 | + "status 0x%x\n", |
6546 | + mic->name, __func__, type, |
6547 | + desc->status); |
6548 | + prev_status = desc->status; |
6549 | + } |
6550 | + if (desc->status & VIRTIO_CONFIG_S_DRIVER_OK) { |
6551 | + mpsslog("%s %s poll.revents %d\n", |
6552 | + mic->name, __func__, pollfd.revents); |
6553 | + mpsslog("%s %s desc-> type %d status 0x%x\n", |
6554 | + mic->name, __func__, type, |
6555 | + desc->status); |
6556 | + break; |
6557 | + } |
6558 | + } |
6559 | + } |
6560 | + return 0; |
6561 | +} |
6562 | + |
6563 | +/* Spin till we have some descriptors */ |
6564 | +static void |
6565 | +spin_for_descriptors(struct mic_info *mic, struct mic_vring *vr) |
6566 | +{ |
6567 | + __u16 avail_idx = read_avail_idx(vr); |
6568 | + |
6569 | + while (avail_idx == le16toh(ACCESS_ONCE(vr->vr.avail->idx))) { |
6570 | +#ifdef DEBUG |
6571 | + mpsslog("%s %s waiting for desc avail %d info_avail %d\n", |
6572 | + mic->name, __func__, |
6573 | + le16toh(vr->vr.avail->idx), vr->info->avail_idx); |
6574 | +#endif |
6575 | + sched_yield(); |
6576 | + } |
6577 | +} |
6578 | + |
6579 | +static void * |
6580 | +virtio_net(void *arg) |
6581 | +{ |
6582 | + static __u8 vnet_hdr[2][sizeof(struct virtio_net_hdr)]; |
6583 | + static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __attribute__ ((aligned(64))); |
6584 | + struct iovec vnet_iov[2][2] = { |
6585 | + { { .iov_base = vnet_hdr[0], .iov_len = sizeof(vnet_hdr[0]) }, |
6586 | + { .iov_base = vnet_buf[0], .iov_len = sizeof(vnet_buf[0]) } }, |
6587 | + { { .iov_base = vnet_hdr[1], .iov_len = sizeof(vnet_hdr[1]) }, |
6588 | + { .iov_base = vnet_buf[1], .iov_len = sizeof(vnet_buf[1]) } }, |
6589 | + }; |
6590 | + struct iovec *iov0 = vnet_iov[0], *iov1 = vnet_iov[1]; |
6591 | + struct mic_info *mic = (struct mic_info *)arg; |
6592 | + char if_name[IFNAMSIZ]; |
6593 | + struct pollfd net_poll[MAX_NET_FD]; |
6594 | + struct mic_vring tx_vr, rx_vr; |
6595 | + struct mic_copy_desc copy; |
6596 | + struct mic_device_desc *desc; |
6597 | + int err; |
6598 | + |
6599 | + snprintf(if_name, IFNAMSIZ, "mic%d", mic->id); |
6600 | + mic->mic_net.tap_fd = tun_alloc(mic, if_name); |
6601 | + if (mic->mic_net.tap_fd < 0) |
6602 | + goto done; |
6603 | + |
6604 | + if (tap_configure(mic, if_name)) |
6605 | + goto done; |
6606 | + mpsslog("MIC name %s id %d\n", mic->name, mic->id); |
6607 | + |
6608 | + net_poll[NET_FD_VIRTIO_NET].fd = mic->mic_net.virtio_net_fd; |
6609 | + net_poll[NET_FD_VIRTIO_NET].events = POLLIN; |
6610 | + net_poll[NET_FD_TUN].fd = mic->mic_net.tap_fd; |
6611 | + net_poll[NET_FD_TUN].events = POLLIN; |
6612 | + |
6613 | + if (MAP_FAILED == init_vr(mic, mic->mic_net.virtio_net_fd, |
6614 | + VIRTIO_ID_NET, &tx_vr, &rx_vr, |
6615 | + virtnet_dev_page.dd.num_vq)) { |
6616 | + mpsslog("%s init_vr failed %s\n", |
6617 | + mic->name, strerror(errno)); |
6618 | + goto done; |
6619 | + } |
6620 | + |
6621 | + copy.iovcnt = 2; |
6622 | + desc = get_device_desc(mic, VIRTIO_ID_NET); |
6623 | + |
6624 | + while (1) { |
6625 | + ssize_t len; |
6626 | + |
6627 | + net_poll[NET_FD_VIRTIO_NET].revents = 0; |
6628 | + net_poll[NET_FD_TUN].revents = 0; |
6629 | + |
6630 | + /* Start polling for data from tap and virtio net */ |
6631 | + err = poll(net_poll, 2, -1); |
6632 | + if (err < 0) { |
6633 | + mpsslog("%s poll failed %s\n", |
6634 | + __func__, strerror(errno)); |
6635 | + continue; |
6636 | + } |
6637 | + if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) { |
6638 | + err = wait_for_card_driver(mic, |
6639 | + mic->mic_net.virtio_net_fd, |
6640 | + VIRTIO_ID_NET); |
6641 | + if (err) { |
6642 | + mpsslog("%s %s %d Exiting...\n", |
6643 | + mic->name, __func__, __LINE__); |
6644 | + break; |
6645 | + } |
6646 | + } |
6647 | + /* |
6648 | + * Check if there is data to be read from TUN and write to |
6649 | + * virtio net fd if there is. |
6650 | + */ |
6651 | + if (net_poll[NET_FD_TUN].revents & POLLIN) { |
6652 | + copy.iov = iov0; |
6653 | + len = readv(net_poll[NET_FD_TUN].fd, |
6654 | + copy.iov, copy.iovcnt); |
6655 | + if (len > 0) { |
6656 | + struct virtio_net_hdr *hdr |
6657 | + = (struct virtio_net_hdr *)vnet_hdr[0]; |
6658 | + |
6659 | + /* Disable checksums on the card since we are on |
6660 | + a reliable PCIe link */ |
6661 | + hdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID; |
6662 | +#ifdef DEBUG |
6663 | + mpsslog("%s %s %d hdr->flags 0x%x ", mic->name, |
6664 | + __func__, __LINE__, hdr->flags); |
6665 | + mpsslog("copy.out_len %d hdr->gso_type 0x%x\n", |
6666 | + copy.out_len, hdr->gso_type); |
6667 | +#endif |
6668 | +#ifdef DEBUG |
6669 | + disp_iovec(mic, copy, __func__, __LINE__); |
6670 | + mpsslog("%s %s %d read from tap 0x%lx\n", |
6671 | + mic->name, __func__, __LINE__, |
6672 | + len); |
6673 | +#endif |
6674 | + spin_for_descriptors(mic, &tx_vr); |
6675 | + txrx_prepare(VIRTIO_ID_NET, 1, &tx_vr, ©, |
6676 | + len); |
6677 | + |
6678 | + err = mic_virtio_copy(mic, |
6679 | + mic->mic_net.virtio_net_fd, &tx_vr, |
6680 | + ©); |
6681 | + if (err < 0) { |
6682 | + mpsslog("%s %s %d mic_virtio_copy %s\n", |
6683 | + mic->name, __func__, __LINE__, |
6684 | + strerror(errno)); |
6685 | + } |
6686 | + if (!err) |
6687 | + verify_out_len(mic, ©); |
6688 | +#ifdef DEBUG |
6689 | + disp_iovec(mic, copy, __func__, __LINE__); |
6690 | + mpsslog("%s %s %d wrote to net 0x%lx\n", |
6691 | + mic->name, __func__, __LINE__, |
6692 | + sum_iovec_len(©)); |
6693 | +#endif |
6694 | + /* Reinitialize IOV for next run */ |
6695 | + iov0[1].iov_len = MAX_NET_PKT_SIZE; |
6696 | + } else if (len < 0) { |
6697 | + disp_iovec(mic, ©, __func__, __LINE__); |
6698 | + mpsslog("%s %s %d read failed %s ", mic->name, |
6699 | + __func__, __LINE__, strerror(errno)); |
6700 | + mpsslog("cnt %d sum %zd\n", |
6701 | + copy.iovcnt, sum_iovec_len(©)); |
6702 | + } |
6703 | + } |
6704 | + |
6705 | + /* |
6706 | + * Check if there is data to be read from virtio net and |
6707 | + * write to TUN if there is. |
6708 | + */ |
6709 | + if (net_poll[NET_FD_VIRTIO_NET].revents & POLLIN) { |
6710 | + while (rx_vr.info->avail_idx != |
6711 | + le16toh(rx_vr.vr.avail->idx)) { |
6712 | + copy.iov = iov1; |
6713 | + txrx_prepare(VIRTIO_ID_NET, 0, &rx_vr, ©, |
6714 | + MAX_NET_PKT_SIZE |
6715 | + + sizeof(struct virtio_net_hdr)); |
6716 | + |
6717 | + err = mic_virtio_copy(mic, |
6718 | + mic->mic_net.virtio_net_fd, &rx_vr, |
6719 | + ©); |
6720 | + if (!err) { |
6721 | +#ifdef DEBUG |
6722 | + struct virtio_net_hdr *hdr |
6723 | + = (struct virtio_net_hdr *) |
6724 | + vnet_hdr[1]; |
6725 | + |
6726 | + mpsslog("%s %s %d hdr->flags 0x%x, ", |
6727 | + mic->name, __func__, __LINE__, |
6728 | + hdr->flags); |
6729 | + mpsslog("out_len %d gso_type 0x%x\n", |
6730 | + copy.out_len, |
6731 | + hdr->gso_type); |
6732 | +#endif |
6733 | + /* Set the correct output iov_len */ |
6734 | + iov1[1].iov_len = copy.out_len - |
6735 | + sizeof(struct virtio_net_hdr); |
6736 | + verify_out_len(mic, ©); |
6737 | +#ifdef DEBUG |
6738 | + disp_iovec(mic, copy, __func__, |
6739 | + __LINE__); |
6740 | + mpsslog("%s %s %d ", |
6741 | + mic->name, __func__, __LINE__); |
6742 | + mpsslog("read from net 0x%lx\n", |
6743 | + sum_iovec_len(copy)); |
6744 | +#endif |
6745 | + len = writev(net_poll[NET_FD_TUN].fd, |
6746 | + copy.iov, copy.iovcnt); |
6747 | + if (len != sum_iovec_len(©)) { |
6748 | + mpsslog("Tun write failed %s ", |
6749 | + strerror(errno)); |
6750 | + mpsslog("len 0x%zx ", len); |
6751 | + mpsslog("read_len 0x%zx\n", |
6752 | + sum_iovec_len(©)); |
6753 | + } else { |
6754 | +#ifdef DEBUG |
6755 | + disp_iovec(mic, ©, __func__, |
6756 | + __LINE__); |
6757 | + mpsslog("%s %s %d ", |
6758 | + mic->name, __func__, |
6759 | + __LINE__); |
6760 | + mpsslog("wrote to tap 0x%lx\n", |
6761 | + len); |
6762 | +#endif |
6763 | + } |
6764 | + } else { |
6765 | + mpsslog("%s %s %d mic_virtio_copy %s\n", |
6766 | + mic->name, __func__, __LINE__, |
6767 | + strerror(errno)); |
6768 | + break; |
6769 | + } |
6770 | + } |
6771 | + } |
6772 | + if (net_poll[NET_FD_VIRTIO_NET].revents & POLLERR) |
6773 | + mpsslog("%s: %s: POLLERR\n", __func__, mic->name); |
6774 | + } |
6775 | +done: |
6776 | + pthread_exit(NULL); |
6777 | +} |
6778 | + |
6779 | +/* virtio_console */ |
6780 | +#define VIRTIO_CONSOLE_FD 0 |
6781 | +#define MONITOR_FD (VIRTIO_CONSOLE_FD + 1) |
6782 | +#define MAX_CONSOLE_FD (MONITOR_FD + 1) /* must be the last one + 1 */ |
6783 | +#define MAX_BUFFER_SIZE PAGE_SIZE |
6784 | + |
6785 | +static void * |
6786 | +virtio_console(void *arg) |
6787 | +{ |
6788 | + static __u8 vcons_buf[2][PAGE_SIZE]; |
6789 | + struct iovec vcons_iov[2] = { |
6790 | + { .iov_base = vcons_buf[0], .iov_len = sizeof(vcons_buf[0]) }, |
6791 | + { .iov_base = vcons_buf[1], .iov_len = sizeof(vcons_buf[1]) }, |
6792 | + }; |
6793 | + struct iovec *iov0 = &vcons_iov[0], *iov1 = &vcons_iov[1]; |
6794 | + struct mic_info *mic = (struct mic_info *)arg; |
6795 | + int err; |
6796 | + struct pollfd console_poll[MAX_CONSOLE_FD]; |
6797 | + int pty_fd; |
6798 | + char *pts_name; |
6799 | + ssize_t len; |
6800 | + struct mic_vring tx_vr, rx_vr; |
6801 | + struct mic_copy_desc copy; |
6802 | + struct mic_device_desc *desc; |
6803 | + |
6804 | + pty_fd = posix_openpt(O_RDWR); |
6805 | + if (pty_fd < 0) { |
6806 | + mpsslog("can't open a pseudoterminal master device: %s\n", |
6807 | + strerror(errno)); |
6808 | + goto _return; |
6809 | + } |
6810 | + pts_name = ptsname(pty_fd); |
6811 | + if (pts_name == NULL) { |
6812 | + mpsslog("can't get pts name\n"); |
6813 | + goto _close_pty; |
6814 | + } |
6815 | + printf("%s console message goes to %s\n", mic->name, pts_name); |
6816 | + mpsslog("%s console message goes to %s\n", mic->name, pts_name); |
6817 | + err = grantpt(pty_fd); |
6818 | + if (err < 0) { |
6819 | + mpsslog("can't grant access: %s %s\n", |
6820 | + pts_name, strerror(errno)); |
6821 | + goto _close_pty; |
6822 | + } |
6823 | + err = unlockpt(pty_fd); |
6824 | + if (err < 0) { |
6825 | + mpsslog("can't unlock a pseudoterminal: %s %s\n", |
6826 | + pts_name, strerror(errno)); |
6827 | + goto _close_pty; |
6828 | + } |
6829 | + console_poll[MONITOR_FD].fd = pty_fd; |
6830 | + console_poll[MONITOR_FD].events = POLLIN; |
6831 | + |
6832 | + console_poll[VIRTIO_CONSOLE_FD].fd = mic->mic_console.virtio_console_fd; |
6833 | + console_poll[VIRTIO_CONSOLE_FD].events = POLLIN; |
6834 | + |
6835 | + if (MAP_FAILED == init_vr(mic, mic->mic_console.virtio_console_fd, |
6836 | + VIRTIO_ID_CONSOLE, &tx_vr, &rx_vr, |
6837 | + virtcons_dev_page.dd.num_vq)) { |
6838 | + mpsslog("%s init_vr failed %s\n", |
6839 | + mic->name, strerror(errno)); |
6840 | + goto _close_pty; |
6841 | + } |
6842 | + |
6843 | + copy.iovcnt = 1; |
6844 | + desc = get_device_desc(mic, VIRTIO_ID_CONSOLE); |
6845 | + |
6846 | + for (;;) { |
6847 | + console_poll[MONITOR_FD].revents = 0; |
6848 | + console_poll[VIRTIO_CONSOLE_FD].revents = 0; |
6849 | + err = poll(console_poll, MAX_CONSOLE_FD, -1); |
6850 | + if (err < 0) { |
6851 | + mpsslog("%s %d: poll failed: %s\n", __func__, __LINE__, |
6852 | + strerror(errno)); |
6853 | + continue; |
6854 | + } |
6855 | + if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) { |
6856 | + err = wait_for_card_driver(mic, |
6857 | + mic->mic_console.virtio_console_fd, |
6858 | + VIRTIO_ID_CONSOLE); |
6859 | + if (err) { |
6860 | + mpsslog("%s %s %d Exiting...\n", |
6861 | + mic->name, __func__, __LINE__); |
6862 | + break; |
6863 | + } |
6864 | + } |
6865 | + |
6866 | + if (console_poll[MONITOR_FD].revents & POLLIN) { |
6867 | + copy.iov = iov0; |
6868 | + len = readv(pty_fd, copy.iov, copy.iovcnt); |
6869 | + if (len > 0) { |
6870 | +#ifdef DEBUG |
6871 | + disp_iovec(mic, copy, __func__, __LINE__); |
6872 | + mpsslog("%s %s %d read from tap 0x%lx\n", |
6873 | + mic->name, __func__, __LINE__, |
6874 | + len); |
6875 | +#endif |
6876 | + spin_for_descriptors(mic, &tx_vr); |
6877 | + txrx_prepare(VIRTIO_ID_CONSOLE, 1, &tx_vr, |
6878 | + ©, len); |
6879 | + |
6880 | + err = mic_virtio_copy(mic, |
6881 | + mic->mic_console.virtio_console_fd, |
6882 | + &tx_vr, ©); |
6883 | + if (err < 0) { |
6884 | + mpsslog("%s %s %d mic_virtio_copy %s\n", |
6885 | + mic->name, __func__, __LINE__, |
6886 | + strerror(errno)); |
6887 | + } |
6888 | + if (!err) |
6889 | + verify_out_len(mic, ©); |
6890 | +#ifdef DEBUG |
6891 | + disp_iovec(mic, copy, __func__, __LINE__); |
6892 | + mpsslog("%s %s %d wrote to net 0x%lx\n", |
6893 | + mic->name, __func__, __LINE__, |
6894 | + sum_iovec_len(copy)); |
6895 | +#endif |
6896 | + /* Reinitialize IOV for next run */ |
6897 | + iov0->iov_len = PAGE_SIZE; |
6898 | + } else if (len < 0) { |
6899 | + disp_iovec(mic, ©, __func__, __LINE__); |
6900 | + mpsslog("%s %s %d read failed %s ", |
6901 | + mic->name, __func__, __LINE__, |
6902 | + strerror(errno)); |
6903 | + mpsslog("cnt %d sum %zd\n", |
6904 | + copy.iovcnt, sum_iovec_len(©)); |
6905 | + } |
6906 | + } |
6907 | + |
6908 | + if (console_poll[VIRTIO_CONSOLE_FD].revents & POLLIN) { |
6909 | + while (rx_vr.info->avail_idx != |
6910 | + le16toh(rx_vr.vr.avail->idx)) { |
6911 | + copy.iov = iov1; |
6912 | + txrx_prepare(VIRTIO_ID_CONSOLE, 0, &rx_vr, |
6913 | + ©, PAGE_SIZE); |
6914 | + |
6915 | + err = mic_virtio_copy(mic, |
6916 | + mic->mic_console.virtio_console_fd, |
6917 | + &rx_vr, ©); |
6918 | + if (!err) { |
6919 | + /* Set the correct output iov_len */ |
6920 | + iov1->iov_len = copy.out_len; |
6921 | + verify_out_len(mic, ©); |
6922 | +#ifdef DEBUG |
6923 | + disp_iovec(mic, copy, __func__, |
6924 | + __LINE__); |
6925 | + mpsslog("%s %s %d ", |
6926 | + mic->name, __func__, __LINE__); |
6927 | + mpsslog("read from net 0x%lx\n", |
6928 | + sum_iovec_len(copy)); |
6929 | +#endif |
6930 | + len = writev(pty_fd, |
6931 | + copy.iov, copy.iovcnt); |
6932 | + if (len != sum_iovec_len(©)) { |
6933 | + mpsslog("Tun write failed %s ", |
6934 | + strerror(errno)); |
6935 | + mpsslog("len 0x%zx ", len); |
6936 | + mpsslog("read_len 0x%zx\n", |
6937 | + sum_iovec_len(©)); |
6938 | + } else { |
6939 | +#ifdef DEBUG |
6940 | + disp_iovec(mic, copy, __func__, |
6941 | + __LINE__); |
6942 | + mpsslog("%s %s %d ", |
6943 | + mic->name, __func__, |
6944 | + __LINE__); |
6945 | + mpsslog("wrote to tap 0x%lx\n", |
6946 | + len); |
6947 | +#endif |
6948 | + } |
6949 | + } else { |
6950 | + mpsslog("%s %s %d mic_virtio_copy %s\n", |
6951 | + mic->name, __func__, __LINE__, |
6952 | + strerror(errno)); |
6953 | + break; |
6954 | + } |
6955 | + } |
6956 | + } |
6957 | + if (console_poll[NET_FD_VIRTIO_NET].revents & POLLERR) |
6958 | + mpsslog("%s: %s: POLLERR\n", __func__, mic->name); |
6959 | + } |
6960 | +_close_pty: |
6961 | + close(pty_fd); |
6962 | +_return: |
6963 | + pthread_exit(NULL); |
6964 | +} |
6965 | + |
6966 | +static void |
6967 | +add_virtio_device(struct mic_info *mic, struct mic_device_desc *dd) |
6968 | +{ |
6969 | + char path[PATH_MAX]; |
6970 | + int fd, err; |
6971 | + |
6972 | + snprintf(path, PATH_MAX, "/dev/mic%d", mic->id); |
6973 | + fd = open(path, O_RDWR); |
6974 | + if (fd < 0) { |
6975 | + mpsslog("Could not open %s %s\n", path, strerror(errno)); |
6976 | + return; |
6977 | + } |
6978 | + |
6979 | + err = ioctl(fd, MIC_VIRTIO_ADD_DEVICE, dd); |
6980 | + if (err < 0) { |
6981 | + mpsslog("Could not add %d %s\n", dd->type, strerror(errno)); |
6982 | + close(fd); |
6983 | + return; |
6984 | + } |
6985 | + switch (dd->type) { |
6986 | + case VIRTIO_ID_NET: |
6987 | + mic->mic_net.virtio_net_fd = fd; |
6988 | + mpsslog("Added VIRTIO_ID_NET for %s\n", mic->name); |
6989 | + break; |
6990 | + case VIRTIO_ID_CONSOLE: |
6991 | + mic->mic_console.virtio_console_fd = fd; |
6992 | + mpsslog("Added VIRTIO_ID_CONSOLE for %s\n", mic->name); |
6993 | + break; |
6994 | + case VIRTIO_ID_BLOCK: |
6995 | + mic->mic_virtblk.virtio_block_fd = fd; |
6996 | + mpsslog("Added VIRTIO_ID_BLOCK for %s\n", mic->name); |
6997 | + break; |
6998 | + } |
6999 | +} |
7000 | + |
7001 | +static bool |
7002 | +set_backend_file(struct mic_info *mic) |
7003 | +{ |
7004 | + FILE *config; |
7005 | + char buff[PATH_MAX], *line, *evv, *p; |
7006 | + |
7007 | + snprintf(buff, PATH_MAX, "%s/mpssd%03d.conf", mic_config_dir, mic->id); |
7008 | + config = fopen(buff, "r"); |
7009 | + if (config == NULL) |
7010 | + return false; |
7011 | + do { /* look for "virtblk_backend=XXXX" */ |
7012 | + line = fgets(buff, PATH_MAX, config); |
7013 | + if (line == NULL) |
7014 | + break; |
7015 | + if (*line == '#') |
7016 | + continue; |
7017 | + p = strchr(line, '\n'); |
7018 | + if (p) |
7019 | + *p = '\0'; |
7020 | + } while (strncmp(line, virtblk_backend, strlen(virtblk_backend)) != 0); |
7021 | + fclose(config); |
7022 | + if (line == NULL) |
7023 | + return false; |
7024 | + evv = strchr(line, '='); |
7025 | + if (evv == NULL) |
7026 | + return false; |
7027 | + mic->mic_virtblk.backend_file = malloc(strlen(evv) + 1); |
7028 | + if (mic->mic_virtblk.backend_file == NULL) { |
7029 | + mpsslog("%s %d can't allocate memory\n", mic->name, mic->id); |
7030 | + return false; |
7031 | + } |
7032 | + strcpy(mic->mic_virtblk.backend_file, evv + 1); |
7033 | + return true; |
7034 | +} |
7035 | + |
7036 | +#define SECTOR_SIZE 512 |
7037 | +static bool |
7038 | +set_backend_size(struct mic_info *mic) |
7039 | +{ |
7040 | + mic->mic_virtblk.backend_size = lseek(mic->mic_virtblk.backend, 0, |
7041 | + SEEK_END); |
7042 | + if (mic->mic_virtblk.backend_size < 0) { |
7043 | + mpsslog("%s: can't seek: %s\n", |
7044 | + mic->name, mic->mic_virtblk.backend_file); |
7045 | + return false; |
7046 | + } |
7047 | + virtblk_dev_page.blk_config.capacity = |
7048 | + mic->mic_virtblk.backend_size / SECTOR_SIZE; |
7049 | + if ((mic->mic_virtblk.backend_size % SECTOR_SIZE) != 0) |
7050 | + virtblk_dev_page.blk_config.capacity++; |
7051 | + |
7052 | + virtblk_dev_page.blk_config.capacity = |
7053 | + htole64(virtblk_dev_page.blk_config.capacity); |
7054 | + |
7055 | + return true; |
7056 | +} |
7057 | + |
7058 | +static bool |
7059 | +open_backend(struct mic_info *mic) |
7060 | +{ |
7061 | + if (!set_backend_file(mic)) |
7062 | + goto _error_exit; |
7063 | + mic->mic_virtblk.backend = open(mic->mic_virtblk.backend_file, O_RDWR); |
7064 | + if (mic->mic_virtblk.backend < 0) { |
7065 | + mpsslog("%s: can't open: %s\n", mic->name, |
7066 | + mic->mic_virtblk.backend_file); |
7067 | + goto _error_free; |
7068 | + } |
7069 | + if (!set_backend_size(mic)) |
7070 | + goto _error_close; |
7071 | + mic->mic_virtblk.backend_addr = mmap(NULL, |
7072 | + mic->mic_virtblk.backend_size, |
7073 | + PROT_READ|PROT_WRITE, MAP_SHARED, |
7074 | + mic->mic_virtblk.backend, 0L); |
7075 | + if (mic->mic_virtblk.backend_addr == MAP_FAILED) { |
7076 | + mpsslog("%s: can't map: %s %s\n", |
7077 | + mic->name, mic->mic_virtblk.backend_file, |
7078 | + strerror(errno)); |
7079 | + goto _error_close; |
7080 | + } |
7081 | + return true; |
7082 | + |
7083 | + _error_close: |
7084 | + close(mic->mic_virtblk.backend); |
7085 | + _error_free: |
7086 | + free(mic->mic_virtblk.backend_file); |
7087 | + _error_exit: |
7088 | + return false; |
7089 | +} |
7090 | + |
7091 | +static void |
7092 | +close_backend(struct mic_info *mic) |
7093 | +{ |
7094 | + munmap(mic->mic_virtblk.backend_addr, mic->mic_virtblk.backend_size); |
7095 | + close(mic->mic_virtblk.backend); |
7096 | + free(mic->mic_virtblk.backend_file); |
7097 | +} |
7098 | + |
7099 | +static bool |
7100 | +start_virtblk(struct mic_info *mic, struct mic_vring *vring) |
7101 | +{ |
7102 | + if (((unsigned long)&virtblk_dev_page.blk_config % 8) != 0) { |
7103 | + mpsslog("%s: blk_config is not 8 byte aligned.\n", |
7104 | + mic->name); |
7105 | + return false; |
7106 | + } |
7107 | + add_virtio_device(mic, &virtblk_dev_page.dd); |
7108 | + if (MAP_FAILED == init_vr(mic, mic->mic_virtblk.virtio_block_fd, |
7109 | + VIRTIO_ID_BLOCK, vring, NULL, |
7110 | + virtblk_dev_page.dd.num_vq)) { |
7111 | + mpsslog("%s init_vr failed %s\n", |
7112 | + mic->name, strerror(errno)); |
7113 | + return false; |
7114 | + } |
7115 | + return true; |
7116 | +} |
7117 | + |
7118 | +static void |
7119 | +stop_virtblk(struct mic_info *mic) |
7120 | +{ |
7121 | + int vr_size, ret; |
7122 | + |
7123 | + vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES, |
7124 | + MIC_VIRTIO_RING_ALIGN) + |
7125 | + sizeof(struct _mic_vring_info)); |
7126 | + ret = munmap(mic->mic_virtblk.block_dp, |
7127 | + MIC_DEVICE_PAGE_END + vr_size * virtblk_dev_page.dd.num_vq); |
7128 | + if (ret < 0) |
7129 | + mpsslog("%s munmap errno %d\n", mic->name, errno); |
7130 | + close(mic->mic_virtblk.virtio_block_fd); |
7131 | +} |
7132 | + |
7133 | +static __u8 |
7134 | +header_error_check(struct vring_desc *desc) |
7135 | +{ |
7136 | + if (le32toh(desc->len) != sizeof(struct virtio_blk_outhdr)) { |
7137 | + mpsslog("%s() %d: length is not sizeof(virtio_blk_outhd)\n", |
7138 | + __func__, __LINE__); |
7139 | + return -EIO; |
7140 | + } |
7141 | + if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT)) { |
7142 | + mpsslog("%s() %d: alone\n", |
7143 | + __func__, __LINE__); |
7144 | + return -EIO; |
7145 | + } |
7146 | + if (le16toh(desc->flags) & VRING_DESC_F_WRITE) { |
7147 | + mpsslog("%s() %d: not read\n", |
7148 | + __func__, __LINE__); |
7149 | + return -EIO; |
7150 | + } |
7151 | + return 0; |
7152 | +} |
7153 | + |
7154 | +static int |
7155 | +read_header(int fd, struct virtio_blk_outhdr *hdr, __u32 desc_idx) |
7156 | +{ |
7157 | + struct iovec iovec; |
7158 | + struct mic_copy_desc copy; |
7159 | + |
7160 | + iovec.iov_len = sizeof(*hdr); |
7161 | + iovec.iov_base = hdr; |
7162 | + copy.iov = &iovec; |
7163 | + copy.iovcnt = 1; |
7164 | + copy.vr_idx = 0; /* only one vring on virtio_block */ |
7165 | + copy.update_used = false; /* do not update used index */ |
7166 | + return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
7167 | +} |
7168 | + |
7169 | +static int |
7170 | +transfer_blocks(int fd, struct iovec *iovec, __u32 iovcnt) |
7171 | +{ |
7172 | + struct mic_copy_desc copy; |
7173 | + |
7174 | + copy.iov = iovec; |
7175 | + copy.iovcnt = iovcnt; |
7176 | + copy.vr_idx = 0; /* only one vring on virtio_block */ |
7177 | + copy.update_used = false; /* do not update used index */ |
7178 | + return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
7179 | +} |
7180 | + |
7181 | +static __u8 |
7182 | +status_error_check(struct vring_desc *desc) |
7183 | +{ |
7184 | + if (le32toh(desc->len) != sizeof(__u8)) { |
7185 | + mpsslog("%s() %d: length is not sizeof(status)\n", |
7186 | + __func__, __LINE__); |
7187 | + return -EIO; |
7188 | + } |
7189 | + return 0; |
7190 | +} |
7191 | + |
7192 | +static int |
7193 | +write_status(int fd, __u8 *status) |
7194 | +{ |
7195 | + struct iovec iovec; |
7196 | + struct mic_copy_desc copy; |
7197 | + |
7198 | + iovec.iov_base = status; |
7199 | + iovec.iov_len = sizeof(*status); |
7200 | + copy.iov = &iovec; |
7201 | + copy.iovcnt = 1; |
7202 | + copy.vr_idx = 0; /* only one vring on virtio_block */ |
7203 | + copy.update_used = true; /* Update used index */ |
7204 | + return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
7205 | +} |
7206 | + |
7207 | +#ifndef VIRTIO_BLK_T_GET_ID |
7208 | +#define VIRTIO_BLK_T_GET_ID 8 |
7209 | +#endif |
7210 | + |
7211 | +static void * |
7212 | +virtio_block(void *arg) |
7213 | +{ |
7214 | + struct mic_info *mic = (struct mic_info *)arg; |
7215 | + int ret; |
7216 | + struct pollfd block_poll; |
7217 | + struct mic_vring vring; |
7218 | + __u16 avail_idx; |
7219 | + __u32 desc_idx; |
7220 | + struct vring_desc *desc; |
7221 | + struct iovec *iovec, *piov; |
7222 | + __u8 status; |
7223 | + __u32 buffer_desc_idx; |
7224 | + struct virtio_blk_outhdr hdr; |
7225 | + void *fos; |
7226 | + |
7227 | + for (;;) { /* forever */ |
7228 | + if (!open_backend(mic)) { /* No virtblk */ |
7229 | + for (mic->mic_virtblk.signaled = 0; |
7230 | + !mic->mic_virtblk.signaled;) |
7231 | + sleep(1); |
7232 | + continue; |
7233 | + } |
7234 | + |
7235 | + /* backend file is specified. */ |
7236 | + if (!start_virtblk(mic, &vring)) |
7237 | + goto _close_backend; |
7238 | + iovec = malloc(sizeof(*iovec) * |
7239 | + le32toh(virtblk_dev_page.blk_config.seg_max)); |
7240 | + if (!iovec) { |
7241 | + mpsslog("%s: can't alloc iovec: %s\n", |
7242 | + mic->name, strerror(ENOMEM)); |
7243 | + goto _stop_virtblk; |
7244 | + } |
7245 | + |
7246 | + block_poll.fd = mic->mic_virtblk.virtio_block_fd; |
7247 | + block_poll.events = POLLIN; |
7248 | + for (mic->mic_virtblk.signaled = 0; |
7249 | + !mic->mic_virtblk.signaled;) { |
7250 | + block_poll.revents = 0; |
7251 | + /* timeout in 1 sec to see signaled */ |
7252 | + ret = poll(&block_poll, 1, 1000); |
7253 | + if (ret < 0) { |
7254 | + mpsslog("%s %d: poll failed: %s\n", |
7255 | + __func__, __LINE__, |
7256 | + strerror(errno)); |
7257 | + continue; |
7258 | + } |
7259 | + |
7260 | + if (!(block_poll.revents & POLLIN)) { |
7261 | +#ifdef DEBUG |
7262 | + mpsslog("%s %d: block_poll.revents=0x%x\n", |
7263 | + __func__, __LINE__, block_poll.revents); |
7264 | +#endif |
7265 | + continue; |
7266 | + } |
7267 | + |
7268 | + /* POLLIN */ |
7269 | + while (vring.info->avail_idx != |
7270 | + le16toh(vring.vr.avail->idx)) { |
7271 | + /* read header element */ |
7272 | + avail_idx = |
7273 | + vring.info->avail_idx & |
7274 | + (vring.vr.num - 1); |
7275 | + desc_idx = le16toh( |
7276 | + vring.vr.avail->ring[avail_idx]); |
7277 | + desc = &vring.vr.desc[desc_idx]; |
7278 | +#ifdef DEBUG |
7279 | + mpsslog("%s() %d: avail_idx=%d ", |
7280 | + __func__, __LINE__, |
7281 | + vring.info->avail_idx); |
7282 | + mpsslog("vring.vr.num=%d desc=%p\n", |
7283 | + vring.vr.num, desc); |
7284 | +#endif |
7285 | + status = header_error_check(desc); |
7286 | + ret = read_header( |
7287 | + mic->mic_virtblk.virtio_block_fd, |
7288 | + &hdr, desc_idx); |
7289 | + if (ret < 0) { |
7290 | + mpsslog("%s() %d %s: ret=%d %s\n", |
7291 | + __func__, __LINE__, |
7292 | + mic->name, ret, |
7293 | + strerror(errno)); |
7294 | + break; |
7295 | + } |
7296 | + /* buffer element */ |
7297 | + piov = iovec; |
7298 | + status = 0; |
7299 | + fos = mic->mic_virtblk.backend_addr + |
7300 | + (hdr.sector * SECTOR_SIZE); |
7301 | + buffer_desc_idx = next_desc(desc); |
7302 | + desc_idx = buffer_desc_idx; |
7303 | + for (desc = &vring.vr.desc[buffer_desc_idx]; |
7304 | + desc->flags & VRING_DESC_F_NEXT; |
7305 | + desc_idx = next_desc(desc), |
7306 | + desc = &vring.vr.desc[desc_idx]) { |
7307 | + piov->iov_len = desc->len; |
7308 | + piov->iov_base = fos; |
7309 | + piov++; |
7310 | + fos += desc->len; |
7311 | + } |
7312 | + /* Returning NULLs for VIRTIO_BLK_T_GET_ID. */ |
7313 | + if (hdr.type & ~(VIRTIO_BLK_T_OUT | |
7314 | + VIRTIO_BLK_T_GET_ID)) { |
7315 | + /* |
7316 | + VIRTIO_BLK_T_IN - does not do |
7317 | + anything. Probably for documenting. |
7318 | + VIRTIO_BLK_T_SCSI_CMD - for |
7319 | + virtio_scsi. |
7320 | + VIRTIO_BLK_T_FLUSH - turned off in |
7321 | + config space. |
7322 | + VIRTIO_BLK_T_BARRIER - defined but not |
7323 | + used in anywhere. |
7324 | + */ |
7325 | + mpsslog("%s() %d: type %x ", |
7326 | + __func__, __LINE__, |
7327 | + hdr.type); |
7328 | + mpsslog("is not supported\n"); |
7329 | + status = -ENOTSUP; |
7330 | + |
7331 | + } else { |
7332 | + ret = transfer_blocks( |
7333 | + mic->mic_virtblk.virtio_block_fd, |
7334 | + iovec, |
7335 | + piov - iovec); |
7336 | + if (ret < 0 && |
7337 | + status != 0) |
7338 | + status = ret; |
7339 | + } |
7340 | + /* write status and update used pointer */ |
7341 | + if (status != 0) |
7342 | + status = status_error_check(desc); |
7343 | + ret = write_status( |
7344 | + mic->mic_virtblk.virtio_block_fd, |
7345 | + &status); |
7346 | +#ifdef DEBUG |
7347 | + mpsslog("%s() %d: write status=%d on desc=%p\n", |
7348 | + __func__, __LINE__, |
7349 | + status, desc); |
7350 | +#endif |
7351 | + } |
7352 | + } |
7353 | + free(iovec); |
7354 | +_stop_virtblk: |
7355 | + stop_virtblk(mic); |
7356 | +_close_backend: |
7357 | + close_backend(mic); |
7358 | + } /* forever */ |
7359 | + |
7360 | + pthread_exit(NULL); |
7361 | +} |
7362 | + |
7363 | +static void |
7364 | +reset(struct mic_info *mic) |
7365 | +{ |
7366 | +#define RESET_TIMEOUT 120 |
7367 | + int i = RESET_TIMEOUT; |
7368 | + setsysfs(mic->name, "state", "reset"); |
7369 | + while (i) { |
7370 | + char *state; |
7371 | + state = readsysfs(mic->name, "state"); |
7372 | + if (!state) |
7373 | + goto retry; |
7374 | + mpsslog("%s: %s %d state %s\n", |
7375 | + mic->name, __func__, __LINE__, state); |
7376 | + |
7377 | + if (!strcmp(state, "ready")) { |
7378 | + free(state); |
7379 | + break; |
7380 | + } |
7381 | + free(state); |
7382 | +retry: |
7383 | + sleep(1); |
7384 | + i--; |
7385 | + } |
7386 | +} |
7387 | + |
7388 | +static int |
7389 | +get_mic_shutdown_status(struct mic_info *mic, char *shutdown_status) |
7390 | +{ |
7391 | + if (!strcmp(shutdown_status, "nop")) |
7392 | + return MIC_NOP; |
7393 | + if (!strcmp(shutdown_status, "crashed")) |
7394 | + return MIC_CRASHED; |
7395 | + if (!strcmp(shutdown_status, "halted")) |
7396 | + return MIC_HALTED; |
7397 | + if (!strcmp(shutdown_status, "poweroff")) |
7398 | + return MIC_POWER_OFF; |
7399 | + if (!strcmp(shutdown_status, "restart")) |
7400 | + return MIC_RESTART; |
7401 | + mpsslog("%s: BUG invalid status %s\n", mic->name, shutdown_status); |
7402 | + /* Invalid state */ |
7403 | + assert(0); |
7404 | +}; |
7405 | + |
7406 | +static int get_mic_state(struct mic_info *mic) |
7407 | +{ |
7408 | + char *state = NULL; |
7409 | + enum mic_states mic_state; |
7410 | + |
7411 | + while (!state) { |
7412 | + state = readsysfs(mic->name, "state"); |
7413 | + sleep(1); |
7414 | + } |
7415 | + mpsslog("%s: %s %d state %s\n", |
7416 | + mic->name, __func__, __LINE__, state); |
7417 | + |
7418 | + if (!strcmp(state, "ready")) { |
7419 | + mic_state = MIC_READY; |
7420 | + } else if (!strcmp(state, "booting")) { |
7421 | + mic_state = MIC_BOOTING; |
7422 | + } else if (!strcmp(state, "online")) { |
7423 | + mic_state = MIC_ONLINE; |
7424 | + } else if (!strcmp(state, "shutting_down")) { |
7425 | + mic_state = MIC_SHUTTING_DOWN; |
7426 | + } else if (!strcmp(state, "reset_failed")) { |
7427 | + mic_state = MIC_RESET_FAILED; |
7428 | + } else if (!strcmp(state, "resetting")) { |
7429 | + mic_state = MIC_RESETTING; |
7430 | + } else { |
7431 | + mpsslog("%s: BUG invalid state %s\n", mic->name, state); |
7432 | + assert(0); |
7433 | + } |
7434 | + |
7435 | + free(state); |
7436 | + return mic_state; |
7437 | +}; |
7438 | + |
7439 | +static void mic_handle_shutdown(struct mic_info *mic) |
7440 | +{ |
7441 | +#define SHUTDOWN_TIMEOUT 60 |
7442 | + int i = SHUTDOWN_TIMEOUT; |
7443 | + char *shutdown_status; |
7444 | + while (i) { |
7445 | + shutdown_status = readsysfs(mic->name, "shutdown_status"); |
7446 | + if (!shutdown_status) { |
7447 | + sleep(1); |
7448 | + continue; |
7449 | + } |
7450 | + mpsslog("%s: %s %d shutdown_status %s\n", |
7451 | + mic->name, __func__, __LINE__, shutdown_status); |
7452 | + switch (get_mic_shutdown_status(mic, shutdown_status)) { |
7453 | + case MIC_RESTART: |
7454 | + mic->restart = 1; |
7455 | + case MIC_HALTED: |
7456 | + case MIC_POWER_OFF: |
7457 | + case MIC_CRASHED: |
7458 | + free(shutdown_status); |
7459 | + goto reset; |
7460 | + default: |
7461 | + break; |
7462 | + } |
7463 | + free(shutdown_status); |
7464 | + sleep(1); |
7465 | + i--; |
7466 | + } |
7467 | +reset: |
7468 | + if (!i) |
7469 | + mpsslog("%s: %s %d timing out waiting for shutdown_status %s\n", |
7470 | + mic->name, __func__, __LINE__, shutdown_status); |
7471 | + reset(mic); |
7472 | +} |
7473 | + |
7474 | +static int open_state_fd(struct mic_info *mic) |
7475 | +{ |
7476 | + char pathname[PATH_MAX]; |
7477 | + int fd; |
7478 | + |
7479 | + snprintf(pathname, PATH_MAX - 1, "%s/%s/%s", |
7480 | + MICSYSFSDIR, mic->name, "state"); |
7481 | + |
7482 | + fd = open(pathname, O_RDONLY); |
7483 | + if (fd < 0) |
7484 | + mpsslog("%s: opening file %s failed %s\n", |
7485 | + mic->name, pathname, strerror(errno)); |
7486 | + return fd; |
7487 | +} |
7488 | + |
7489 | +static int block_till_state_change(int fd, struct mic_info *mic) |
7490 | +{ |
7491 | + struct pollfd ufds[1]; |
7492 | + char value[PAGE_SIZE]; |
7493 | + int ret; |
7494 | + |
7495 | + ufds[0].fd = fd; |
7496 | + ufds[0].events = POLLERR | POLLPRI; |
7497 | + ret = poll(ufds, 1, -1); |
7498 | + if (ret < 0) { |
7499 | + mpsslog("%s: %s %d poll failed %s\n", |
7500 | + mic->name, __func__, __LINE__, strerror(errno)); |
7501 | + return ret; |
7502 | + } |
7503 | + |
7504 | + ret = lseek(fd, 0, SEEK_SET); |
7505 | + if (ret < 0) { |
7506 | + mpsslog("%s: %s %d Failed to seek to 0: %s\n", |
7507 | + mic->name, __func__, __LINE__, strerror(errno)); |
7508 | + return ret; |
7509 | + } |
7510 | + |
7511 | + ret = read(fd, value, sizeof(value)); |
7512 | + if (ret < 0) { |
7513 | + mpsslog("%s: %s %d Failed to read sysfs entry: %s\n", |
7514 | + mic->name, __func__, __LINE__, strerror(errno)); |
7515 | + return ret; |
7516 | + } |
7517 | + |
7518 | + return 0; |
7519 | +} |
7520 | + |
7521 | +static void * |
7522 | +mic_config(void *arg) |
7523 | +{ |
7524 | + struct mic_info *mic = (struct mic_info *)arg; |
7525 | + int fd, ret, stat = 0; |
7526 | + |
7527 | + fd = open_state_fd(mic); |
7528 | + if (fd < 0) { |
7529 | + mpsslog("%s: %s %d open state fd failed %s\n", |
7530 | + mic->name, __func__, __LINE__, strerror(errno)); |
7531 | + goto exit; |
7532 | + } |
7533 | + |
7534 | + do { |
7535 | + ret = block_till_state_change(fd, mic); |
7536 | + if (ret < 0) { |
7537 | + mpsslog("%s: %s %d block_till_state_change error %s\n", |
7538 | + mic->name, __func__, __LINE__, strerror(errno)); |
7539 | + goto close_exit; |
7540 | + } |
7541 | + |
7542 | + switch (get_mic_state(mic)) { |
7543 | + case MIC_SHUTTING_DOWN: |
7544 | + mic_handle_shutdown(mic); |
7545 | + break; |
7546 | + case MIC_READY: |
7547 | + case MIC_RESET_FAILED: |
7548 | + ret = kill(mic->pid, SIGTERM); |
7549 | + mpsslog("%s: %s %d kill pid %d ret %d\n", |
7550 | + mic->name, __func__, __LINE__, |
7551 | + mic->pid, ret); |
7552 | + if (!ret) { |
7553 | + ret = waitpid(mic->pid, &stat, |
7554 | + WIFSIGNALED(stat)); |
7555 | + mpsslog("%s: %s %d waitpid ret %d pid %d\n", |
7556 | + mic->name, __func__, __LINE__, |
7557 | + ret, mic->pid); |
7558 | + } |
7559 | + if (mic->boot_on_resume) { |
7560 | + setsysfs(mic->name, "state", "boot"); |
7561 | + mic->boot_on_resume = 0; |
7562 | + } |
7563 | + goto close_exit; |
7564 | + default: |
7565 | + break; |
7566 | + } |
7567 | + } while (1); |
7568 | + |
7569 | +close_exit: |
7570 | + close(fd); |
7571 | +exit: |
7572 | + init_mic(mic); |
7573 | + pthread_exit(NULL); |
7574 | +} |
7575 | + |
7576 | +static void |
7577 | +set_cmdline(struct mic_info *mic) |
7578 | +{ |
7579 | + char buffer[PATH_MAX]; |
7580 | + int len; |
7581 | + |
7582 | + len = snprintf(buffer, PATH_MAX, |
7583 | + "clocksource=tsc highres=off nohz=off "); |
7584 | + len += snprintf(buffer + len, PATH_MAX - len, |
7585 | + "cpufreq_on;corec6_off;pc3_off;pc6_off "); |
7586 | + len += snprintf(buffer + len, PATH_MAX - len, |
7587 | + "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0", |
7588 | + mic->id + 1); |
7589 | + |
7590 | + setsysfs(mic->name, "cmdline", buffer); |
7591 | + mpsslog("%s: Command line: \"%s\"\n", mic->name, buffer); |
7592 | + snprintf(buffer, PATH_MAX, "172.31.%d.1", mic->id + 1); |
7593 | + mpsslog("%s: IPADDR: \"%s\"\n", mic->name, buffer); |
7594 | +} |
7595 | + |
7596 | +static void |
7597 | +set_log_buf_info(struct mic_info *mic) |
7598 | +{ |
7599 | + int fd; |
7600 | + off_t len; |
7601 | + char system_map[] = "/lib/firmware/mic/System.map"; |
7602 | + char *map, *temp, log_buf[17] = {'\0'}; |
7603 | + |
7604 | + fd = open(system_map, O_RDONLY); |
7605 | + if (fd < 0) { |
7606 | + mpsslog("%s: Opening System.map failed: %d\n", |
7607 | + mic->name, errno); |
7608 | + return; |
7609 | + } |
7610 | + len = lseek(fd, 0, SEEK_END); |
7611 | + if (len < 0) { |
7612 | + mpsslog("%s: Reading System.map size failed: %d\n", |
7613 | + mic->name, errno); |
7614 | + close(fd); |
7615 | + return; |
7616 | + } |
7617 | + map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); |
7618 | + if (map == MAP_FAILED) { |
7619 | + mpsslog("%s: mmap of System.map failed: %d\n", |
7620 | + mic->name, errno); |
7621 | + close(fd); |
7622 | + return; |
7623 | + } |
7624 | + temp = strstr(map, "__log_buf"); |
7625 | + if (!temp) { |
7626 | + mpsslog("%s: __log_buf not found: %d\n", mic->name, errno); |
7627 | + munmap(map, len); |
7628 | + close(fd); |
7629 | + return; |
7630 | + } |
7631 | + strncpy(log_buf, temp - 19, 16); |
7632 | + setsysfs(mic->name, "log_buf_addr", log_buf); |
7633 | + mpsslog("%s: log_buf_addr: %s\n", mic->name, log_buf); |
7634 | + temp = strstr(map, "log_buf_len"); |
7635 | + if (!temp) { |
7636 | + mpsslog("%s: log_buf_len not found: %d\n", mic->name, errno); |
7637 | + munmap(map, len); |
7638 | + close(fd); |
7639 | + return; |
7640 | + } |
7641 | + strncpy(log_buf, temp - 19, 16); |
7642 | + setsysfs(mic->name, "log_buf_len", log_buf); |
7643 | + mpsslog("%s: log_buf_len: %s\n", mic->name, log_buf); |
7644 | + munmap(map, len); |
7645 | + close(fd); |
7646 | +} |
7647 | + |
7648 | +static void |
7649 | +change_virtblk_backend(int x, siginfo_t *siginfo, void *p) |
7650 | +{ |
7651 | + struct mic_info *mic; |
7652 | + |
7653 | + for (mic = mic_list.next; mic != NULL; mic = mic->next) |
7654 | + mic->mic_virtblk.signaled = 1/* true */; |
7655 | +} |
7656 | + |
7657 | +static void |
7658 | +set_mic_boot_params(struct mic_info *mic) |
7659 | +{ |
7660 | + set_log_buf_info(mic); |
7661 | + set_cmdline(mic); |
7662 | +} |
7663 | + |
7664 | +static void * |
7665 | +init_mic(void *arg) |
7666 | +{ |
7667 | + struct mic_info *mic = (struct mic_info *)arg; |
7668 | + struct sigaction ignore = { |
7669 | + .sa_flags = 0, |
7670 | + .sa_handler = SIG_IGN |
7671 | + }; |
7672 | + struct sigaction act = { |
7673 | + .sa_flags = SA_SIGINFO, |
7674 | + .sa_sigaction = change_virtblk_backend, |
7675 | + }; |
7676 | + char buffer[PATH_MAX]; |
7677 | + int err, fd; |
7678 | + |
7679 | + /* |
7680 | + * Currently, one virtio block device is supported for each MIC card |
7681 | + * at a time. Any user (or test) can send a SIGUSR1 to the MIC daemon. |
7682 | + * The signal informs the virtio block backend about a change in the |
7683 | + * configuration file which specifies the virtio backend file name on |
7684 | + * the host. Virtio block backend then re-reads the configuration file |
7685 | + * and switches to the new block device. This signalling mechanism may |
7686 | + * not be required once multiple virtio block devices are supported by |
7687 | + * the MIC daemon. |
7688 | + */ |
7689 | + sigaction(SIGUSR1, &ignore, NULL); |
7690 | +retry: |
7691 | + fd = open_state_fd(mic); |
7692 | + if (fd < 0) { |
7693 | + mpsslog("%s: %s %d open state fd failed %s\n", |
7694 | + mic->name, __func__, __LINE__, strerror(errno)); |
7695 | + sleep(2); |
7696 | + goto retry; |
7697 | + } |
7698 | + |
7699 | + if (mic->restart) { |
7700 | + snprintf(buffer, PATH_MAX, "boot"); |
7701 | + setsysfs(mic->name, "state", buffer); |
7702 | + mpsslog("%s restarting mic %d\n", |
7703 | + mic->name, mic->restart); |
7704 | + mic->restart = 0; |
7705 | + } |
7706 | + |
7707 | + while (1) { |
7708 | + while (block_till_state_change(fd, mic)) { |
7709 | + mpsslog("%s: %s %d block_till_state_change error %s\n", |
7710 | + mic->name, __func__, __LINE__, strerror(errno)); |
7711 | + sleep(2); |
7712 | + continue; |
7713 | + } |
7714 | + |
7715 | + if (get_mic_state(mic) == MIC_BOOTING) |
7716 | + break; |
7717 | + } |
7718 | + |
7719 | + mic->pid = fork(); |
7720 | + switch (mic->pid) { |
7721 | + case 0: |
7722 | + add_virtio_device(mic, &virtcons_dev_page.dd); |
7723 | + add_virtio_device(mic, &virtnet_dev_page.dd); |
7724 | + err = pthread_create(&mic->mic_console.console_thread, NULL, |
7725 | + virtio_console, mic); |
7726 | + if (err) |
7727 | + mpsslog("%s virtcons pthread_create failed %s\n", |
7728 | + mic->name, strerror(err)); |
7729 | + err = pthread_create(&mic->mic_net.net_thread, NULL, |
7730 | + virtio_net, mic); |
7731 | + if (err) |
7732 | + mpsslog("%s virtnet pthread_create failed %s\n", |
7733 | + mic->name, strerror(err)); |
7734 | + err = pthread_create(&mic->mic_virtblk.block_thread, NULL, |
7735 | + virtio_block, mic); |
7736 | + if (err) |
7737 | + mpsslog("%s virtblk pthread_create failed %s\n", |
7738 | + mic->name, strerror(err)); |
7739 | + sigemptyset(&act.sa_mask); |
7740 | + err = sigaction(SIGUSR1, &act, NULL); |
7741 | + if (err) |
7742 | + mpsslog("%s sigaction SIGUSR1 failed %s\n", |
7743 | + mic->name, strerror(errno)); |
7744 | + while (1) |
7745 | + sleep(60); |
7746 | + case -1: |
7747 | + mpsslog("fork failed MIC name %s id %d errno %d\n", |
7748 | + mic->name, mic->id, errno); |
7749 | + break; |
7750 | + default: |
7751 | + err = pthread_create(&mic->config_thread, NULL, |
7752 | + mic_config, mic); |
7753 | + if (err) |
7754 | + mpsslog("%s mic_config pthread_create failed %s\n", |
7755 | + mic->name, strerror(err)); |
7756 | + } |
7757 | + |
7758 | + return NULL; |
7759 | +} |
7760 | + |
7761 | +static void |
7762 | +start_daemon(void) |
7763 | +{ |
7764 | + struct mic_info *mic; |
7765 | + int err; |
7766 | + |
7767 | + for (mic = mic_list.next; mic; mic = mic->next) { |
7768 | + set_mic_boot_params(mic); |
7769 | + err = pthread_create(&mic->init_thread, NULL, init_mic, mic); |
7770 | + if (err) |
7771 | + mpsslog("%s init_mic pthread_create failed %s\n", |
7772 | + mic->name, strerror(err)); |
7773 | + } |
7774 | + |
7775 | + while (1) |
7776 | + sleep(60); |
7777 | +} |
7778 | + |
7779 | +static int |
7780 | +init_mic_list(void) |
7781 | +{ |
7782 | + struct mic_info *mic = &mic_list; |
7783 | + struct dirent *file; |
7784 | + DIR *dp; |
7785 | + int cnt = 0; |
7786 | + |
7787 | + dp = opendir(MICSYSFSDIR); |
7788 | + if (!dp) |
7789 | + return 0; |
7790 | + |
7791 | + while ((file = readdir(dp)) != NULL) { |
7792 | + if (!strncmp(file->d_name, "mic", 3)) { |
7793 | + mic->next = calloc(1, sizeof(struct mic_info)); |
7794 | + if (mic->next) { |
7795 | + mic = mic->next; |
7796 | + mic->id = atoi(&file->d_name[3]); |
7797 | + mic->name = malloc(strlen(file->d_name) + 16); |
7798 | + if (mic->name) |
7799 | + strcpy(mic->name, file->d_name); |
7800 | + mpsslog("MIC name %s id %d\n", mic->name, |
7801 | + mic->id); |
7802 | + cnt++; |
7803 | + } |
7804 | + } |
7805 | + } |
7806 | + |
7807 | + closedir(dp); |
7808 | + return cnt; |
7809 | +} |
7810 | + |
7811 | +void |
7812 | +mpsslog(char *format, ...) |
7813 | +{ |
7814 | + va_list args; |
7815 | + char buffer[4096]; |
7816 | + char ts[52], *ts1; |
7817 | + time_t t; |
7818 | + |
7819 | + if (logfp == NULL) |
7820 | + return; |
7821 | + |
7822 | + va_start(args, format); |
7823 | + vsprintf(buffer, format, args); |
7824 | + va_end(args); |
7825 | + |
7826 | + time(&t); |
7827 | + ts1 = ctime_r(&t, ts); |
7828 | + ts1[strlen(ts1) - 1] = '\0'; |
7829 | + fprintf(logfp, "%s: %s", ts1, buffer); |
7830 | + |
7831 | + fflush(logfp); |
7832 | +} |
7833 | + |
7834 | +int |
7835 | +main(int argc, char *argv[]) |
7836 | +{ |
7837 | + int cnt; |
7838 | + pid_t pid; |
7839 | + |
7840 | + myname = argv[0]; |
7841 | + |
7842 | + logfp = fopen(LOGFILE_NAME, "a+"); |
7843 | + if (!logfp) { |
7844 | + fprintf(stderr, "cannot open logfile '%s'\n", LOGFILE_NAME); |
7845 | + exit(1); |
7846 | + } |
7847 | + pid = fork(); |
7848 | + switch (pid) { |
7849 | + case 0: |
7850 | + break; |
7851 | + case -1: |
7852 | + exit(2); |
7853 | + default: |
7854 | + exit(0); |
7855 | + } |
7856 | + |
7857 | + mpsslog("MIC Daemon start\n"); |
7858 | + |
7859 | + cnt = init_mic_list(); |
7860 | + if (cnt == 0) { |
7861 | + mpsslog("MIC module not loaded\n"); |
7862 | + exit(3); |
7863 | + } |
7864 | + mpsslog("MIC found %d devices\n", cnt); |
7865 | + |
7866 | + start_daemon(); |
7867 | + |
7868 | + exit(0); |
7869 | +} |
7870 | diff --git a/samples/mic/mpssd/mpssd.h b/samples/mic/mpssd/mpssd.h |
7871 | new file mode 100644 |
7872 | index 000000000000..8bd64944aacc |
7873 | --- /dev/null |
7874 | +++ b/samples/mic/mpssd/mpssd.h |
7875 | @@ -0,0 +1,103 @@ |
7876 | +/* |
7877 | + * Intel MIC Platform Software Stack (MPSS) |
7878 | + * |
7879 | + * Copyright(c) 2013 Intel Corporation. |
7880 | + * |
7881 | + * This program is free software; you can redistribute it and/or modify |
7882 | + * it under the terms of the GNU General Public License, version 2, as |
7883 | + * published by the Free Software Foundation. |
7884 | + * |
7885 | + * This program is distributed in the hope that it will be useful, but |
7886 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
7887 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
7888 | + * General Public License for more details. |
7889 | + * |
7890 | + * The full GNU General Public License is included in this distribution in |
7891 | + * the file called "COPYING". |
7892 | + * |
7893 | + * Intel MIC User Space Tools. |
7894 | + */ |
7895 | +#ifndef _MPSSD_H_ |
7896 | +#define _MPSSD_H_ |
7897 | + |
7898 | +#include <stdio.h> |
7899 | +#include <stdlib.h> |
7900 | +#include <string.h> |
7901 | +#include <fcntl.h> |
7902 | +#include <unistd.h> |
7903 | +#include <dirent.h> |
7904 | +#include <libgen.h> |
7905 | +#include <pthread.h> |
7906 | +#include <stdarg.h> |
7907 | +#include <time.h> |
7908 | +#include <errno.h> |
7909 | +#include <sys/dir.h> |
7910 | +#include <sys/ioctl.h> |
7911 | +#include <sys/poll.h> |
7912 | +#include <sys/types.h> |
7913 | +#include <sys/socket.h> |
7914 | +#include <sys/stat.h> |
7915 | +#include <sys/types.h> |
7916 | +#include <sys/mman.h> |
7917 | +#include <sys/utsname.h> |
7918 | +#include <sys/wait.h> |
7919 | +#include <netinet/in.h> |
7920 | +#include <arpa/inet.h> |
7921 | +#include <netdb.h> |
7922 | +#include <pthread.h> |
7923 | +#include <signal.h> |
7924 | +#include <limits.h> |
7925 | +#include <syslog.h> |
7926 | +#include <getopt.h> |
7927 | +#include <net/if.h> |
7928 | +#include <linux/if_tun.h> |
7929 | +#include <linux/if_tun.h> |
7930 | +#include <linux/virtio_ids.h> |
7931 | + |
7932 | +#define MICSYSFSDIR "/sys/class/mic" |
7933 | +#define LOGFILE_NAME "/var/log/mpssd" |
7934 | +#define PAGE_SIZE 4096 |
7935 | + |
7936 | +struct mic_console_info { |
7937 | + pthread_t console_thread; |
7938 | + int virtio_console_fd; |
7939 | + void *console_dp; |
7940 | +}; |
7941 | + |
7942 | +struct mic_net_info { |
7943 | + pthread_t net_thread; |
7944 | + int virtio_net_fd; |
7945 | + int tap_fd; |
7946 | + void *net_dp; |
7947 | +}; |
7948 | + |
7949 | +struct mic_virtblk_info { |
7950 | + pthread_t block_thread; |
7951 | + int virtio_block_fd; |
7952 | + void *block_dp; |
7953 | + volatile sig_atomic_t signaled; |
7954 | + char *backend_file; |
7955 | + int backend; |
7956 | + void *backend_addr; |
7957 | + long backend_size; |
7958 | +}; |
7959 | + |
7960 | +struct mic_info { |
7961 | + int id; |
7962 | + char *name; |
7963 | + pthread_t config_thread; |
7964 | + pthread_t init_thread; |
7965 | + pid_t pid; |
7966 | + struct mic_console_info mic_console; |
7967 | + struct mic_net_info mic_net; |
7968 | + struct mic_virtblk_info mic_virtblk; |
7969 | + int restart; |
7970 | + int boot_on_resume; |
7971 | + struct mic_info *next; |
7972 | +}; |
7973 | + |
7974 | +__attribute__((format(printf, 1, 2))) |
7975 | +void mpsslog(char *format, ...); |
7976 | +char *readsysfs(char *dir, char *entry); |
7977 | +int setsysfs(char *dir, char *entry, char *value); |
7978 | +#endif |
7979 | diff --git a/samples/mic/mpssd/sysfs.c b/samples/mic/mpssd/sysfs.c |
7980 | new file mode 100644 |
7981 | index 000000000000..8dd326936083 |
7982 | --- /dev/null |
7983 | +++ b/samples/mic/mpssd/sysfs.c |
7984 | @@ -0,0 +1,102 @@ |
7985 | +/* |
7986 | + * Intel MIC Platform Software Stack (MPSS) |
7987 | + * |
7988 | + * Copyright(c) 2013 Intel Corporation. |
7989 | + * |
7990 | + * This program is free software; you can redistribute it and/or modify |
7991 | + * it under the terms of the GNU General Public License, version 2, as |
7992 | + * published by the Free Software Foundation. |
7993 | + * |
7994 | + * This program is distributed in the hope that it will be useful, but |
7995 | + * WITHOUT ANY WARRANTY; without even the implied warranty of |
7996 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
7997 | + * General Public License for more details. |
7998 | + * |
7999 | + * The full GNU General Public License is included in this distribution in |
8000 | + * the file called "COPYING". |
8001 | + * |
8002 | + * Intel MIC User Space Tools. |
8003 | + */ |
8004 | + |
8005 | +#include "mpssd.h" |
8006 | + |
8007 | +#define PAGE_SIZE 4096 |
8008 | + |
8009 | +char * |
8010 | +readsysfs(char *dir, char *entry) |
8011 | +{ |
8012 | + char filename[PATH_MAX]; |
8013 | + char value[PAGE_SIZE]; |
8014 | + char *string = NULL; |
8015 | + int fd; |
8016 | + int len; |
8017 | + |
8018 | + if (dir == NULL) |
8019 | + snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry); |
8020 | + else |
8021 | + snprintf(filename, PATH_MAX, |
8022 | + "%s/%s/%s", MICSYSFSDIR, dir, entry); |
8023 | + |
8024 | + fd = open(filename, O_RDONLY); |
8025 | + if (fd < 0) { |
8026 | + mpsslog("Failed to open sysfs entry '%s': %s\n", |
8027 | + filename, strerror(errno)); |
8028 | + return NULL; |
8029 | + } |
8030 | + |
8031 | + len = read(fd, value, sizeof(value)); |
8032 | + if (len < 0) { |
8033 | + mpsslog("Failed to read sysfs entry '%s': %s\n", |
8034 | + filename, strerror(errno)); |
8035 | + goto readsys_ret; |
8036 | + } |
8037 | + if (len == 0) |
8038 | + goto readsys_ret; |
8039 | + |
8040 | + value[len - 1] = '\0'; |
8041 | + |
8042 | + string = malloc(strlen(value) + 1); |
8043 | + if (string) |
8044 | + strcpy(string, value); |
8045 | + |
8046 | +readsys_ret: |
8047 | + close(fd); |
8048 | + return string; |
8049 | +} |
8050 | + |
8051 | +int |
8052 | +setsysfs(char *dir, char *entry, char *value) |
8053 | +{ |
8054 | + char filename[PATH_MAX]; |
8055 | + char *oldvalue; |
8056 | + int fd, ret = 0; |
8057 | + |
8058 | + if (dir == NULL) |
8059 | + snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry); |
8060 | + else |
8061 | + snprintf(filename, PATH_MAX, "%s/%s/%s", |
8062 | + MICSYSFSDIR, dir, entry); |
8063 | + |
8064 | + oldvalue = readsysfs(dir, entry); |
8065 | + |
8066 | + fd = open(filename, O_RDWR); |
8067 | + if (fd < 0) { |
8068 | + ret = errno; |
8069 | + mpsslog("Failed to open sysfs entry '%s': %s\n", |
8070 | + filename, strerror(errno)); |
8071 | + goto done; |
8072 | + } |
8073 | + |
8074 | + if (!oldvalue || strcmp(value, oldvalue)) { |
8075 | + if (write(fd, value, strlen(value)) < 0) { |
8076 | + ret = errno; |
8077 | + mpsslog("Failed to write new sysfs entry '%s': %s\n", |
8078 | + filename, strerror(errno)); |
8079 | + } |
8080 | + } |
8081 | + close(fd); |
8082 | +done: |
8083 | + if (oldvalue) |
8084 | + free(oldvalue); |
8085 | + return ret; |
8086 | +} |
8087 | diff --git a/samples/seccomp/bpf-helper.h b/samples/seccomp/bpf-helper.h |
8088 | index 38ee70f3cd5b..1d8de9edd858 100644 |
8089 | --- a/samples/seccomp/bpf-helper.h |
8090 | +++ b/samples/seccomp/bpf-helper.h |
8091 | @@ -138,7 +138,7 @@ union arg64 { |
8092 | #define ARG_32(idx) \ |
8093 | BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)) |
8094 | |
8095 | -/* Loads hi into A and lo in X */ |
8096 | +/* Loads lo into M[0] and hi into M[1] and A */ |
8097 | #define ARG_64(idx) \ |
8098 | BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)), \ |
8099 | BPF_STMT(BPF_ST, 0), /* lo -> M[0] */ \ |
8100 | @@ -153,88 +153,107 @@ union arg64 { |
8101 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 1, 0), \ |
8102 | jt |
8103 | |
8104 | -/* Checks the lo, then swaps to check the hi. A=lo,X=hi */ |
8105 | +#define JA32(value, jt) \ |
8106 | + BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \ |
8107 | + jt |
8108 | + |
8109 | +#define JGE32(value, jt) \ |
8110 | + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \ |
8111 | + jt |
8112 | + |
8113 | +#define JGT32(value, jt) \ |
8114 | + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \ |
8115 | + jt |
8116 | + |
8117 | +#define JLE32(value, jt) \ |
8118 | + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \ |
8119 | + jt |
8120 | + |
8121 | +#define JLT32(value, jt) \ |
8122 | + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \ |
8123 | + jt |
8124 | + |
8125 | +/* |
8126 | + * All the JXX64 checks assume lo is saved in M[0] and hi is saved in both |
8127 | + * A and M[1]. This invariant is kept by restoring A if necessary. |
8128 | + */ |
8129 | #define JEQ64(lo, hi, jt) \ |
8130 | + /* if (hi != arg.hi) goto NOMATCH; */ \ |
8131 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ |
8132 | BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ |
8133 | + /* if (lo != arg.lo) goto NOMATCH; */ \ |
8134 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 0, 2), \ |
8135 | - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ |
8136 | + BPF_STMT(BPF_LD+BPF_MEM, 1), \ |
8137 | jt, \ |
8138 | - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ |
8139 | + BPF_STMT(BPF_LD+BPF_MEM, 1) |
8140 | |
8141 | #define JNE64(lo, hi, jt) \ |
8142 | - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 5, 0), \ |
8143 | - BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ |
8144 | + /* if (hi != arg.hi) goto MATCH; */ \ |
8145 | + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \ |
8146 | + BPF_STMT(BPF_LD+BPF_MEM, 0), \ |
8147 | + /* if (lo != arg.lo) goto MATCH; */ \ |
8148 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 2, 0), \ |
8149 | - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ |
8150 | + BPF_STMT(BPF_LD+BPF_MEM, 1), \ |
8151 | jt, \ |
8152 | - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ |
8153 | - |
8154 | -#define JA32(value, jt) \ |
8155 | - BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \ |
8156 | - jt |
8157 | + BPF_STMT(BPF_LD+BPF_MEM, 1) |
8158 | |
8159 | #define JA64(lo, hi, jt) \ |
8160 | + /* if (hi & arg.hi) goto MATCH; */ \ |
8161 | BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (hi), 3, 0), \ |
8162 | - BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ |
8163 | + BPF_STMT(BPF_LD+BPF_MEM, 0), \ |
8164 | + /* if (lo & arg.lo) goto MATCH; */ \ |
8165 | BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (lo), 0, 2), \ |
8166 | - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ |
8167 | + BPF_STMT(BPF_LD+BPF_MEM, 1), \ |
8168 | jt, \ |
8169 | - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ |
8170 | + BPF_STMT(BPF_LD+BPF_MEM, 1) |
8171 | |
8172 | -#define JGE32(value, jt) \ |
8173 | - BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \ |
8174 | - jt |
8175 | - |
8176 | -#define JLT32(value, jt) \ |
8177 | - BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \ |
8178 | - jt |
8179 | - |
8180 | -/* Shortcut checking if hi > arg.hi. */ |
8181 | #define JGE64(lo, hi, jt) \ |
8182 | + /* if (hi > arg.hi) goto MATCH; */ \ |
8183 | BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \ |
8184 | + /* if (hi != arg.hi) goto NOMATCH; */ \ |
8185 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ |
8186 | - BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ |
8187 | + BPF_STMT(BPF_LD+BPF_MEM, 0), \ |
8188 | + /* if (lo >= arg.lo) goto MATCH; */ \ |
8189 | BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 0, 2), \ |
8190 | - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ |
8191 | - jt, \ |
8192 | - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ |
8193 | - |
8194 | -#define JLT64(lo, hi, jt) \ |
8195 | - BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \ |
8196 | - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ |
8197 | - BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ |
8198 | - BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \ |
8199 | - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ |
8200 | + BPF_STMT(BPF_LD+BPF_MEM, 1), \ |
8201 | jt, \ |
8202 | - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ |
8203 | + BPF_STMT(BPF_LD+BPF_MEM, 1) |
8204 | |
8205 | -#define JGT32(value, jt) \ |
8206 | - BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \ |
8207 | - jt |
8208 | - |
8209 | -#define JLE32(value, jt) \ |
8210 | - BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \ |
8211 | - jt |
8212 | - |
8213 | -/* Check hi > args.hi first, then do the GE checking */ |
8214 | #define JGT64(lo, hi, jt) \ |
8215 | + /* if (hi > arg.hi) goto MATCH; */ \ |
8216 | BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \ |
8217 | + /* if (hi != arg.hi) goto NOMATCH; */ \ |
8218 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ |
8219 | - BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ |
8220 | + BPF_STMT(BPF_LD+BPF_MEM, 0), \ |
8221 | + /* if (lo > arg.lo) goto MATCH; */ \ |
8222 | BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 0, 2), \ |
8223 | - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ |
8224 | + BPF_STMT(BPF_LD+BPF_MEM, 1), \ |
8225 | jt, \ |
8226 | - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ |
8227 | + BPF_STMT(BPF_LD+BPF_MEM, 1) |
8228 | |
8229 | #define JLE64(lo, hi, jt) \ |
8230 | - BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 6, 0), \ |
8231 | - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \ |
8232 | - BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ |
8233 | + /* if (hi < arg.hi) goto MATCH; */ \ |
8234 | + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \ |
8235 | + /* if (hi != arg.hi) goto NOMATCH; */ \ |
8236 | + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ |
8237 | + BPF_STMT(BPF_LD+BPF_MEM, 0), \ |
8238 | + /* if (lo <= arg.lo) goto MATCH; */ \ |
8239 | BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \ |
8240 | - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ |
8241 | + BPF_STMT(BPF_LD+BPF_MEM, 1), \ |
8242 | + jt, \ |
8243 | + BPF_STMT(BPF_LD+BPF_MEM, 1) |
8244 | + |
8245 | +#define JLT64(lo, hi, jt) \ |
8246 | + /* if (hi < arg.hi) goto MATCH; */ \ |
8247 | + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \ |
8248 | + /* if (hi != arg.hi) goto NOMATCH; */ \ |
8249 | + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ |
8250 | + BPF_STMT(BPF_LD+BPF_MEM, 0), \ |
8251 | + /* if (lo < arg.lo) goto MATCH; */ \ |
8252 | + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 2, 0), \ |
8253 | + BPF_STMT(BPF_LD+BPF_MEM, 1), \ |
8254 | jt, \ |
8255 | - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ |
8256 | + BPF_STMT(BPF_LD+BPF_MEM, 1) |
8257 | |
8258 | #define LOAD_SYSCALL_NR \ |
8259 | BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ |
8260 | diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c |
8261 | index 1d5acbe0c08b..86240d02b530 100644 |
8262 | --- a/sound/core/seq/seq_fifo.c |
8263 | +++ b/sound/core/seq/seq_fifo.c |
8264 | @@ -135,6 +135,7 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f, |
8265 | f->tail = cell; |
8266 | if (f->head == NULL) |
8267 | f->head = cell; |
8268 | + cell->next = NULL; |
8269 | f->cells++; |
8270 | spin_unlock_irqrestore(&f->lock, flags); |
8271 | |
8272 | @@ -214,6 +215,8 @@ void snd_seq_fifo_cell_putback(struct snd_seq_fifo *f, |
8273 | spin_lock_irqsave(&f->lock, flags); |
8274 | cell->next = f->head; |
8275 | f->head = cell; |
8276 | + if (!f->tail) |
8277 | + f->tail = cell; |
8278 | f->cells++; |
8279 | spin_unlock_irqrestore(&f->lock, flags); |
8280 | } |
8281 | diff --git a/sound/core/timer.c b/sound/core/timer.c |
8282 | index ae4ea2e2e7fe..278a332f97bd 100644 |
8283 | --- a/sound/core/timer.c |
8284 | +++ b/sound/core/timer.c |
8285 | @@ -1700,9 +1700,21 @@ static int snd_timer_user_params(struct file *file, |
8286 | return -EBADFD; |
8287 | if (copy_from_user(¶ms, _params, sizeof(params))) |
8288 | return -EFAULT; |
8289 | - if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) { |
8290 | - err = -EINVAL; |
8291 | - goto _end; |
8292 | + if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) { |
8293 | + u64 resolution; |
8294 | + |
8295 | + if (params.ticks < 1) { |
8296 | + err = -EINVAL; |
8297 | + goto _end; |
8298 | + } |
8299 | + |
8300 | + /* Don't allow resolution less than 1ms */ |
8301 | + resolution = snd_timer_resolution(tu->timeri); |
8302 | + resolution *= params.ticks; |
8303 | + if (resolution < 1000000) { |
8304 | + err = -EINVAL; |
8305 | + goto _end; |
8306 | + } |
8307 | } |
8308 | if (params.queue_size > 0 && |
8309 | (params.queue_size < 32 || params.queue_size > 1024)) { |
8310 | diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c |
8311 | index 9667cbfb0ca2..ab4cdab5cfa5 100644 |
8312 | --- a/sound/pci/ctxfi/cthw20k1.c |
8313 | +++ b/sound/pci/ctxfi/cthw20k1.c |
8314 | @@ -27,12 +27,6 @@ |
8315 | #include "cthw20k1.h" |
8316 | #include "ct20k1reg.h" |
8317 | |
8318 | -#if BITS_PER_LONG == 32 |
8319 | -#define CT_XFI_DMA_MASK DMA_BIT_MASK(32) /* 32 bit PTE */ |
8320 | -#else |
8321 | -#define CT_XFI_DMA_MASK DMA_BIT_MASK(64) /* 64 bit PTE */ |
8322 | -#endif |
8323 | - |
8324 | struct hw20k1 { |
8325 | struct hw hw; |
8326 | spinlock_t reg_20k1_lock; |
8327 | @@ -1904,19 +1898,18 @@ static int hw_card_start(struct hw *hw) |
8328 | { |
8329 | int err; |
8330 | struct pci_dev *pci = hw->pci; |
8331 | + const unsigned int dma_bits = BITS_PER_LONG; |
8332 | |
8333 | err = pci_enable_device(pci); |
8334 | if (err < 0) |
8335 | return err; |
8336 | |
8337 | /* Set DMA transfer mask */ |
8338 | - if (dma_set_mask(&pci->dev, CT_XFI_DMA_MASK) < 0 || |
8339 | - dma_set_coherent_mask(&pci->dev, CT_XFI_DMA_MASK) < 0) { |
8340 | - dev_err(hw->card->dev, |
8341 | - "architecture does not support PCI busmaster DMA with mask 0x%llx\n", |
8342 | - CT_XFI_DMA_MASK); |
8343 | - err = -ENXIO; |
8344 | - goto error1; |
8345 | + if (dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) { |
8346 | + dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits)); |
8347 | + } else { |
8348 | + dma_set_mask(&pci->dev, DMA_BIT_MASK(32)); |
8349 | + dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)); |
8350 | } |
8351 | |
8352 | if (!hw->io_base) { |
8353 | diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c |
8354 | index 9dc2950e1ab7..d86678c2a957 100644 |
8355 | --- a/sound/pci/ctxfi/cthw20k2.c |
8356 | +++ b/sound/pci/ctxfi/cthw20k2.c |
8357 | @@ -26,12 +26,6 @@ |
8358 | #include "cthw20k2.h" |
8359 | #include "ct20k2reg.h" |
8360 | |
8361 | -#if BITS_PER_LONG == 32 |
8362 | -#define CT_XFI_DMA_MASK DMA_BIT_MASK(32) /* 32 bit PTE */ |
8363 | -#else |
8364 | -#define CT_XFI_DMA_MASK DMA_BIT_MASK(64) /* 64 bit PTE */ |
8365 | -#endif |
8366 | - |
8367 | struct hw20k2 { |
8368 | struct hw hw; |
8369 | /* for i2c */ |
8370 | @@ -2029,19 +2023,18 @@ static int hw_card_start(struct hw *hw) |
8371 | int err = 0; |
8372 | struct pci_dev *pci = hw->pci; |
8373 | unsigned int gctl; |
8374 | + const unsigned int dma_bits = BITS_PER_LONG; |
8375 | |
8376 | err = pci_enable_device(pci); |
8377 | if (err < 0) |
8378 | return err; |
8379 | |
8380 | /* Set DMA transfer mask */ |
8381 | - if (dma_set_mask(&pci->dev, CT_XFI_DMA_MASK) < 0 || |
8382 | - dma_set_coherent_mask(&pci->dev, CT_XFI_DMA_MASK) < 0) { |
8383 | - dev_err(hw->card->dev, |
8384 | - "architecture does not support PCI busmaster DMA with mask 0x%llx\n", |
8385 | - CT_XFI_DMA_MASK); |
8386 | - err = -ENXIO; |
8387 | - goto error1; |
8388 | + if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) { |
8389 | + dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits)); |
8390 | + } else { |
8391 | + dma_set_mask(&pci->dev, DMA_BIT_MASK(32)); |
8392 | + dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)); |
8393 | } |
8394 | |
8395 | if (!hw->io_base) { |
8396 | diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c |
8397 | index ad4a1e9a3ae1..8f3e5e9d8bdb 100644 |
8398 | --- a/sound/pci/hda/hda_intel.c |
8399 | +++ b/sound/pci/hda/hda_intel.c |
8400 | @@ -2208,9 +2208,9 @@ static const struct pci_device_id azx_ids[] = { |
8401 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, |
8402 | /* Lewisburg */ |
8403 | { PCI_DEVICE(0x8086, 0xa1f0), |
8404 | - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, |
8405 | + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, |
8406 | { PCI_DEVICE(0x8086, 0xa270), |
8407 | - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, |
8408 | + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, |
8409 | /* Lynx Point-LP */ |
8410 | { PCI_DEVICE(0x8086, 0x9c20), |
8411 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, |
8412 | diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c |
8413 | index 00c50d58f108..cf0785ddbd14 100644 |
8414 | --- a/sound/pci/hda/patch_realtek.c |
8415 | +++ b/sound/pci/hda/patch_realtek.c |
8416 | @@ -5560,6 +5560,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
8417 | SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE), |
8418 | SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), |
8419 | SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME), |
8420 | + SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER), |
8421 | SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
8422 | SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), |
8423 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), |
8424 | @@ -5674,6 +5675,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
8425 | SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460), |
8426 | SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), |
8427 | SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), |
8428 | + SND_PCI_QUIRK(0x17aa, 0x3112, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), |
8429 | SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), |
8430 | SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), |
8431 | SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP), |
8432 | @@ -6047,6 +6049,12 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { |
8433 | SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, |
8434 | ALC298_STANDARD_PINS, |
8435 | {0x17, 0x90170150}), |
8436 | + SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_SPK_VOLUME, |
8437 | + {0x12, 0xb7a60140}, |
8438 | + {0x13, 0xb7a60150}, |
8439 | + {0x17, 0x90170110}, |
8440 | + {0x1a, 0x03011020}, |
8441 | + {0x21, 0x03211030}), |
8442 | {} |
8443 | }; |
8444 |