Annotation of /trunk/kernel-alx/patches-4.4/0152-4.4.53-all-fixes.patch
Parent Directory | Revision Log
Revision 2888 -
(hide 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 | niro | 2888 | 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 |