]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - Documentation/mic/mpssd/mpssd.c
Merge remote-tracking branch 'userns/for-next'
[karo-tx-linux.git] / Documentation / mic / mpssd / mpssd.c
index 3c5c379fc29d6797d0ce17a837cbda64278f68b3..aaeafa18d99bb70bee8cf5bd1d39829b17d6d3d4 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/mic_common.h>
 #include <tools/endian.h>
 
-static void init_mic(struct mic_info *mic);
+static void *init_mic(void *arg);
 
 static FILE *logfp;
 static struct mic_info mic_list;
@@ -116,19 +116,18 @@ static struct {
                .num = htole16(MIC_VRING_ENTRIES),
        },
 #if GSO_ENABLED
-               .host_features = htole32(
+       .host_features = htole32(
                1 << VIRTIO_NET_F_CSUM |
                1 << VIRTIO_NET_F_GSO |
                1 << VIRTIO_NET_F_GUEST_TSO4 |
                1 << VIRTIO_NET_F_GUEST_TSO6 |
-               1 << VIRTIO_NET_F_GUEST_ECN |
-               1 << VIRTIO_NET_F_GUEST_UFO),
+               1 << VIRTIO_NET_F_GUEST_ECN),
 #else
                .host_features = 0,
 #endif
 };
 
-static const char *mic_config_dir = "/etc/sysconfig/mic";
+static const char *mic_config_dir = "/etc/mpss";
 static const char *virtblk_backend = "VIRTBLK_BACKEND";
 static struct {
        struct mic_device_desc dd;
@@ -192,7 +191,7 @@ tap_configure(struct mic_info *mic, char *dev)
                return ret;
        }
 
-       snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id);
+       snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id + 1);
 
        pid = fork();
        if (pid == 0) {
@@ -255,8 +254,7 @@ static int tun_alloc(struct mic_info *mic, char *dev)
                return err;
        }
 #if GSO_ENABLED
-       offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
-               TUN_F_TSO_ECN | TUN_F_UFO;
+       offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_TSO_ECN;
 
        err = ioctl(fd, TUNSETOFFLOAD, offload);
        if (err < 0) {
@@ -332,7 +330,6 @@ static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type)
                        return d;
        }
        mpsslog("%s %s %d not found\n", mic->name, __func__, type);
-       assert(0);
        return NULL;
 }
 
@@ -415,6 +412,13 @@ mic_virtio_copy(struct mic_info *mic, int fd,
        return ret;
 }
 
