/*
 * vhost-user-scsi host device
 *
 * Copyright (c) 2016 Nutanix Inc. All rights reserved.
 *
 * Author:
 *  Felipe Franciosi <felipe@nutanix.com>
 *
 * This work is largely based on the "vhost-scsi" implementation by:
 *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
 *  Nicholas Bellinger <nab@risingtidesystems.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
 * See the COPYING.LIB file in the top-level directory.
 *
 */

#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "hw/fw-path-provider.h"
#include "hw/qdev-core.h"
#include "hw/qdev-properties.h"
#include "hw/qdev-properties-system.h"
#include "hw/virtio/vhost.h"
#include "hw/virtio/vhost-backend.h"
#include "hw/virtio/vhost-user-scsi.h"
#include "hw/virtio/virtio.h"
#include "chardev/char-fe.h"
#include "system/system.h"

/* Features supported by the host application */
static const int user_feature_bits[] = {
    VIRTIO_F_NOTIFY_ON_EMPTY,
    VIRTIO_RING_F_INDIRECT_DESC,
    VIRTIO_RING_F_EVENT_IDX,
    VIRTIO_SCSI_F_HOTPLUG,
    VIRTIO_F_RING_RESET,
    VIRTIO_F_IN_ORDER,
    VIRTIO_F_NOTIFICATION_DATA,
    VHOST_INVALID_FEATURE_BIT
};

static int vhost_user_scsi_start(VHostUserSCSI *s, Error **errp)
{
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
    int ret;

    ret = vhost_scsi_common_start(vsc, errp);
    s->started_vu = !(ret < 0);

    return ret;
}

static int vhost_user_scsi_stop(VHostUserSCSI *s)
{
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);

    if (!s->started_vu) {
        return 0;
    }
    s->started_vu = false;

    return vhost_scsi_common_stop(vsc);
}

static int vhost_user_scsi_set_status(VirtIODevice *vdev, uint8_t status)
{
    VHostUserSCSI *s = (VHostUserSCSI *)vdev;
    DeviceState *dev = DEVICE(vdev);
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
    bool should_start = virtio_device_should_start(vdev, status);
    Error *local_err = NULL;
    int ret;

    if (!s->connected) {
        return -1;
    }

    if (vhost_dev_is_started(&vsc->dev) == should_start) {
        return 0;
    }

    if (should_start) {
        ret = vhost_user_scsi_start(s, &local_err);
        if (ret < 0) {
            error_reportf_err(local_err,
                              "unable to start vhost-user-scsi: %s: ",
                              strerror(-ret));
            qemu_chr_fe_disconnect(&vs->conf.chardev);
        }
    } else {
        ret = vhost_user_scsi_stop(s);
        if (ret) {
            return ret;
        }
    }
    return 0;
}

static void vhost_user_scsi_handle_output(VirtIODevice *vdev, VirtQueue *vq)
{
    VHostUserSCSI *s = (VHostUserSCSI *)vdev;
    DeviceState *dev = DEVICE(vdev);
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);

    Error *local_err = NULL;
    int i, ret;

    if (!vdev->start_on_kick) {
        return;
    }

    if (!s->connected) {
        return;
    }

    if (vhost_dev_is_started(&vsc->dev)) {
        return;
    }

    /*
     * Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start
     * vhost here instead of waiting for .set_status().
     */
    ret = vhost_user_scsi_start(s, &local_err);
    if (ret < 0) {
        error_reportf_err(local_err, "vhost-user-scsi: vhost start failed: ");
        qemu_chr_fe_disconnect(&vs->conf.chardev);
        return;
    }

    /* Kick right away to begin processing requests already in vring */
    for (i = 0; i < vsc->dev.nvqs; i++) {
        VirtQueue *kick_vq = virtio_get_queue(vdev, i);

        if (!virtio_queue_get_desc_addr(vdev, i)) {
            continue;
        }
        event_notifier_set(virtio_queue_get_host_notifier(kick_vq));
    }
}

static int vhost_user_scsi_connect(DeviceState *dev, Error **errp)
{
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VHostUserSCSI *s = VHOST_USER_SCSI(vdev);
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
    int ret = 0;

    if (s->connected) {
        return 0;
    }

    vsc->dev.num_queues = vs->conf.num_queues;
    vsc->dev.nvqs = VIRTIO_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
    vsc->dev.vqs = s->vhost_vqs;
    vsc->dev.vq_index = 0;
    vsc->dev.backend_features = 0;

    ret = vhost_dev_init(&vsc->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0,
                         errp);
    if (ret < 0) {
        return ret;
    }

    s->connected = true;

    /* restore vhost state */
    if (virtio_device_started(vdev, vdev->status)) {
        ret = vhost_user_scsi_start(s, errp);
    }

    return ret;
}

