aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/mic
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/mic')
-rw-r--r--Documentation/mic/mic_overview.txt31
-rwxr-xr-xDocumentation/mic/mpssd/mpss4
-rw-r--r--Documentation/mic/mpssd/mpssd.c362
-rw-r--r--Documentation/mic/mpssd/mpssd.h1
4 files changed, 251 insertions, 147 deletions
diff --git a/Documentation/mic/mic_overview.txt b/Documentation/mic/mic_overview.txt
index 1a2f2c8ec59e..73f44fc3e715 100644
--- a/Documentation/mic/mic_overview.txt
+++ b/Documentation/mic/mic_overview.txt
@@ -28,6 +28,10 @@ The Symmetric Communication Interface (SCIF (pronounced as skiff)) is a
28low level communications API across PCIe currently implemented for MIC. 28low level communications API across PCIe currently implemented for MIC.
29More details are available at scif_overview.txt. 29More details are available at scif_overview.txt.
30 30
31The Coprocessor State Management (COSM) driver on the host allows for
32boot, shutdown and reset of Intel MIC devices. It communicates with a COSM
33"client" driver on the MIC cards over SCIF to perform these functions.
34
31Here is a block diagram of the various components described above. The 35Here is a block diagram of the various components described above. The
32virtio backends are situated on the host rather than the card given better 36virtio backends are situated on the host rather than the card given better
33single threaded performance for the host compared to MIC, the ability of 37single threaded performance for the host compared to MIC, the ability of
@@ -51,19 +55,20 @@ the fact that the virtio block storage backend can only be on the host.
51 | | | Virtio over PCIe IOCTLs | 55 | | | Virtio over PCIe IOCTLs |
52 | | +--------------------------+ 56 | | +--------------------------+
53+-----------+ | | | +-----------+ 57+-----------+ | | | +-----------+
54| MIC DMA | | +----------+ | +-----------+ | | MIC DMA | 58| MIC DMA | | +------+ | +------+ +------+ | | MIC DMA |
55| Driver | | | SCIF | | | SCIF | | | Driver | 59| Driver | | | SCIF | | | SCIF | | COSM | | | Driver |
56+-----------+ | +----------+ | +-----------+ | +-----------+ 60+-----------+ | +------+ | +------+ +--+---+ | +-----------+
57 | | | | | | | 61 | | | | | | | |
58+---------------+ | +-----+-----+ | +-----+-----+ | +---------------+ 62+---------------+ | +------+ | +--+---+ +--+---+ | +----------------+
59|MIC virtual Bus| | |SCIF HW Bus| | |SCIF HW BUS| | |MIC virtual Bus| 63|MIC virtual Bus| | |SCIF | | |SCIF | | COSM | | |MIC virtual Bus |
60+---------------+ | +-----------+ | +-----+-----+ | +---------------+ 64+---------------+ | |HW Bus| | |HW Bus| | Bus | | +----------------+
61 | | | | | | | 65 | | +------+ | +--+---+ +------+ | |
62 | +--------------+ | | | +---------------+ | 66 | | | | | | | |
63 | |Intel MIC | | | | |Intel MIC | | 67 | +-----------+---+ | | | +---------------+ |
64 +---|Card Driver +----+ | | |Host Driver | | 68 | |Intel MIC | | | | |Intel MIC | |
65 +--------------+ | +----+---------------+-----+ 69 +---|Card Driver | | | | |Host Driver | |
66 | | | 70 +------------+--------+ | +----+---------------+-----+
71 | | |
67 +-------------------------------------------------------------+ 72 +-------------------------------------------------------------+
68 | | 73 | |
69 | PCIe Bus | 74 | PCIe Bus |
diff --git a/Documentation/mic/mpssd/mpss b/Documentation/mic/mpssd/mpss
index 582aad4811ae..09ea90931649 100755
--- a/Documentation/mic/mpssd/mpss
+++ b/Documentation/mic/mpssd/mpss
@@ -119,10 +119,10 @@ stop()
119 # Wait for the cards to go offline 119 # Wait for the cards to go offline
120 for f in $sysfs/* 120 for f in $sysfs/*
121 do 121 do
122 while [ "`cat $f/state`" != "offline" ] 122 while [ "`cat $f/state`" != "ready" ]
123 do 123 do
124 sleep 1 124 sleep 1
125 echo -e "Waiting for "`basename $f`" to go offline" 125 echo -e "Waiting for "`basename $f`" to become ready"
126 done 126 done
127 done 127 done
128 128
diff --git a/Documentation/mic/mpssd/mpssd.c b/Documentation/mic/mpssd/mpssd.c
index 3c5c379fc29d..aaeafa18d99b 100644
--- a/Documentation/mic/mpssd/mpssd.c
+++ b/Documentation/mic/mpssd/mpssd.c
@@ -43,7 +43,7 @@
43#include <linux/mic_common.h> 43#include <linux/mic_common.h>
44#include <tools/endian.h> 44#include <tools/endian.h>
45 45
46static void init_mic(struct mic_info *mic); 46static void *init_mic(void *arg);
47 47
48static FILE *logfp; 48static FILE *logfp;
49static struct mic_info mic_list; 49static struct mic_info mic_list;
@@ -116,19 +116,18 @@ static struct {
116 .num = htole16(MIC_VRING_ENTRIES), 116 .num = htole16(MIC_VRING_ENTRIES),
117 }, 117 },
118#if GSO_ENABLED 118#if GSO_ENABLED
119 .host_features = htole32( 119 .host_features = htole32(
120 1 << VIRTIO_NET_F_CSUM | 120 1 << VIRTIO_NET_F_CSUM |
121 1 << VIRTIO_NET_F_GSO | 121 1 << VIRTIO_NET_F_GSO |
122 1 << VIRTIO_NET_F_GUEST_TSO4 | 122 1 << VIRTIO_NET_F_GUEST_TSO4 |
123 1 << VIRTIO_NET_F_GUEST_TSO6 | 123 1 << VIRTIO_NET_F_GUEST_TSO6 |
124 1 << VIRTIO_NET_F_GUEST_ECN | 124 1 << VIRTIO_NET_F_GUEST_ECN),
125 1 << VIRTIO_NET_F_GUEST_UFO),
126#else 125#else
127 .host_features = 0, 126 .host_features = 0,
128#endif 127#endif
129}; 128};
130 129
131static const char *mic_config_dir = "/etc/sysconfig/mic"; 130static const char *mic_config_dir = "/etc/mpss";
132static const char *virtblk_backend = "VIRTBLK_BACKEND"; 131static const char *virtblk_backend = "VIRTBLK_BACKEND";
133static struct { 132static struct {
134 struct mic_device_desc dd; 133 struct mic_device_desc dd;
@@ -192,7 +191,7 @@ tap_configure(struct mic_info *mic, char *dev)
192 return ret; 191 return ret;
193 } 192 }
194 193
195 snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id); 194 snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id + 1);
196 195
197 pid = fork(); 196 pid = fork();
198 if (pid == 0) { 197 if (pid == 0) {
@@ -255,8 +254,7 @@ static int tun_alloc(struct mic_info *mic, char *dev)
255 return err; 254 return err;
256 } 255 }
257#if GSO_ENABLED 256#if GSO_ENABLED
258 offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | 257 offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_TSO_ECN;
259 TUN_F_TSO_ECN | TUN_F_UFO;
260 258
261 err = ioctl(fd, TUNSETOFFLOAD, offload); 259 err = ioctl(fd, TUNSETOFFLOAD, offload);
262 if (err < 0) { 260 if (err < 0) {
@@ -332,7 +330,6 @@ static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type)
332 return d; 330 return d;
333 } 331 }
334 mpsslog("%s %s %d not found\n", mic->name, __func__, type); 332 mpsslog("%s %s %d not found\n", mic->name, __func__, type);
335 assert(0);
336 return NULL; 333 return NULL;
337} 334}
338 335
@@ -415,6 +412,13 @@ mic_virtio_copy(struct mic_info *mic, int fd,
415 return ret; 412 return ret;
416} 413}
417 414
415static inline unsigned _vring_size(unsigned int num, unsigned long align)
416{
417 return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (3 + num)
418 + align - 1) & ~(align - 1))
419 + sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num;
420}
421
418/* 422/*
419 * This initialization routine requires at least one 423 * This initialization routine requires at least one
420 * vring i.e. vr0. vr1 is optional. 424 * vring i.e. vr0. vr1 is optional.
@@ -426,8 +430,9 @@ init_vr(struct mic_info *mic, int fd, int type,
426 int vr_size; 430 int vr_size;
427 char *va; 431 char *va;
428 432
429 vr_size = PAGE_ALIGN(vring_size(MIC_VRING_ENTRIES, 433 vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES,
430 MIC_VIRTIO_RING_ALIGN) + sizeof(struct _mic_vring_info)); 434 MIC_VIRTIO_RING_ALIGN) +
435 sizeof(struct _mic_vring_info));
431 va = mmap(NULL, MIC_DEVICE_PAGE_END + vr_size * num_vq, 436 va = mmap(NULL, MIC_DEVICE_PAGE_END + vr_size * num_vq,
432 PROT_READ, MAP_SHARED, fd, 0); 437 PROT_READ, MAP_SHARED, fd, 0);
433 if (MAP_FAILED == va) { 438 if (MAP_FAILED == va) {
@@ -439,25 +444,25 @@ init_vr(struct mic_info *mic, int fd, int type,
439 set_dp(mic, type, va); 444 set_dp(mic, type, va);
440 vr0->va = (struct mic_vring *)&va[MIC_DEVICE_PAGE_END]; 445 vr0->va = (struct mic_vring *)&va[MIC_DEVICE_PAGE_END];
441 vr0->info = vr0->va + 446 vr0->info = vr0->va +
442 vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN); 447 _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN);
443 vring_init(&vr0->vr, 448 vring_init(&vr0->vr,
444 MIC_VRING_ENTRIES, vr0->va, MIC_VIRTIO_RING_ALIGN); 449 MIC_VRING_ENTRIES, vr0->va, MIC_VIRTIO_RING_ALIGN);
445 mpsslog("%s %s vr0 %p vr0->info %p vr_size 0x%x vring 0x%x ", 450 mpsslog("%s %s vr0 %p vr0->info %p vr_size 0x%x vring 0x%x ",
446 __func__, mic->name, vr0->va, vr0->info, vr_size, 451 __func__, mic->name, vr0->va, vr0->info, vr_size,
447 vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN)); 452 _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
448 mpsslog("magic 0x%x expected 0x%x\n", 453 mpsslog("magic 0x%x expected 0x%x\n",
449 le32toh(vr0->info->magic), MIC_MAGIC + type); 454 le32toh(vr0->info->magic), MIC_MAGIC + type);
450 assert(le32toh(vr0->info->magic) == MIC_MAGIC + type); 455 assert(le32toh(vr0->info->magic) == MIC_MAGIC + type);
451 if (vr1) { 456 if (vr1) {
452 vr1->va = (struct mic_vring *) 457 vr1->va = (struct mic_vring *)
453 &va[MIC_DEVICE_PAGE_END + vr_size]; 458 &va[MIC_DEVICE_PAGE_END + vr_size];
454 vr1->info = vr1->va + vring_size(MIC_VRING_ENTRIES, 459 vr1->info = vr1->va + _vring_size(MIC_VRING_ENTRIES,
455 MIC_VIRTIO_RING_ALIGN); 460 MIC_VIRTIO_RING_ALIGN);
456 vring_init(&vr1->vr, 461 vring_init(&vr1->vr,
457 MIC_VRING_ENTRIES, vr1->va, MIC_VIRTIO_RING_ALIGN); 462 MIC_VRING_ENTRIES, vr1->va, MIC_VIRTIO_RING_ALIGN);
458 mpsslog("%s %s vr1 %p vr1->info %p vr_size 0x%x vring 0x%x ", 463 mpsslog("%s %s vr1 %p vr1->info %p vr_size 0x%x vring 0x%x ",
459 __func__, mic->name, vr1->va, vr1->info, vr_size, 464 __func__, mic->name, vr1->va, vr1->info, vr_size,
460 vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN)); 465 _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
461 mpsslog("magic 0x%x expected 0x%x\n", 466 mpsslog("magic 0x%x expected 0x%x\n",
462 le32toh(vr1->info->magic), MIC_MAGIC + type + 1); 467 le32toh(vr1->info->magic), MIC_MAGIC + type + 1);
463 assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1); 468 assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1);
@@ -466,16 +471,21 @@ done:
466 return va; 471 return va;
467} 472}
468 473
469static void 474static int
470wait_for_card_driver(struct mic_info *mic, int fd, int type) 475wait_for_card_driver(struct mic_info *mic, int fd, int type)
471{ 476{
472 struct pollfd pollfd; 477 struct pollfd pollfd;
473 int err; 478 int err;
474 struct mic_device_desc *desc = get_device_desc(mic, type); 479 struct mic_device_desc *desc = get_device_desc(mic, type);
480 __u8 prev_status;
475 481
482 if (!desc)
483 return -ENODEV;
484 prev_status = desc->status;
476 pollfd.fd = fd; 485 pollfd.fd = fd;
477 mpsslog("%s %s Waiting .... desc-> type %d status 0x%x\n", 486 mpsslog("%s %s Waiting .... desc-> type %d status 0x%x\n",
478 mic->name, __func__, type, desc->status); 487 mic->name, __func__, type, desc->status);
488
479 while (1) { 489 while (1) {
480 pollfd.events = POLLIN; 490 pollfd.events = POLLIN;
481 pollfd.revents = 0; 491 pollfd.revents = 0;
@@ -487,8 +497,13 @@ wait_for_card_driver(struct mic_info *mic, int fd, int type)
487 } 497 }
488 498
489 if (pollfd.revents) { 499 if (pollfd.revents) {
490 mpsslog("%s %s Waiting... desc-> type %d status 0x%x\n", 500 if (desc->status != prev_status) {
491 mic->name, __func__, type, desc->status); 501 mpsslog("%s %s Waiting... desc-> type %d "
502 "status 0x%x\n",
503 mic->name, __func__, type,
504 desc->status);
505 prev_status = desc->status;
506 }
492 if (desc->status & VIRTIO_CONFIG_S_DRIVER_OK) { 507 if (desc->status & VIRTIO_CONFIG_S_DRIVER_OK) {
493 mpsslog("%s %s poll.revents %d\n", 508 mpsslog("%s %s poll.revents %d\n",
494 mic->name, __func__, pollfd.revents); 509 mic->name, __func__, pollfd.revents);
@@ -499,6 +514,7 @@ wait_for_card_driver(struct mic_info *mic, int fd, int type)
499 } 514 }
500 } 515 }
501 } 516 }
517 return 0;
502} 518}
503 519
504/* Spin till we have some descriptors */ 520/* Spin till we have some descriptors */
@@ -575,9 +591,16 @@ virtio_net(void *arg)
575 __func__, strerror(errno)); 591 __func__, strerror(errno));
576 continue; 592 continue;
577 } 593 }
578 if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) 594 if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
579 wait_for_card_driver(mic, mic->mic_net.virtio_net_fd, 595 err = wait_for_card_driver(mic,
580 VIRTIO_ID_NET); 596 mic->mic_net.virtio_net_fd,
597 VIRTIO_ID_NET);
598 if (err) {
599 mpsslog("%s %s %d Exiting...\n",
600 mic->name, __func__, __LINE__);
601 break;
602 }
603 }
581 /* 604 /*
582 * Check if there is data to be read from TUN and write to 605 * Check if there is data to be read from TUN and write to
583 * virtio net fd if there is. 606 * virtio net fd if there is.
@@ -786,10 +809,16 @@ virtio_console(void *arg)
786 strerror(errno)); 809 strerror(errno));
787 continue; 810 continue;
788 } 811 }
789 if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) 812 if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
790 wait_for_card_driver(mic, 813 err = wait_for_card_driver(mic,
791 mic->mic_console.virtio_console_fd, 814 mic->mic_console.virtio_console_fd,
792 VIRTIO_ID_CONSOLE); 815 VIRTIO_ID_CONSOLE);
816 if (err) {
817 mpsslog("%s %s %d Exiting...\n",
818 mic->name, __func__, __LINE__);
819 break;
820 }
821 }
793 822
794 if (console_poll[MONITOR_FD].revents & POLLIN) { 823 if (console_poll[MONITOR_FD].revents & POLLIN) {
795 copy.iov = iov0; 824 copy.iov = iov0;
@@ -1048,8 +1077,9 @@ stop_virtblk(struct mic_info *mic)
1048{ 1077{
1049 int vr_size, ret; 1078 int vr_size, ret;
1050 1079
1051 vr_size = PAGE_ALIGN(vring_size(MIC_VRING_ENTRIES, 1080 vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES,
1052 MIC_VIRTIO_RING_ALIGN) + sizeof(struct _mic_vring_info)); 1081 MIC_VIRTIO_RING_ALIGN) +
1082 sizeof(struct _mic_vring_info));
1053 ret = munmap(mic->mic_virtblk.block_dp, 1083 ret = munmap(mic->mic_virtblk.block_dp,
1054 MIC_DEVICE_PAGE_END + vr_size * virtblk_dev_page.dd.num_vq); 1084 MIC_DEVICE_PAGE_END + vr_size * virtblk_dev_page.dd.num_vq);
1055 if (ret < 0) 1085 if (ret < 0)
@@ -1131,6 +1161,10 @@ write_status(int fd, __u8 *status)
1131 return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy); 1161 return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
1132} 1162}
1133 1163
1164#ifndef VIRTIO_BLK_T_GET_ID
1165#define VIRTIO_BLK_T_GET_ID 8
1166#endif
1167
1134static void * 1168static void *
1135virtio_block(void *arg) 1169virtio_block(void *arg)
1136{ 1170{
@@ -1297,12 +1331,7 @@ reset(struct mic_info *mic)
1297 mpsslog("%s: %s %d state %s\n", 1331 mpsslog("%s: %s %d state %s\n",
1298 mic->name, __func__, __LINE__, state); 1332 mic->name, __func__, __LINE__, state);
1299 1333
1300 /* 1334 if (!strcmp(state, "ready")) {
1301 * If the shutdown was initiated by OSPM, the state stays
1302 * in "suspended" which is also a valid condition for reset.
1303 */
1304 if ((!strcmp(state, "offline")) ||
1305 (!strcmp(state, "suspended"))) {
1306 free(state); 1335 free(state);
1307 break; 1336 break;
1308 } 1337 }
@@ -1331,34 +1360,50 @@ get_mic_shutdown_status(struct mic_info *mic, char *shutdown_status)
1331 assert(0); 1360 assert(0);
1332}; 1361};
1333 1362
1334static int get_mic_state(struct mic_info *mic, char *state) 1363static int get_mic_state(struct mic_info *mic)
1335{ 1364{
1336 if (!strcmp(state, "offline")) 1365 char *state = NULL;
1337 return MIC_OFFLINE; 1366 enum mic_states mic_state;
1338 if (!strcmp(state, "online")) 1367
1339 return MIC_ONLINE; 1368 while (!state) {
1340 if (!strcmp(state, "shutting_down")) 1369 state = readsysfs(mic->name, "state");
1341 return MIC_SHUTTING_DOWN; 1370 sleep(1);
1342 if (!strcmp(state, "reset_failed")) 1371 }
1343 return MIC_RESET_FAILED; 1372 mpsslog("%s: %s %d state %s\n",
1344 if (!strcmp(state, "suspending")) 1373 mic->name, __func__, __LINE__, state);
1345 return MIC_SUSPENDING; 1374
1346 if (!strcmp(state, "suspended")) 1375 if (!strcmp(state, "ready")) {
1347 return MIC_SUSPENDED; 1376 mic_state = MIC_READY;
1348 mpsslog("%s: BUG invalid state %s\n", mic->name, state); 1377 } else if (!strcmp(state, "booting")) {
1349 /* Invalid state */ 1378 mic_state = MIC_BOOTING;
1350 assert(0); 1379 } else if (!strcmp(state, "online")) {
1380 mic_state = MIC_ONLINE;
1381 } else if (!strcmp(state, "shutting_down")) {
1382 mic_state = MIC_SHUTTING_DOWN;
1383 } else if (!strcmp(state, "reset_failed")) {
1384 mic_state = MIC_RESET_FAILED;
1385 } else if (!strcmp(state, "resetting")) {
1386 mic_state = MIC_RESETTING;
1387 } else {
1388 mpsslog("%s: BUG invalid state %s\n", mic->name, state);
1389 assert(0);
1390 }
1391
1392 free(state);
1393 return mic_state;
1351}; 1394};
1352 1395
1353static void mic_handle_shutdown(struct mic_info *mic) 1396static void mic_handle_shutdown(struct mic_info *mic)
1354{ 1397{
1355#define SHUTDOWN_TIMEOUT 60 1398#define SHUTDOWN_TIMEOUT 60
1356 int i = SHUTDOWN_TIMEOUT, ret, stat = 0; 1399 int i = SHUTDOWN_TIMEOUT;
1357 char *shutdown_status; 1400 char *shutdown_status;
1358 while (i) { 1401 while (i) {
1359 shutdown_status = readsysfs(mic->name, "shutdown_status"); 1402 shutdown_status = readsysfs(mic->name, "shutdown_status");
1360 if (!shutdown_status) 1403 if (!shutdown_status) {
1404 sleep(1);
1361 continue; 1405 continue;
1406 }
1362 mpsslog("%s: %s %d shutdown_status %s\n", 1407 mpsslog("%s: %s %d shutdown_status %s\n",
1363 mic->name, __func__, __LINE__, shutdown_status); 1408 mic->name, __func__, __LINE__, shutdown_status);
1364 switch (get_mic_shutdown_status(mic, shutdown_status)) { 1409 switch (get_mic_shutdown_status(mic, shutdown_status)) {
@@ -1377,94 +1422,110 @@ static void mic_handle_shutdown(struct mic_info *mic)
1377 i--; 1422 i--;
1378 } 1423 }
1379reset: 1424reset:
1380 ret = kill(mic->pid, SIGTERM); 1425 if (!i)
1381 mpsslog("%s: %s %d kill pid %d ret %d\n", 1426 mpsslog("%s: %s %d timing out waiting for shutdown_status %s\n",
1382 mic->name, __func__, __LINE__, 1427 mic->name, __func__, __LINE__, shutdown_status);
1383 mic->pid, ret); 1428 reset(mic);
1384 if (!ret) {
1385 ret = waitpid(mic->pid, &stat,
1386 WIFSIGNALED(stat));
1387 mpsslog("%s: %s %d waitpid ret %d pid %d\n",
1388 mic->name, __func__, __LINE__,
1389 ret, mic->pid);
1390 }
1391 if (ret == mic->pid)
1392 reset(mic);
1393} 1429}
1394 1430
1395static void * 1431static int open_state_fd(struct mic_info *mic)
1396mic_config(void *arg)
1397{ 1432{
1398 struct mic_info *mic = (struct mic_info *)arg;
1399 char *state = NULL;
1400 char pathname[PATH_MAX]; 1433 char pathname[PATH_MAX];
1401 int fd, ret; 1434 int fd;
1402 struct pollfd ufds[1];
1403 char value[4096];
1404 1435
1405 snprintf(pathname, PATH_MAX - 1, "%s/%s/%s", 1436 snprintf(pathname, PATH_MAX - 1, "%s/%s/%s",
1406 MICSYSFSDIR, mic->name, "state"); 1437 MICSYSFSDIR, mic->name, "state");
1407 1438
1408 fd = open(pathname, O_RDONLY); 1439 fd = open(pathname, O_RDONLY);
1409 if (fd < 0) { 1440 if (fd < 0)
1410 mpsslog("%s: opening file %s failed %s\n", 1441 mpsslog("%s: opening file %s failed %s\n",
1411 mic->name, pathname, strerror(errno)); 1442 mic->name, pathname, strerror(errno));
1412 goto error; 1443 return fd;
1444}
1445
1446static int block_till_state_change(int fd, struct mic_info *mic)
1447{
1448 struct pollfd ufds[1];
1449 char value[PAGE_SIZE];
1450 int ret;
1451
1452 ufds[0].fd = fd;
1453 ufds[0].events = POLLERR | POLLPRI;
1454 ret = poll(ufds, 1, -1);
1455 if (ret < 0) {
1456 mpsslog("%s: %s %d poll failed %s\n",
1457 mic->name, __func__, __LINE__, strerror(errno));
1458 return ret;
1459 }
1460
1461 ret = lseek(fd, 0, SEEK_SET);
1462 if (ret < 0) {
1463 mpsslog("%s: %s %d Failed to seek to 0: %s\n",
1464 mic->name, __func__, __LINE__, strerror(errno));
1465 return ret;
1466 }
1467
1468 ret = read(fd, value, sizeof(value));
1469 if (ret < 0) {
1470 mpsslog("%s: %s %d Failed to read sysfs entry: %s\n",
1471 mic->name, __func__, __LINE__, strerror(errno));
1472 return ret;
1473 }
1474
1475 return 0;
1476}
1477
1478static void *
1479mic_config(void *arg)
1480{
1481 struct mic_info *mic = (struct mic_info *)arg;
1482 int fd, ret, stat = 0;
1483
1484 fd = open_state_fd(mic);
1485 if (fd < 0) {
1486 mpsslog("%s: %s %d open state fd failed %s\n",
1487 mic->name, __func__, __LINE__, strerror(errno));
1488 goto exit;
1413 } 1489 }
1414 1490
1415 do { 1491 do {
1416 ret = lseek(fd, 0, SEEK_SET); 1492 ret = block_till_state_change(fd, mic);
1417 if (ret < 0) { 1493 if (ret < 0) {
1418 mpsslog("%s: Failed to seek to file start '%s': %s\n", 1494 mpsslog("%s: %s %d block_till_state_change error %s\n",
1419 mic->name, pathname, strerror(errno)); 1495 mic->name, __func__, __LINE__, strerror(errno));
1420 goto close_error1; 1496 goto close_exit;
1421 } 1497 }
1422 ret = read(fd, value, sizeof(value)); 1498
1423 if (ret < 0) { 1499 switch (get_mic_state(mic)) {
1424 mpsslog("%s: Failed to read sysfs entry '%s': %s\n",
1425 mic->name, pathname, strerror(errno));
1426 goto close_error1;
1427 }
1428retry:
1429 state = readsysfs(mic->name, "state");
1430 if (!state)
1431 goto retry;
1432 mpsslog("%s: %s %d state %s\n",
1433 mic->name, __func__, __LINE__, state);
1434 switch (get_mic_state(mic, state)) {
1435 case MIC_SHUTTING_DOWN: 1500 case MIC_SHUTTING_DOWN:
1436 mic_handle_shutdown(mic); 1501 mic_handle_shutdown(mic);
1437 goto close_error; 1502 break;
1438 case MIC_SUSPENDING: 1503 case MIC_READY:
1439 mic->boot_on_resume = 1; 1504 case MIC_RESET_FAILED:
1440 setsysfs(mic->name, "state", "suspend"); 1505 ret = kill(mic->pid, SIGTERM);
1441 mic_handle_shutdown(mic); 1506 mpsslog("%s: %s %d kill pid %d ret %d\n",
1442 goto close_error; 1507 mic->name, __func__, __LINE__,
1443 case MIC_OFFLINE: 1508 mic->pid, ret);
1509 if (!ret) {
1510 ret = waitpid(mic->pid, &stat,
1511 WIFSIGNALED(stat));
1512 mpsslog("%s: %s %d waitpid ret %d pid %d\n",
1513 mic->name, __func__, __LINE__,
1514 ret, mic->pid);
1515 }
1444 if (mic->boot_on_resume) { 1516 if (mic->boot_on_resume) {
1445 setsysfs(mic->name, "state", "boot"); 1517 setsysfs(mic->name, "state", "boot");
1446 mic->boot_on_resume = 0; 1518 mic->boot_on_resume = 0;
1447 } 1519 }
1448 break; 1520 goto close_exit;
1449 default: 1521 default:
1450 break; 1522 break;
1451 } 1523 }
1452 free(state);
1453
1454 ufds[0].fd = fd;
1455 ufds[0].events = POLLERR | POLLPRI;
1456 ret = poll(ufds, 1, -1);
1457 if (ret < 0) {
1458 mpsslog("%s: poll failed %s\n",
1459 mic->name, strerror(errno));
1460 goto close_error1;
1461 }
1462 } while (1); 1524 } while (1);
1463close_error: 1525
1464 free(state); 1526close_exit:
1465close_error1:
1466 close(fd); 1527 close(fd);
1467error: 1528exit:
1468 init_mic(mic); 1529 init_mic(mic);
1469 pthread_exit(NULL); 1530 pthread_exit(NULL);
1470} 1531}
@@ -1477,15 +1538,15 @@ set_cmdline(struct mic_info *mic)
1477 1538
1478 len = snprintf(buffer, PATH_MAX, 1539 len = snprintf(buffer, PATH_MAX,
1479 "clocksource=tsc highres=off nohz=off "); 1540 "clocksource=tsc highres=off nohz=off ");
1480 len += snprintf(buffer + len, PATH_MAX - len, 1541 len += snprintf(buffer + len, PATH_MAX,
1481 "cpufreq_on;corec6_off;pc3_off;pc6_off "); 1542 "cpufreq_on;corec6_off;pc3_off;pc6_off ");
1482 len += snprintf(buffer + len, PATH_MAX - len, 1543 len += snprintf(buffer + len, PATH_MAX,
1483 "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0", 1544 "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0",
1484 mic->id); 1545 mic->id + 1);
1485 1546
1486 setsysfs(mic->name, "cmdline", buffer); 1547 setsysfs(mic->name, "cmdline", buffer);
1487 mpsslog("%s: Command line: \"%s\"\n", mic->name, buffer); 1548 mpsslog("%s: Command line: \"%s\"\n", mic->name, buffer);
1488 snprintf(buffer, PATH_MAX, "172.31.%d.1", mic->id); 1549 snprintf(buffer, PATH_MAX, "172.31.%d.1", mic->id + 1);
1489 mpsslog("%s: IPADDR: \"%s\"\n", mic->name, buffer); 1550 mpsslog("%s: IPADDR: \"%s\"\n", mic->name, buffer);
1490} 1551}
1491 1552
@@ -1541,8 +1602,6 @@ set_log_buf_info(struct mic_info *mic)
1541 close(fd); 1602 close(fd);
1542} 1603}
1543 1604
1544static void init_mic(struct mic_info *mic);
1545
1546static void 1605static void
1547change_virtblk_backend(int x, siginfo_t *siginfo, void *p) 1606change_virtblk_backend(int x, siginfo_t *siginfo, void *p)
1548{ 1607{
@@ -1553,8 +1612,16 @@ change_virtblk_backend(int x, siginfo_t *siginfo, void *p)
1553} 1612}
1554 1613
1555static void 1614static void
1556init_mic(struct mic_info *mic) 1615set_mic_boot_params(struct mic_info *mic)
1616{
1617 set_log_buf_info(mic);
1618 set_cmdline(mic);
1619}
1620
1621static void *
1622init_mic(void *arg)
1557{ 1623{
1624 struct mic_info *mic = (struct mic_info *)arg;
1558 struct sigaction ignore = { 1625 struct sigaction ignore = {
1559 .sa_flags = 0, 1626 .sa_flags = 0,
1560 .sa_handler = SIG_IGN 1627 .sa_handler = SIG_IGN
@@ -1564,7 +1631,7 @@ init_mic(struct mic_info *mic)
1564 .sa_sigaction = change_virtblk_backend, 1631 .sa_sigaction = change_virtblk_backend,
1565 }; 1632 };
1566 char buffer[PATH_MAX]; 1633 char buffer[PATH_MAX];
1567 int err; 1634 int err, fd;
1568 1635
1569 /* 1636 /*
1570 * Currently, one virtio block device is supported for each MIC card 1637 * Currently, one virtio block device is supported for each MIC card
@@ -1577,12 +1644,38 @@ init_mic(struct mic_info *mic)
1577 * the MIC daemon. 1644 * the MIC daemon.
1578 */ 1645 */
1579 sigaction(SIGUSR1, &ignore, NULL); 1646 sigaction(SIGUSR1, &ignore, NULL);
1647retry:
1648 fd = open_state_fd(mic);
1649 if (fd < 0) {
1650 mpsslog("%s: %s %d open state fd failed %s\n",
1651 mic->name, __func__, __LINE__, strerror(errno));
1652 sleep(2);
1653 goto retry;
1654 }
1655
1656 if (mic->restart) {
1657 snprintf(buffer, PATH_MAX, "boot");
1658 setsysfs(mic->name, "state", buffer);
1659 mpsslog("%s restarting mic %d\n",
1660 mic->name, mic->restart);
1661 mic->restart = 0;
1662 }
1663
1664 while (1) {
1665 while (block_till_state_change(fd, mic)) {
1666 mpsslog("%s: %s %d block_till_state_change error %s\n",
1667 mic->name, __func__, __LINE__, strerror(errno));
1668 sleep(2);
1669 continue;
1670 }
1671
1672 if (get_mic_state(mic) == MIC_BOOTING)
1673 break;
1674 }
1580 1675
1581 mic->pid = fork(); 1676 mic->pid = fork();
1582 switch (mic->pid) { 1677 switch (mic->pid) {
1583 case 0: 1678 case 0:
1584 set_log_buf_info(mic);
1585 set_cmdline(mic);
1586 add_virtio_device(mic, &virtcons_dev_page.dd); 1679 add_virtio_device(mic, &virtcons_dev_page.dd);
1587 add_virtio_device(mic, &virtnet_dev_page.dd); 1680 add_virtio_device(mic, &virtnet_dev_page.dd);
1588 err = pthread_create(&mic->mic_console.console_thread, NULL, 1681 err = pthread_create(&mic->mic_console.console_thread, NULL,
@@ -1612,24 +1705,29 @@ init_mic(struct mic_info *mic)
1612 mic->name, mic->id, errno); 1705 mic->name, mic->id, errno);
1613 break; 1706 break;
1614 default: 1707 default:
1615 if (mic->restart) { 1708 err = pthread_create(&mic->config_thread, NULL,
1616 snprintf(buffer, PATH_MAX, "boot"); 1709 mic_config, mic);
1617 setsysfs(mic->name, "state", buffer); 1710 if (err)
1618 mpsslog("%s restarting mic %d\n", 1711 mpsslog("%s mic_config pthread_create failed %s\n",
1619 mic->name, mic->restart); 1712 mic->name, strerror(err));
1620 mic->restart = 0;
1621 }
1622 pthread_create(&mic->config_thread, NULL, mic_config, mic);
1623 } 1713 }
1714
1715 return NULL;
1624} 1716}
1625 1717
1626static void 1718static void
1627start_daemon(void) 1719start_daemon(void)
1628{ 1720{
1629 struct mic_info *mic; 1721 struct mic_info *mic;
1722 int err;
1630 1723
1631 for (mic = mic_list.next; mic != NULL; mic = mic->next) 1724 for (mic = mic_list.next; mic; mic = mic->next) {
1632 init_mic(mic); 1725 set_mic_boot_params(mic);
1726 err = pthread_create(&mic->init_thread, NULL, init_mic, mic);
1727 if (err)
1728 mpsslog("%s init_mic pthread_create failed %s\n",
1729 mic->name, strerror(err));
1730 }
1633 1731
1634 while (1) 1732 while (1)
1635 sleep(60); 1733 sleep(60);
diff --git a/Documentation/mic/mpssd/mpssd.h b/Documentation/mic/mpssd/mpssd.h
index f5f18b15d9a0..8bd64944aacc 100644
--- a/Documentation/mic/mpssd/mpssd.h
+++ b/Documentation/mic/mpssd/mpssd.h
@@ -86,6 +86,7 @@ struct mic_info {
86 int id; 86 int id;
87 char *name; 87 char *name;
88 pthread_t config_thread; 88 pthread_t config_thread;
89 pthread_t init_thread;
89 pid_t pid; 90 pid_t pid;
90 struct mic_console_info mic_console; 91 struct mic_console_info mic_console;
91 struct mic_net_info mic_net; 92 struct mic_net_info mic_net;