+static inline unsigned _vring_size(unsigned int num, unsigned long align)
+{
+       return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (3 + num)
+                               + align - 1) & ~(align - 1))
+               + sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num;
+}
+
 /*
  * This initialization routine requires at least one
  * vring i.e. vr0. vr1 is optional.
@@ -426,8 +430,9 @@ init_vr(struct mic_info *mic, int fd, int type,
        int vr_size;
        char *va;
 
-       vr_size = PAGE_ALIGN(vring_size(MIC_VRING_ENTRIES,
-               MIC_VIRTIO_RING_ALIGN) + sizeof(struct _mic_vring_info));
+       vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES,
+                                        MIC_VIRTIO_RING_ALIGN) +
+                            sizeof(struct _mic_vring_info));
        va = mmap(NULL, MIC_DEVICE_PAGE_END + vr_size * num_vq,
                PROT_READ, MAP_SHARED, fd, 0);
        if (MAP_FAILED == va) {
@@ -439,25 +444,25 @@ init_vr(struct mic_info *mic, int fd, int type,
        set_dp(mic, type, va);
        vr0->va = (struct mic_vring *)&va[MIC_DEVICE_PAGE_END];
        vr0->info = vr0->va +
-               vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN);
+               _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN);
        vring_init(&vr0->vr,
                   MIC_VRING_ENTRIES, vr0->va, MIC_VIRTIO_RING_ALIGN);
        mpsslog("%s %s vr0 %p vr0->info %p vr_size 0x%x vring 0x%x ",
                __func__, mic->name, vr0->va, vr0->info, vr_size,
-               vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
+               _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
        mpsslog("magic 0x%x expected 0x%x\n",
                le32toh(vr0->info->magic), MIC_MAGIC + type);
        assert(le32toh(vr0->info->magic) == MIC_MAGIC + type);
        if (vr1) {
                vr1->va = (struct mic_vring *)
                        &va[MIC_DEVICE_PAGE_END + vr_size];
-               vr1->info = vr1->va + vring_size(MIC_VRING_ENTRIES,
+               vr1->info = vr1->va + _vring_size(MIC_VRING_ENTRIES,
                        MIC_VIRTIO_RING_ALIGN);
                vring_init(&vr1->vr,
                           MIC_VRING_ENTRIES, vr1->va, MIC_VIRTIO_RING_ALIGN);
                mpsslog("%s %s vr1 %p vr1->info %p vr_size 0x%x vring 0x%x ",
                        __func__, mic->name, vr1->va, vr1->info, vr_size,
-                       vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
+                       _vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
                mpsslog("magic 0x%x expected 0x%x\n",
                        le32toh(vr1->info->magic), MIC_MAGIC + type + 1);
                assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1);
@@ -466,16 +471,21 @@ done:
        return va;
 }
 
-static void
+static int
 wait_for_card_driver(struct mic_info *mic, int fd, int type)
 {
        struct pollfd pollfd;
        int err;
        struct mic_device_desc *desc = get_device_desc(mic, type);
+       __u8 prev_status;
 
+       if (!desc)
+               return -ENODEV;
+       prev_status = desc->status;
        pollfd.fd = fd;
        mpsslog("%s %s Waiting .... desc-> type %d status 0x%x\n",
                mic->name, __func__, type, desc->status);
+
        while (1) {
                pollfd.events = POLLIN;
                pollfd.revents = 0;
@@ -487,8 +497,13 @@ wait_for_card_driver(struct mic_info *mic, int fd, int type)
                }
 
                if (pollfd.revents) {
-                       mpsslog("%s %s Waiting... desc-> type %d status 0x%x\n",
-                               mic->name, __func__, type, desc->status);
+                       if (desc->status != prev_status) {
+                               mpsslog("%s %s Waiting... desc-> type %d "
+                                       "status 0x%x\n",
+                                       mic->name, __func__, type,
+                                       desc->status);
+                               prev_status = desc->status;
+                       }
                        if (desc->status & VIRTIO_CONFIG_S_DRIVER_OK) {
                                mpsslog("%s %s poll.revents %d\n",
                                        mic->name, __func__, pollfd.revents);
@@ -499,6 +514,7 @@ wait_for_card_driver(struct mic_info *mic, int fd, int type)
                        }
                }
        }
+       return 0;
 }
 
 /* Spin till we have some descriptors */
@@ -575,9 +591,16 @@ virtio_net(void *arg)
                                __func__, strerror(errno));
                        continue;
                }