static void vhost_user_scsi_event(void *opaque, QEMUChrEvent event);

static void vhost_user_scsi_disconnect(DeviceState *dev)
{
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VHostUserSCSI *s = VHOST_USER_SCSI(vdev);
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);

    if (!s->connected) {
        goto done;
    }
    s->connected = false;

    vhost_user_scsi_stop(s);

    vhost_dev_cleanup(&vsc->dev);

done:
    /* Re-instate the event handler for new connections */
    qemu_chr_fe_set_handlers(&vs->conf.chardev, NULL, NULL,
                             vhost_user_scsi_event, NULL, dev, NULL, true);
}

static void vhost_user_scsi_event(void *opaque, QEMUChrEvent event)
{
    DeviceState *dev = opaque;
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VHostUserSCSI *s = VHOST_USER_SCSI(vdev);
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
    Error *local_err = NULL;

    switch (event) {
    case CHR_EVENT_OPENED:
        if (vhost_user_scsi_connect(dev, &local_err) < 0) {
            error_report_err(local_err);
            qemu_chr_fe_disconnect(&vs->conf.chardev);
            return;
        }
        break;
    case CHR_EVENT_CLOSED:
        /* defer close until later to avoid circular close */
        vhost_user_async_close(dev, &vs->conf.chardev, &vsc->dev,
                               vhost_user_scsi_disconnect);
        break;
    case CHR_EVENT_BREAK:
    case CHR_EVENT_MUX_IN:
    case CHR_EVENT_MUX_OUT:
        /* Ignore */
        break;
    }
}

static int vhost_user_scsi_realize_connect(VHostUserSCSI *s, Error **errp)
{
    DeviceState *dev = DEVICE(s);
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
    int ret;

    s->connected = false;

    ret = qemu_chr_fe_wait_connected(&vs->conf.chardev, errp);
    if (ret < 0) {
        return ret;
    }

    ret = vhost_user_scsi_connect(dev, errp);
    if (ret < 0) {
        qemu_chr_fe_disconnect(&vs->conf.chardev);
        return ret;
    }
    assert(s->connected);

    return 0;
}

static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
{
    ERRP_GUARD();
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
    VHostUserSCSI *s = VHOST_USER_SCSI(dev);
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
    Error *err = NULL;
    int ret;
    int retries = VU_REALIZE_CONN_RETRIES;

    if (!vs->conf.chardev.chr) {
        error_setg(errp, "vhost-user-scsi: missing chardev");
        return;
    }

    virtio_scsi_common_realize(dev, vhost_user_scsi_handle_output,
                               vhost_user_scsi_handle_output,
                               vhost_user_scsi_handle_output, &err);
    if (err != NULL) {
        error_propagate(errp, err);
        return;
    }

    if (!vhost_user_init(&s->vhost_user, &vs->conf.chardev, errp)) {
        goto free_virtio;
    }

    vsc->inflight = g_new0(struct vhost_inflight, 1);
    s->vhost_vqs = g_new0(struct vhost_virtqueue,
                          VIRTIO_SCSI_VQ_NUM_FIXED + vs->conf.num_queues);

    assert(!*errp);
    do {
        if (*errp) {
            error_prepend(errp, "Reconnecting after error: ");
            error_report_err(*errp);
            *errp = NULL;
        }
        ret = vhost_user_scsi_realize_connect(s, errp);
    } while (ret < 0 && retries--);

    if (ret < 0) {
        goto free_vhost;
    }

    /* we're fully initialized, now we can operate, so add the handler */
    qemu_chr_fe_set_handlers(&vs->conf.chardev,  NULL, NULL,
                             vhost_user_scsi_event, NULL, (void *)dev,
                             NULL, true);
    /* Channel and lun both are 0 for bootable vhost-user-scsi disk */
    vsc->channel = 0;
    vsc->lun = 0;
    vsc->target = vs->conf.boot_tpgt;

    return;

free_vhost:
    g_free(s->vhost_vqs);
    s->vhost_vqs = NULL;
    g_free(vsc->inflight);
    vsc->inflight = NULL;
    vhost_user_cleanup(&s->vhost_user);

free_virtio:
    virtio_scsi_common_unrealize(dev);
}

