diff options
Diffstat (limited to 'Documentation/mic')
| -rw-r--r-- | Documentation/mic/mic_overview.txt | 31 | ||||
| -rwxr-xr-x | Documentation/mic/mpssd/mpss | 4 | ||||
| -rw-r--r-- | Documentation/mic/mpssd/mpssd.c | 362 | ||||
| -rw-r--r-- | Documentation/mic/mpssd/mpssd.h | 1 |
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 | |||
| 28 | low level communications API across PCIe currently implemented for MIC. | 28 | low level communications API across PCIe currently implemented for MIC. |
| 29 | More details are available at scif_overview.txt. | 29 | More details are available at scif_overview.txt. |
| 30 | 30 | ||
| 31 | The Coprocessor State Management (COSM) driver on the host allows for | ||
| 32 | boot, 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 | |||
| 31 | Here is a block diagram of the various components described above. The | 35 | Here is a block diagram of the various components described above. The |
| 32 | virtio backends are situated on the host rather than the card given better | 36 | virtio backends are situated on the host rather than the card given better |
| 33 | single threaded performance for the host compared to MIC, the ability of | 37 | single 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 | ||
| 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); |
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; |