-               if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK))
-                       wait_for_card_driver(mic, mic->mic_net.virtio_net_fd,
-                                            VIRTIO_ID_NET);
+               if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+                       err = wait_for_card_driver(mic,
+                                                  mic->mic_net.virtio_net_fd,
+                                                  VIRTIO_ID_NET);
+                       if (err) {
+                               mpsslog("%s %s %d Exiting...\n",
+                                       mic->name, __func__, __LINE__);
+                               break;
+                       }
+               }
                /*
                 * Check if there is data to be read from TUN and write to
                 * virtio net fd if there is.
@@ -786,10 +809,16 @@ virtio_console(void *arg)
                                strerror(errno));
                        continue;
                }
-               if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK))
-                       wait_for_card_driver(mic,
-                                            mic->mic_console.virtio_console_fd,
-                               VIRTIO_ID_CONSOLE);
+               if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+                       err = wait_for_card_driver(mic,
+                                       mic->mic_console.virtio_console_fd,
+                                       VIRTIO_ID_CONSOLE);
+                       if (err) {
+                               mpsslog("%s %s %d Exiting...\n",
+                                       mic->name, __func__, __LINE__);
+                               break;
+                       }
+               }
 
                if (console_poll[MONITOR_FD].revents & POLLIN) {
                        copy.iov = iov0;
@@ -1048,8 +1077,9 @@ stop_virtblk(struct mic_info *mic)
 {
        int vr_size, ret;
 
-       vr_size = PAGE_ALIGN(vring_size(MIC_VRING_ENTRIES,
-               MIC_VIRTIO_RING_ALIGN) + sizeof(struct _mic_vring_info));
+       vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES,
+                                        MIC_VIRTIO_RING_ALIGN) +
+                            sizeof(struct _mic_vring_info));
        ret = munmap(mic->mic_virtblk.block_dp,
                MIC_DEVICE_PAGE_END + vr_size * virtblk_dev_page.dd.num_vq);
        if (ret < 0)
@@ -1131,6 +1161,10 @@ write_status(int fd, __u8 *status)
        return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
 }
 
+#ifndef VIRTIO_BLK_T_GET_ID
+#define VIRTIO_BLK_T_GET_ID    8
+#endif
+
 static void *
 virtio_block(void *arg)
 {
@@ -1297,12 +1331,7 @@ reset(struct mic_info *mic)
                mpsslog("%s: %s %d state %s\n",
                        mic->name, __func__, __LINE__, state);
 
-               /*
-                * If the shutdown was initiated by OSPM, the state stays
-                * in "suspended" which is also a valid condition for reset.
-                */
-               if ((!strcmp(state, "offline")) ||
-                   (!strcmp(state, "suspended"))) {
+               if (!strcmp(state, "ready")) {
                        free(state);
                        break;
                }
@@ -1331,34 +1360,50 @@ get_mic_shutdown_status(struct mic_info *mic, char *shutdown_status)
        assert(0);
 };
 