static void vhost_user_scsi_unrealize(DeviceState *dev)
{
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VHostUserSCSI *s = VHOST_USER_SCSI(dev);
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
    VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);

    /* This will stop the vhost backend. */
    vhost_user_scsi_set_status(vdev, 0);
    qemu_chr_fe_set_handlers(&vs->conf.chardev, NULL, NULL, NULL, NULL, NULL,
                             NULL, false);

    vhost_dev_cleanup(&vsc->dev);
    g_free(s->vhost_vqs);
    s->vhost_vqs = NULL;

    vhost_dev_free_inflight(vsc->inflight);
    g_free(vsc->inflight);
    vsc->inflight = NULL;

    vhost_user_cleanup(&s->vhost_user);
    virtio_scsi_common_unrealize(dev);
}

static const Property vhost_user_scsi_properties[] = {
    DEFINE_PROP_CHR("chardev", VirtIOSCSICommon, conf.chardev),
    DEFINE_PROP_UINT32("boot_tpgt", VirtIOSCSICommon, conf.boot_tpgt, 0),
    DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues,
                       VIRTIO_SCSI_AUTO_NUM_QUEUES),
    DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSICommon, conf.virtqueue_size,
                       128),
    DEFINE_PROP_UINT32("max_sectors", VirtIOSCSICommon, conf.max_sectors,
                       0xFFFF),
    DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSICommon, conf.cmd_per_lun, 128),
    DEFINE_PROP_BIT64("hotplug", VHostSCSICommon, host_features,
                                                  VIRTIO_SCSI_F_HOTPLUG,
                                                  true),
    DEFINE_PROP_BIT64("param_change", VHostSCSICommon, host_features,
                                                       VIRTIO_SCSI_F_CHANGE,
                                                       true),
    DEFINE_PROP_BIT64("t10_pi", VHostSCSICommon, host_features,
                                                 VIRTIO_SCSI_F_T10_PI,
                                                 false),
};

static void vhost_user_scsi_reset(VirtIODevice *vdev)
{
    VHostUserSCSI *s = VHOST_USER_SCSI(vdev);
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);

    vhost_dev_free_inflight(vsc->inflight);
}

static struct vhost_dev *vhost_user_scsi_get_vhost(VirtIODevice *vdev)
{
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(vdev);
    return &vsc->dev;
}

static const VMStateDescription vmstate_vhost_scsi = {
    .name = "virtio-scsi",
    .minimum_version_id = 1,
    .version_id = 1,
    .fields = (const VMStateField[]) {
        VMSTATE_VIRTIO_DEVICE,
        VMSTATE_END_OF_LIST()
    },
};

static void vhost_user_scsi_class_init(ObjectClass *klass, const void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
    FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(klass);

    device_class_set_props(dc, vhost_user_scsi_properties);
    dc->vmsd = &vmstate_vhost_scsi;
    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
    vdc->realize = vhost_user_scsi_realize;
    vdc->unrealize = vhost_user_scsi_unrealize;
    vdc->get_features = vhost_scsi_common_get_features;
    vdc->set_config = vhost_scsi_common_set_config;
    vdc->set_status = vhost_user_scsi_set_status;
    fwc->get_dev_path = vhost_scsi_common_get_fw_dev_path;
    vdc->reset = vhost_user_scsi_reset;
    vdc->get_vhost = vhost_user_scsi_get_vhost;
}

static void vhost_user_scsi_instance_init(Object *obj)
{
    VHostSCSICommon *vsc = VHOST_SCSI_COMMON(obj);

    vsc->feature_bits = user_feature_bits;

    /* Add the bootindex property for this object */
    device_add_bootindex_property(obj, &vsc->bootindex, "bootindex", NULL,
                                  DEVICE(vsc));
}

static const TypeInfo vhost_user_scsi_info = {
    .name = TYPE_VHOST_USER_SCSI,
    .parent = TYPE_VHOST_SCSI_COMMON,
    .instance_size = sizeof(VHostUserSCSI),
    .class_init = vhost_user_scsi_class_init,
    .instance_init = vhost_user_scsi_instance_init,
    .interfaces = (const InterfaceInfo[]) {
        { TYPE_FW_PATH_PROVIDER },
        { }
    },
};

static void virtio_register_types(void)
{
    type_register_static(&vhost_user_scsi_info);
}

type_init(virtio_register_types)
