diff options
Diffstat (limited to 'Documentation/mic/mpssd/mpssd.c')
-rw-r--r-- | Documentation/mic/mpssd/mpssd.c | 362 |
1 files changed, 230 insertions, 132 deletions
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 | ||
46 | static void init_mic(struct mic_info *mic); | 46 | static void *init_mic(void *arg); |
47 | 47 | ||
48 | static FILE *logfp; | 48 | static FILE *logfp; |
49 | static struct mic_info mic_list; | 49 | static 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 | ||
131 | static const char *mic_config_dir = "/etc/sysconfig/mic"; | 130 | static const char *mic_config_dir = "/etc/mpss"; |
132 | static const char *virtblk_backend = "VIRTBLK_BACKEND"; | 131 | static const char *virtblk_backend = "VIRTBLK_BACKEND"; |
133 | static struct { | 132 | static 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 | ||
415 | static 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 | ||
469 | static void | 474 | static int |
470 | wait_for_card_driver(struct mic_info *mic, int fd, int type) | 475 | wait_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, ©); | 1161 | return ioctl(fd, MIC_VIRTIO_COPY_DESC, ©); |
1132 | } | 1162 | } |
1133 | 1163 | ||
1164 | #ifndef VIRTIO_BLK_T_GET_ID | ||
1165 | #define VIRTIO_BLK_T_GET_ID 8 | ||
1166 | #endif | ||
1167 | |||
1134 | static void * | 1168 | static void * |
1135 | virtio_block(void *arg) | 1169 | virtio_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 | ||
1334 | static int get_mic_state(struct mic_info *mic, char *state) | 1363 | static 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 | ||
1353 | static void mic_handle_shutdown(struct mic_info *mic) | 1396 | static 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 | } |
1379 | reset: | 1424 | reset: |
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 | ||
1395 | static void * | 1431 | static int open_state_fd(struct mic_info *mic) |
1396 | mic_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 | |||
1446 | static 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 | |||
1478 | static void * | ||
1479 | mic_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 | } | ||
1428 | retry: | ||
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); |
1463 | close_error: | 1525 | |
1464 | free(state); | 1526 | close_exit: |
1465 | close_error1: | ||
1466 | close(fd); | 1527 | close(fd); |
1467 | error: | 1528 | exit: |
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 | ||
1544 | static void init_mic(struct mic_info *mic); | ||
1545 | |||
1546 | static void | 1605 | static void |
1547 | change_virtblk_backend(int x, siginfo_t *siginfo, void *p) | 1606 | change_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 | ||
1555 | static void | 1614 | static void |
1556 | init_mic(struct mic_info *mic) | 1615 | set_mic_boot_params(struct mic_info *mic) |
1616 | { | ||
1617 | set_log_buf_info(mic); | ||
1618 | set_cmdline(mic); | ||
1619 | } | ||
1620 | |||
1621 | static void * | ||
1622 | init_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); |
1647 | retry: | ||
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 | ||
1626 | static void | 1718 | static void |
1627 | start_daemon(void) | 1719 | start_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); |