-static int get_mic_state(struct mic_info *mic, char *state)
+static int get_mic_state(struct mic_info *mic)
 {
-       if (!strcmp(state, "offline"))
-               return MIC_OFFLINE;
-       if (!strcmp(state, "online"))
-               return MIC_ONLINE;
-       if (!strcmp(state, "shutting_down"))
-               return MIC_SHUTTING_DOWN;
-       if (!strcmp(state, "reset_failed"))
-               return MIC_RESET_FAILED;
-       if (!strcmp(state, "suspending"))
-               return MIC_SUSPENDING;
-       if (!strcmp(state, "suspended"))
-               return MIC_SUSPENDED;
-       mpsslog("%s: BUG invalid state %s\n", mic->name, state);
-       /* Invalid state */
-       assert(0);
+       char *state = NULL;
+       enum mic_states mic_state;
+
+       while (!state) {
+               state = readsysfs(mic->name, "state");
+               sleep(1);
+       }
+       mpsslog("%s: %s %d state %s\n",
+               mic->name, __func__, __LINE__, state);
+
+       if (!strcmp(state, "ready")) {
+               mic_state = MIC_READY;
+       } else if (!strcmp(state, "booting")) {
+               mic_state = MIC_BOOTING;
+       } else if (!strcmp(state, "online")) {
+               mic_state = MIC_ONLINE;
+       } else if (!strcmp(state, "shutting_down")) {
+               mic_state = MIC_SHUTTING_DOWN;
+       } else if (!strcmp(state, "reset_failed")) {
+               mic_state = MIC_RESET_FAILED;
+       } else if (!strcmp(state, "resetting")) {
+               mic_state = MIC_RESETTING;
+       } else {
+               mpsslog("%s: BUG invalid state %s\n", mic->name, state);
+               assert(0);
+       }
+
+       free(state);
+       return mic_state;
 };
 
 static void mic_handle_shutdown(struct mic_info *mic)
 {
 #define SHUTDOWN_TIMEOUT 60
-       int i = SHUTDOWN_TIMEOUT, ret, stat = 0;
+       int i = SHUTDOWN_TIMEOUT;
        char *shutdown_status;
        while (i) {
                shutdown_status = readsysfs(mic->name, "shutdown_status");
-               if (!shutdown_status)
+               if (!shutdown_status) {
+                       sleep(1);
                        continue;
+               }
                mpsslog("%s: %s %d shutdown_status %s\n",
                        mic->name, __func__, __LINE__, shutdown_status);
                switch (get_mic_shutdown_status(mic, shutdown_status)) {
@@ -1377,94 +1422,110 @@ static void mic_handle_shutdown(struct mic_info *mic)
                i--;
        }
 reset:
-       ret = kill(mic->pid, SIGTERM);
-       mpsslog("%s: %s %d kill pid %d ret %d\n",
-               mic->name, __func__, __LINE__,
-               mic->pid, ret);
-       if (!ret) {
-               ret = waitpid(mic->pid, &stat,
-                       WIFSIGNALED(stat));
-               mpsslog("%s: %s %d waitpid ret %d pid %d\n",
-                       mic->name, __func__, __LINE__,
-                       ret, mic->pid);
-       }
-       if (ret == mic->pid)
-               reset(mic);
+       if (!i)
+               mpsslog("%s: %s %d timing out waiting for shutdown_status %s\n",
+                       mic->name, __func__, __LINE__, shutdown_status);
+       reset(mic);
 }
 
-static void *
-mic_config(void *arg)
+static int open_state_fd(struct mic_info *mic)
 {
-       struct mic_info *mic = (struct mic_info *)arg;
-       char *state = NULL;
        char pathname[PATH_MAX];
-       int fd, ret;
-       struct pollfd ufds[1];
-       char value[4096];
+       int fd;
 
        snprintf(pathname, PATH_MAX - 1, "%s/%s/%s",
                 MICSYSFSDIR, mic->name, "state");
 
        fd = open(pathname, O_RDONLY);
-       if (fd < 0) {
+       if (fd < 0)
                mpsslog("%s: opening file %s failed %s\n",
                        mic->name, pathname, strerror(errno));
-               goto error;
+       return fd;
+}
+
+static int block_till_state_change(int fd, struct mic_info *mic)
+{
+       struct pollfd ufds[1];
+       char value[PAGE_SIZE];
+       int ret;
+
+       ufds[0].fd = fd;
+       ufds[0].events = POLLERR | POLLPRI;
+       ret = poll(ufds, 1, -1);
+       if (ret < 0) {
+               mpsslog("%s: %s %d poll failed %s\n",
+                       mic->name, __func__, __LINE__, strerror(errno));
+               return ret;
+       }
+
+       ret = lseek(fd, 0, SEEK_SET);
+       if (ret < 0) {
+               mpsslog("%s: %s %d Failed to seek to 0: %s\n",
+                       mic->name, __func__, __LINE__, strerror(errno));
+               return ret;
+       }
+
+       ret = read(fd, value, sizeof(value));
+       if (ret < 0) {
+               mpsslog("%s: %s %d Failed to read sysfs entry: %s\n",
+                       mic->name, __func__, __LINE__, strerror(errno));
+               return ret;
+       }
+
+       return 0;
+}
+
+static void *
+mic_config(void *arg)
+{
+       struct mic_info *mic = (struct mic_info *)arg;
+       int fd, ret, stat = 0;
+
+       fd = open_state_fd(mic);
+       if (fd < 0) {
+               mpsslog("%s: %s %d open state fd failed %s\n",
+                       mic->name, __func__, __LINE__, strerror(errno));
+               goto exit;
        }
 
        do {
-               ret = lseek(fd, 0, SEEK_SET);
+               ret = block_till_state_change(fd, mic);
                if (ret < 0) {
-                       mpsslog("%s: Failed to seek to file start '%s': %s\n",
-                               mic->name, pathname, strerror(errno));
-                       goto close_error1;
+                       mpsslog("%s: %s %d block_till_state_change error %s\n",
+                               mic->name, __func__, __LINE__, strerror(errno));
+                       goto close_exit;
                }
-               ret = read(fd, value, sizeof(value));
-               if (ret < 0) {
-                       mpsslog("%s: Failed to read sysfs entry '%s': %s\n",
-                               mic->name, pathname, strerror(errno));
-                       goto close_error1;
-               }
-retry:
-               state = readsysfs(mic->name, "state");
-               if (!state)
-                       goto retry;
-               mpsslog("%s: %s %d state %s\n",
-                       mic->name, __func__, __LINE__, state);
-               switch (get_mic_state(mic, state)) {
+
+               switch (get_mic_state(mic)) {
                case MIC_SHUTTING_DOWN:
                        mic_handle_shutdown(mic);
-                       goto close_error;
-               case MIC_SUSPENDING:
-                       mic->boot_on_resume = 1;
-                       setsysfs(mic->name, "state", "suspend");
-                       mic_handle_shutdown(mic);
-                       goto close_error;
-               case MIC_OFFLINE:
+                       break;
+               case MIC_READY:
+               case MIC_RESET_FAILED:
+                       ret = kill(mic->pid, SIGTERM);
+                       mpsslog("%s: %s %d kill pid %d ret %d\n",
+                               mic->name, __func__, __LINE__,
+                               mic->pid, ret);
+                       if (!ret) {
+                               ret = waitpid(mic->pid, &stat,
+                                             WIFSIGNALED(stat));
+                               mpsslog("%s: %s %d waitpid ret %d pid %d\n",
+                                       mic->name, __func__, __LINE__,
+                                       ret, mic->pid);
+                       }
                        if (mic->boot_on_resume) {
                                setsysfs(mic->name, "state", "boot");
                                mic->boot_on_resume = 0;
                        }
-                       break;
+                       goto close_exit;
                default:
                        break;
                }
-               free(state);
-
-               ufds[0].fd = fd;
-               ufds[0].events = POLLERR | POLLPRI;
-               ret = poll(ufds, 1, -1);
-               if (ret < 0) {
-                       mpsslog("%s: poll failed %s\n",
-                               mic->name, strerror(errno));
-                       goto close_error1;
-               }
        } while (1);
-close_error:
-       free(state);
-close_error1:
+
+close_exit:
        close(fd);
-error:
+exit:
        init_mic(mic);
        pthread_exit(NULL);
 }
@@ -1477,15 +1538,15 @@ set_cmdline(struct mic_info *mic)
 
        len = snprintf(buffer, PATH_MAX,
                "clocksource=tsc highres=off nohz=off ");
-       len += snprintf(buffer + len, PATH_MAX - len,
+       len += snprintf(buffer + len, PATH_MAX,
                "cpufreq_on;corec6_off;pc3_off;pc6_off ");
-       len += snprintf(buffer + len, PATH_MAX - len,
+       len += snprintf(buffer + len, PATH_MAX,
                "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0",
-               mic->id);
+               mic->id + 1);
 
        setsysfs(mic->name, "cmdline", buffer);
        mpsslog("%s: Command line: \"%s\"\n", mic->name, buffer);
-       snprintf(buffer, PATH_MAX, "172.31.%d.1", mic->id);
+       snprintf(buffer, PATH_MAX, "172.31.%d.1", mic->id + 1);
        mpsslog("%s: IPADDR: \"%s\"\n", mic->name, buffer);
 }
 
@@ -1541,8 +1602,6 @@ set_log_buf_info(struct mic_info *mic)
        close(fd);
 }
 
-static void init_mic(struct mic_info *mic);
-
 static void
 change_virtblk_backend(int x, siginfo_t *siginfo, void *p)
 {
@@ -1553,8 +1612,16 @@ change_virtblk_backend(int x, siginfo_t *siginfo, void *p)
 }
 
 static void
-init_mic(struct mic_info *mic)
+set_mic_boot_params(struct mic_info *mic)
+{
+       set_log_buf_info(mic);
+       set_cmdline(mic);
+}
+
+static void *
+init_mic(void *arg)
 {
+       struct mic_info *mic = (struct mic_info *)arg;
        struct sigaction ignore = {
                .sa_flags = 0,
                .sa_handler = SIG_IGN
@@ -1564,7 +1631,7 @@ init_mic(struct mic_info *mic)
                .sa_sigaction = change_virtblk_backend,
        };
        char buffer[PATH_MAX];
-       int err;
+       int err, fd;
 
        /*
         * Currently, one virtio block device is supported for each MIC card
@@ -1577,12 +1644,38 @@ init_mic(struct mic_info *mic)
         * the MIC daemon.
         */
        sigaction(SIGUSR1, &ignore, NULL);
+retry:
+       fd = open_state_fd(mic);
+       if (fd < 0) {
+               mpsslog("%s: %s %d open state fd failed %s\n",
+                       mic->name, __func__, __LINE__, strerror(errno));
+               sleep(2);
+               goto retry;
+       }
+
+       if (mic->restart) {
+               snprintf(buffer, PATH_MAX, "boot");
+               setsysfs(mic->name, "state", buffer);
+               mpsslog("%s restarting mic %d\n",
+                       mic->name, mic->restart);
+               mic->restart = 0;
+       }
+
+       while (1) {
+               while (block_till_state_change(fd, mic)) {
+                       mpsslog("%s: %s %d block_till_state_change error %s\n",
+                               mic->name, __func__, __LINE__, strerror(errno));
+                       sleep(2);
+                       continue;
+               }
+
+               if (get_mic_state(mic) == MIC_BOOTING)
+                       break;
+       }
 
        mic->pid = fork();
        switch (mic->pid) {
        case 0:
-               set_log_buf_info(mic);
-               set_cmdline(mic);
                add_virtio_device(mic, &virtcons_dev_page.dd);
                add_virtio_device(mic, &virtnet_dev_page.dd);
                err = pthread_create(&mic->mic_console.console_thread, NULL,
@@ -1612,24 +1705,29 @@ init_mic(struct mic_info *mic)
                        mic->name, mic->id, errno);
                break;
        default:
-               if (mic->restart) {
-                       snprintf(buffer, PATH_MAX, "boot");
-                       setsysfs(mic->name, "state", buffer);
-                       mpsslog("%s restarting mic %d\n",
-                               mic->name, mic->restart);
-                       mic->restart = 0;
-               }
-               pthread_create(&mic->config_thread, NULL, mic_config, mic);
+               err = pthread_create(&mic->config_thread, NULL,
+                                    mic_config, mic);
+               if (err)
+                       mpsslog("%s mic_config pthread_create failed %s\n",
+                               mic->name, strerror(err));
        }
+
+       return NULL;
 }
 
 static void
 start_daemon(void)
 {
        struct mic_info *mic;
+       int err;
 
-       for (mic = mic_list.next; mic != NULL; mic = mic->next)
-               init_mic(mic);
+       for (mic = mic_list.next; mic; mic = mic->next) {
+               set_mic_boot_params(mic);
+               err = pthread_create(&mic->init_thread, NULL, init_mic, mic);
+               if (err)
+                       mpsslog("%s init_mic pthread_create failed %s\n",
+                               mic->name, strerror(err));
+       }
 
        while (1)
                sleep(60);